1 /* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation, nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <loc_misc_utils.h>
36 #include <log_util.h>
37 #include <LocIpc.h>
38 #include <algorithm>
39 
40 using namespace std;
41 
42 namespace loc_util {
43 
44 #ifdef LOG_TAG
45 #undef LOG_TAG
46 #endif
47 #define LOG_TAG "LocSvc_LocIpc"
48 
49 #define SOCK_OP_AND_LOG(buf, length, opable, rtv, exe)  \
50     if (nullptr == (buf) || 0 == (length)) { \
51         LOC_LOGe("Invalid inputs: buf - %p, length - %d", (buf), (length)); \
52     } else if (!(opable)) {                                             \
53         LOC_LOGe("Invalid object: operable - %d", (opable));            \
54     } else { \
55         rtv = (exe); \
56         if (-1 == rtv) { \
57             LOC_LOGw("failed reason: %s", strerror(errno)); \
58         } \
59     }
60 
61 const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT";
62 const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$";
send(const void * buf,size_t len,int flags,const struct sockaddr * destAddr,socklen_t addrlen) const63 ssize_t Sock::send(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
64                           socklen_t addrlen) const {
65     ssize_t rtv = -1;
66     SOCK_OP_AND_LOG(buf, len, isValid(), rtv, sendto(buf, len, flags, destAddr, addrlen));
67     return rtv;
68 }
recv(const shared_ptr<ILocIpcListener> & dataCb,int flags,struct sockaddr * srcAddr,socklen_t * addrlen,int sid) const69 ssize_t Sock::recv(const shared_ptr<ILocIpcListener>& dataCb, int flags, struct sockaddr *srcAddr,
70                            socklen_t *addrlen, int sid) const {
71     ssize_t rtv = -1;
72     if (-1 == sid) {
73         sid = mSid;
74     } // else it sid would be connection based socket id for recv
75     SOCK_OP_AND_LOG(dataCb.get(), mMaxTxSize, isValid(), rtv,
76                     recvfrom(dataCb, sid, flags, srcAddr, addrlen));
77     return rtv;
78 }
sendto(const void * buf,size_t len,int flags,const struct sockaddr * destAddr,socklen_t addrlen) const79 ssize_t Sock::sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
80                             socklen_t addrlen) const {
81     ssize_t rtv = -1;
82     if (len <= mMaxTxSize) {
83         rtv = ::sendto(mSid, buf, len, flags, destAddr, addrlen);
84     } else {
85         std::string head(LOC_IPC_HEAD + to_string(len));
86         rtv = ::sendto(mSid, head.c_str(), head.length(), flags, destAddr, addrlen);
87         if (rtv > 0) {
88             for (size_t offset = 0; offset < len && rtv > 0; offset += rtv) {
89                 rtv = ::sendto(mSid, (char*)buf + offset, min(len - offset, (size_t)mMaxTxSize),
90                                flags, destAddr, addrlen);
91             }
92             rtv = (rtv > 0) ? (head.length() + len) : -1;
93         }
94     }
95     return rtv;
96 }
recvfrom(const shared_ptr<ILocIpcListener> & dataCb,int sid,int flags,struct sockaddr * srcAddr,socklen_t * addrlen) const97 ssize_t Sock::recvfrom(const shared_ptr<ILocIpcListener>& dataCb, int sid, int flags,
98                        struct sockaddr *srcAddr, socklen_t *addrlen) const  {
99     ssize_t nBytes = -1;
100     std::string msg(mMaxTxSize, 0);
101 
102     if ((nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen)) > 0) {
103         if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) {
104             LOC_LOGi("recvd abort msg.data %s", msg.data());
105             nBytes = 0;
106         } else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) {
107             // short message
108             msg.resize(nBytes);
109             dataCb->onReceive(msg.data(), nBytes);
110         } else {
111             // long message
112             size_t msgLen = 0;
113             sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen);
114             msg.resize(msgLen);
115             for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0);
116                  msgLenReceived += nBytes) {
117                 nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived,
118                                     flags, srcAddr, addrlen);
119             }
120             if (nBytes > 0) {
121                 nBytes = msgLen;
122                 dataCb->onReceive(msg.data(), nBytes);
123             }
124         }
125     }
126 
127     return nBytes;
128 }
sendAbort(int flags,const struct sockaddr * destAddr,socklen_t addrlen)129 ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) {
130     return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen);
131 }
132 
133 class LocIpcLocalSender : public LocIpcSender {
134 protected:
135     shared_ptr<Sock> mSock;
136     struct sockaddr_un mAddr;
isOperable() const137     inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
send(const uint8_t data[],uint32_t length,int32_t) const138     inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
139         return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
140     }
141 public:
LocIpcLocalSender(const char * name)142     inline LocIpcLocalSender(const char* name) : LocIpcSender(),
143             mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))),
144             mAddr({.sun_family = AF_UNIX, {}}) {
145         if (mSock != nullptr && mSock->isValid()) {
146             snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
147         }
148     }
149 };
150 
151 class LocIpcLocalRecver : public LocIpcLocalSender, public LocIpcRecver {
152 protected:
recv() const153     inline virtual ssize_t recv() const override {
154         socklen_t size = sizeof(mAddr);
155         return mSock->recv(mDataCb, 0, (struct sockaddr*)&mAddr, &size);
156     }
157 public:
LocIpcLocalRecver(const shared_ptr<ILocIpcListener> & listener,const char * name)158     inline LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) :
159             LocIpcLocalSender(name), LocIpcRecver(listener, *this) {
160 
161         if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) {
162             LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
163         }
164 
165         umask(0157);
166         if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
167             LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
168             mSock->close();
169         }
170     }
~LocIpcLocalRecver()171     inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
getName() const172     inline virtual const char* getName() const override { return mAddr.sun_path; };
abort() const173     inline virtual void abort() const override {
174         if (isSendable()) {
175             mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
176         }
177     }
178 };
179 
180 class LocIpcInetTcpSender : public LocIpcSender {
181 protected:
182     shared_ptr<Sock> mSock;
183     const string mName;
184     sockaddr_in mAddr;
185     mutable bool mFirstTime;
isOperable() const186     inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
send(const uint8_t data[],uint32_t length,int32_t) const187     inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
188         if (mFirstTime) {
189             mFirstTime = false;
190             ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
191         }
192         return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
193     }
194 public:
LocIpcInetTcpSender(const char * name,int32_t port)195     inline LocIpcInetTcpSender(const char* name, int32_t port) : LocIpcSender(),
196             mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, SOCK_STREAM, 0)))),
197             mName((nullptr == name) ? "" : name),
198             mAddr({.sin_family=AF_INET, .sin_port=htons(port), .sin_addr={htonl(INADDR_ANY)}}),
199             mFirstTime(true) {
200         if (mSock != nullptr && mSock->isValid() && nullptr != name) {
201             struct hostent* hp = gethostbyname(name);
202             if (nullptr != hp) {
203                 memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
204             }
205         }
206     }
207 };
208 
209 class LocIpcInetTcpRecver : public LocIpcInetTcpSender, public LocIpcRecver {
210     mutable int32_t mConnFd;
211 protected:
recv() const212     inline virtual ssize_t recv() const override {
213         socklen_t size = sizeof(mAddr);
214         if (-1 == mConnFd && mSock->isValid()) {
215             if (::listen(mSock->mSid, 3) < 0 ||
216                 (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
217                 mSock->close();
218                 mConnFd = -1;
219             }
220         }
221         return mSock->recv(mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
222     }
223 public:
LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener> & listener,const char * name,int32_t port)224     inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
225                                int32_t port) :
226             LocIpcInetTcpSender(name, port), LocIpcRecver(listener, *this), mConnFd(-1) {
227         if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
228             LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
229             mSock->close();
230         }
231     }
~LocIpcInetTcpRecver()232     inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd); }
getName() const233     inline virtual const char* getName() const override { return mName.data(); };
abort() const234     inline virtual void abort() const override {
235         if (isSendable()) {
236             mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
237         }
238     }
239 };
240 
241 #ifdef NOT_DEFINED
242 class LocIpcQcsiSender : public LocIpcSender {
243 protected:
isOperable() const244     inline virtual bool isOperable() const override {
245         return mService != nullptr && mService->isServiceRegistered();
246     }
send(const uint8_t data[],uint32_t length,int32_t msgId) const247     inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const override {
248         return mService->sendIndToClient(msgId, data, length);
249     }
LocIpcQcsiSender(shared_ptr<QcsiService> & service)250     inline LocIpcQcsiSender(shared_ptr<QcsiService>& service) : mService(service) {}
251 public:
~LocIpcQcsi()252     inline virtual ~LocIpcQcsi() {}
253 };
254 
255 class LocIpcQcsiRecver : public LocIpcQcsiSender, public LocIpcRecver {
256 protected:
recv() const257     inline virtual ssize_t recv() const override { return mService->recv(); }
258 public:
LocIpcQcsiRecver(unique_ptr<QcsiService> & service)259     inline LocIpcQcsiRecver(unique_ptr<QcsiService>& service) :
260             LocIpcQcsiSender(service), LocIpcRecver(mService->getDataCallback(), *this) {
261     }
262     // only the dele
~LocIpcQcsiRecver()263     inline ~LocIpcQcsiRecver() {}
getName() const264     inline virtual const char* getName() const override { return mService->getName().data(); };
abort() const265     inline virtual void abort() const override { if (isSendable()) mService->abort(); }
getSender()266     shared_ptr<LocIpcQcsiSender> getSender() { return make_pare<LocIpcQcsiSender>(mService); }
267 };
268 #endif
269 
270 class LocIpcRunnable : public LocRunnable {
271     bool mAbortCalled;
272     LocIpc& mLocIpc;
273     unique_ptr<LocIpcRecver> mIpcRecver;
274 public:
LocIpcRunnable(LocIpc & locIpc,unique_ptr<LocIpcRecver> & ipcRecver)275     inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
276             mAbortCalled(false),
277             mLocIpc(locIpc),
278             mIpcRecver(move(ipcRecver)) {}
run()279     inline bool run() override {
280         if (mIpcRecver != nullptr) {
281             mLocIpc.startBlockingListening(*(mIpcRecver.get()));
282             if (!mAbortCalled) {
283                 LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
284             }
285         }
286         // return false so the calling thread exits while loop
287         return false;
288     }
abort()289     inline void abort() {
290         mAbortCalled = true;
291         if (mIpcRecver != nullptr) {
292             mIpcRecver->abort();
293         }
294     }
295 };
296 
startNonBlockingListening(unique_ptr<LocIpcRecver> & ipcRecver)297 bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
298     if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
299         std::string threadName("LocIpc-");
300         threadName.append(ipcRecver->getName());
301         mRunnable = new LocIpcRunnable(*this, ipcRecver);
302         return mThread.start(threadName.c_str(), mRunnable);
303     } else {
304         LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
305         return false;
306     }
307 }
308 
startBlockingListening(LocIpcRecver & ipcRecver)309 bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
310     if (ipcRecver.isRecvable()) {
311         // inform that the socket is ready to receive message
312         ipcRecver.onListenerReady();
313         while (ipcRecver.recvData());
314         return true;
315     } else  {
316         LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
317         return false;
318     }
319 }
320 
stopNonBlockingListening()321 void LocIpc::stopNonBlockingListening() {
322     if (mRunnable) {
323         mRunnable->abort();
324         mRunnable = nullptr;
325     }
326 }
327 
stopBlockingListening(LocIpcRecver & ipcRecver)328 void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
329     if (ipcRecver.isRecvable()) {
330         ipcRecver.abort();
331     }
332 }
333 
send(LocIpcSender & sender,const uint8_t data[],uint32_t length,int32_t msgId)334 bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
335     return sender.sendData(data, length, msgId);
336 }
337 
getLocIpcLocalSender(const char * localSockName)338 shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
339     return make_shared<LocIpcLocalSender>(localSockName);
340 }
getLocIpcLocalRecver(const shared_ptr<ILocIpcListener> & listener,const char * localSockName)341 unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
342                                                       const char* localSockName) {
343     return make_unique<LocIpcLocalRecver>(listener, localSockName);
344 }
345 static void* sLibQrtrHandle = nullptr;
346 static const char* sLibQrtrName = "libloc_socket.so";
getLocIpcQrtrSender(int service,int instance)347 shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
348     typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
349     static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
350             "_ZN8loc_util22createLocIpcQrtrSenderEii");
351     return (nullptr == creator) ? nullptr : creator(service, instance);
352 }
getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener> & listener,int service,int instance)353 unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
354                                                      int service, int instance) {
355     typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
356     static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
357             "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii");
358     return (nullptr == creator) ? nullptr : creator(listener, service, instance);
359 }
getLocIpcQsockSender(int service,int instance)360 shared_ptr<LocIpcSender> LocIpc::getLocIpcQsockSender(int service, int instance) {
361     typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
362     static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
363             "_ZN8loc_util23createLocIpcQsockSenderEii");
364     return (nullptr == creator) ? nullptr : creator(service, instance);
365 }
getLocIpcQsockRecver(const shared_ptr<ILocIpcListener> & listener,int service,int instance)366 unique_ptr<LocIpcRecver> LocIpc::getLocIpcQsockRecver(const shared_ptr<ILocIpcListener>& listener,
367                                                       int service, int instance) {
368     typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
369     static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
370             "_ZN8loc_util23createLocIpcQsockRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii");
371     return (nullptr == creator) ? nullptr : creator(listener, service, instance);
372 }
getLocIpcInetTcpSender(const char * serverName,int32_t port)373 shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
374     return make_shared<LocIpcInetTcpSender>(serverName, port);
375 }
getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener> & listener,const char * serverName,int32_t port)376 unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
377                                                         const char* serverName, int32_t port) {
378     return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
379 }
380 pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener> & listener,int instance)381         LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
382     typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
383     static void* sLibEmuHandle = nullptr;
384     static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
385             "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
386     return (nullptr == creator) ?
387             make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
388             creator(listener, instance);
389 }
390 
391 }
392