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 - %u", (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,uint32_t len,int flags,const struct sockaddr * destAddr,socklen_t addrlen) const63 ssize_t Sock::send(const void *buf, uint32_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: %s, reason: %s", mSock->mSid,
168 mAddr.sun_path, strerror(errno));
169 mSock->close();
170 }
171 }
~LocIpcLocalRecver()172 inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
getName() const173 inline virtual const char* getName() const override { return mAddr.sun_path; };
abort() const174 inline virtual void abort() const override {
175 if (isSendable()) {
176 mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
177 }
178 }
179 };
180
181 class LocIpcInetSender : public LocIpcSender {
182 protected:
183 int mSockType;
184 shared_ptr<Sock> mSock;
185 const string mName;
186 sockaddr_in mAddr;
isOperable() const187 inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
send(const uint8_t data[],uint32_t length,int32_t) const188 virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
189 return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
190 }
191 public:
LocIpcInetSender(const char * name,int32_t port,int sockType)192 inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(),
193 mSockType(sockType),
194 mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))),
195 mName((nullptr == name) ? "" : name),
196 mAddr({.sin_family = AF_INET, .sin_port = htons(port),
197 .sin_addr = {htonl(INADDR_ANY)}}) {
198 if (mSock != nullptr && mSock->isValid() && nullptr != name) {
199 struct hostent* hp = gethostbyname(name);
200 if (nullptr != hp) {
201 memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
202 }
203 }
204 }
205 };
206
207 class LocIpcInetTcpSender : public LocIpcInetSender {
208 protected:
209 mutable bool mFirstTime;
210
send(const uint8_t data[],uint32_t length,int32_t) const211 virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
212 if (mFirstTime) {
213 mFirstTime = false;
214 ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
215 }
216 return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
217 }
218
219 public:
LocIpcInetTcpSender(const char * name,int32_t port)220 inline LocIpcInetTcpSender(const char* name, int32_t port) :
221 LocIpcInetSender(name, port, SOCK_STREAM),
222 mFirstTime(true) {}
223 };
224
225 class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver {
226 int32_t mPort;
227 protected:
228 virtual ssize_t recv() const = 0;
229 public:
LocIpcInetRecver(const shared_ptr<ILocIpcListener> & listener,const char * name,int32_t port,int sockType)230 inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
231 int32_t port, int sockType) :
232 LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this),
233 mPort(port) {
234 if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
235 LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
236 mSock->close();
237 }
238 }
~LocIpcInetRecver()239 inline virtual ~LocIpcInetRecver() {}
getName() const240 inline virtual const char* getName() const override { return mName.data(); };
abort() const241 inline virtual void abort() const override {
242 if (isSendable()) {
243 sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort),
244 .sin_addr = {htonl(INADDR_LOOPBACK)}};
245 mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr));
246 }
247 }
248
249 };
250
251 class LocIpcInetTcpRecver : public LocIpcInetRecver {
252 mutable int32_t mConnFd;
253 protected:
recv() const254 inline virtual ssize_t recv() const override {
255 socklen_t size = sizeof(mAddr);
256 if (-1 == mConnFd && mSock->isValid()) {
257 if (::listen(mSock->mSid, 3) < 0 ||
258 (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
259 mSock->close();
260 mConnFd = -1;
261 }
262 }
263 return mSock->recv(mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
264 }
265 public:
LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener> & listener,const char * name,int32_t port)266 inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
267 int32_t port) :
268 LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {}
~LocIpcInetTcpRecver()269 inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);}
270 };
271
272 class LocIpcInetUdpRecver : public LocIpcInetRecver {
273 protected:
recv() const274 inline virtual ssize_t recv() const override {
275 socklen_t size = sizeof(mAddr);
276 return mSock->recv(mDataCb, 0, (struct sockaddr*)&mAddr, &size);
277 }
278 public:
LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener> & listener,const char * name,int32_t port)279 inline LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
280 int32_t port) :
281 LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {}
282
~LocIpcInetUdpRecver()283 inline virtual ~LocIpcInetUdpRecver() {}
284 };
285
286
287
288 #ifdef NOT_DEFINED
289 class LocIpcQcsiSender : public LocIpcSender {
290 protected:
isOperable() const291 inline virtual bool isOperable() const override {
292 return mService != nullptr && mService->isServiceRegistered();
293 }
send(const uint8_t data[],uint32_t length,int32_t msgId) const294 inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const override {
295 return mService->sendIndToClient(msgId, data, length);
296 }
LocIpcQcsiSender(shared_ptr<QcsiService> & service)297 inline LocIpcQcsiSender(shared_ptr<QcsiService>& service) : mService(service) {}
298 public:
~LocIpcQcsi()299 inline virtual ~LocIpcQcsi() {}
300 };
301
302 class LocIpcQcsiRecver : public LocIpcQcsiSender, public LocIpcRecver {
303 protected:
recv() const304 inline virtual ssize_t recv() const override { return mService->recv(); }
305 public:
LocIpcQcsiRecver(unique_ptr<QcsiService> & service)306 inline LocIpcQcsiRecver(unique_ptr<QcsiService>& service) :
307 LocIpcQcsiSender(service), LocIpcRecver(mService->getDataCallback(), *this) {
308 }
309 // only the dele
~LocIpcQcsiRecver()310 inline ~LocIpcQcsiRecver() {}
getName() const311 inline virtual const char* getName() const override { return mService->getName().data(); };
abort() const312 inline virtual void abort() const override { if (isSendable()) mService->abort(); }
getSender()313 shared_ptr<LocIpcQcsiSender> getSender() { return make_pare<LocIpcQcsiSender>(mService); }
314 };
315 #endif
316
317 class LocIpcRunnable : public LocRunnable {
318 bool mAbortCalled;
319 LocIpc& mLocIpc;
320 unique_ptr<LocIpcRecver> mIpcRecver;
321 public:
LocIpcRunnable(LocIpc & locIpc,unique_ptr<LocIpcRecver> & ipcRecver)322 inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
323 mAbortCalled(false),
324 mLocIpc(locIpc),
325 mIpcRecver(move(ipcRecver)) {}
run()326 inline bool run() override {
327 if (mIpcRecver != nullptr) {
328 mLocIpc.startBlockingListening(*(mIpcRecver.get()));
329 if (!mAbortCalled) {
330 LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
331 }
332 }
333 // return false so the calling thread exits while loop
334 return false;
335 }
abort()336 inline void abort() {
337 mAbortCalled = true;
338 if (mIpcRecver != nullptr) {
339 mIpcRecver->abort();
340 }
341 }
342 };
343
startNonBlockingListening(unique_ptr<LocIpcRecver> & ipcRecver)344 bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
345 if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
346 std::string threadName("LocIpc-");
347 threadName.append(ipcRecver->getName());
348 mRunnable = new LocIpcRunnable(*this, ipcRecver);
349 return mThread.start(threadName.c_str(), mRunnable);
350 } else {
351 LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
352 return false;
353 }
354 }
355
startBlockingListening(LocIpcRecver & ipcRecver)356 bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
357 if (ipcRecver.isRecvable()) {
358 // inform that the socket is ready to receive message
359 ipcRecver.onListenerReady();
360 while (ipcRecver.recvData());
361 return true;
362 } else {
363 LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
364 return false;
365 }
366 }
367
stopNonBlockingListening()368 void LocIpc::stopNonBlockingListening() {
369 if (mRunnable) {
370 mRunnable->abort();
371 mRunnable = nullptr;
372 }
373 }
374
stopBlockingListening(LocIpcRecver & ipcRecver)375 void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
376 if (ipcRecver.isRecvable()) {
377 ipcRecver.abort();
378 }
379 }
380
send(LocIpcSender & sender,const uint8_t data[],uint32_t length,int32_t msgId)381 bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
382 return sender.sendData(data, length, msgId);
383 }
384
getLocIpcLocalSender(const char * localSockName)385 shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
386 return make_shared<LocIpcLocalSender>(localSockName);
387 }
getLocIpcLocalRecver(const shared_ptr<ILocIpcListener> & listener,const char * localSockName)388 unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
389 const char* localSockName) {
390 return make_unique<LocIpcLocalRecver>(listener, localSockName);
391 }
392 static void* sLibQrtrHandle = nullptr;
393 static const char* sLibQrtrName = "libloc_socket.so";
getLocIpcQrtrSender(int service,int instance)394 shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
395 typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
396 static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
397 "_ZN8loc_util22createLocIpcQrtrSenderEii");
398 return (nullptr == creator) ? nullptr : creator(service, instance);
399 }
getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener> & listener,int service,int instance)400 unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
401 int service, int instance) {
402 typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
403 static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
404 #ifdef USE_GLIB
405 "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii");
406 #else
407 "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii");
408 #endif
409 return (nullptr == creator) ? nullptr : creator(listener, service, instance);
410 }
getLocIpcInetTcpSender(const char * serverName,int32_t port)411 shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
412 return make_shared<LocIpcInetTcpSender>(serverName, port);
413 }
getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener> & listener,const char * serverName,int32_t port)414 unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
415 const char* serverName, int32_t port) {
416 return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
417 }
getLocIpcInetUdpSender(const char * serverName,int32_t port)418 shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) {
419 return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM);
420 }
getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener> & listener,const char * serverName,int32_t port)421 unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
422 const char* serverName, int32_t port) {
423 return make_unique<LocIpcInetUdpRecver>(listener, serverName, port);
424 }
425 pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener> & listener,int instance)426 LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
427 typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
428 static void* sLibEmuHandle = nullptr;
429 static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
430 "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
431 return (nullptr == creator) ?
432 make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
433 creator(listener, instance);
434 }
435
436 }
437