blob: cd99b7283f53c9ecc8f88b6a8dcb12ee87c6f1e3 [file] [log] [blame]
Michael Bestas3a0209e2023-05-04 01:15:47 +03001/* Copyright (c) 2017-2020 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
40using namespace std;
41
42namespace 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
61const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT";
62const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$";
63ssize_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}
69ssize_t Sock::recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
70 struct sockaddr *srcAddr, 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(recver, dataCb, sid, flags, srcAddr, addrlen));
77 return rtv;
78}
79ssize_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}
97ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
98 int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const {
99 std::string msg(mMaxTxSize, 0);
100 ssize_t nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen);
101 if (nBytes > 0) {
102 if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) {
103 LOC_LOGi("recvd abort msg.data %s", msg.data());
104 nBytes = 0;
105 } else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) {
106 // short message
107 msg.resize(nBytes);
108 dataCb->onReceive(msg.data(), nBytes, &recver);
109 } else {
110 // long message
111 size_t msgLen = 0;
112 sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen);
113 msg.resize(msgLen);
114 for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0);
115 msgLenReceived += nBytes) {
116 nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived,
117 flags, srcAddr, addrlen);
118 }
119 if (nBytes > 0) {
120 nBytes = msgLen;
121 dataCb->onReceive(msg.data(), nBytes, &recver);
122 }
123 }
124 }
125
126 return nBytes;
127}
128ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) {
129 return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen);
130}
131
132class LocIpcLocalSender : public LocIpcSender {
133protected:
134 shared_ptr<Sock> mSock;
135 struct sockaddr_un mAddr;
136 inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
137 inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
138 return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
139 }
140public:
141 inline LocIpcLocalSender(const char* name) : LocIpcSender(),
142 mSock(nullptr),
143 mAddr({.sun_family = AF_UNIX, {}}) {
144
145 int fd = -1;
146 if (nullptr != name) {
147 fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
148 if (fd >= 0) {
149 timeval timeout;
150 timeout.tv_sec = 2;
151 timeout.tv_usec = 0;
152 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
153 }
154 }
155 mSock.reset(new Sock(fd));
156 if (mSock != nullptr && mSock->isValid()) {
157 snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
158 }
159 }
160};
161
162class LocIpcLocalRecver : public LocIpcLocalSender, public LocIpcRecver {
163protected:
164 inline virtual ssize_t recv() const override {
165 socklen_t size = sizeof(mAddr);
166 return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
167 }
168public:
169 inline LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) :
170 LocIpcLocalSender(name), LocIpcRecver(listener, *this) {
171
172 if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) {
173 LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
174 }
175
176 umask(0157);
177 if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
178 LOC_LOGe("bind socket error. sock fd: %d: %s, reason: %s", mSock->mSid,
179 mAddr.sun_path, strerror(errno));
180 mSock->close();
181 }
182 }
183 inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
184 inline virtual const char* getName() const override { return mAddr.sun_path; };
185 inline virtual void abort() const override {
186 if (isSendable()) {
187 mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
188 }
189 }
190};
191
192class LocIpcInetSender : public LocIpcSender {
193protected:
194 int mSockType;
195 shared_ptr<Sock> mSock;
196 const string mName;
197 sockaddr_in mAddr;
198 inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
199 virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
200 return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
201 }
202public:
203 inline LocIpcInetSender(const LocIpcInetSender& sender) :
204 mSockType(sender.mSockType), mSock(sender.mSock),
205 mName(sender.mName), mAddr(sender.mAddr) {
206 }
207 inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(),
208 mSockType(sockType),
209 mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))),
210 mName((nullptr == name) ? "" : name),
211 mAddr({.sin_family = AF_INET, .sin_port = htons(port),
212 .sin_addr = {htonl(INADDR_ANY)}}) {
213 if (mSock != nullptr && mSock->isValid() && nullptr != name) {
214 struct hostent* hp = gethostbyname(name);
215 if (nullptr != hp) {
216 memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
217 }
218 }
219 }
220
221 unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
222 return make_unique<SockRecver>(listener, *this, mSock);
223 }
224};
225
226class LocIpcInetTcpSender : public LocIpcInetSender {
227protected:
228 mutable bool mFirstTime;
229
230 virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
231 if (mFirstTime) {
232 mFirstTime = false;
233 ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
234 }
235 return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
236 }
237
238public:
239 inline LocIpcInetTcpSender(const char* name, int32_t port) :
240 LocIpcInetSender(name, port, SOCK_STREAM),
241 mFirstTime(true) {}
242};
243
244class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver {
245 int32_t mPort;
246protected:
247 virtual ssize_t recv() const = 0;
248public:
249 inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
250 int32_t port, int sockType) :
251 LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this),
252 mPort(port) {
253 if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
254 LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
255 mSock->close();
256 }
257 }
258 inline virtual ~LocIpcInetRecver() {}
259 inline virtual const char* getName() const override { return mName.data(); };
260 inline virtual void abort() const override {
261 if (isSendable()) {
262 sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort),
263 .sin_addr = {htonl(INADDR_LOOPBACK)}};
264 mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr));
265 }
266 }
267 inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
268 return make_unique<LocIpcInetSender>(static_cast<const LocIpcInetSender&>(*this));
269 }
270};
271
272class LocIpcInetTcpRecver : public LocIpcInetRecver {
273 mutable int32_t mConnFd;
274protected:
275 inline virtual ssize_t recv() const override {
276 socklen_t size = sizeof(mAddr);
277 if (-1 == mConnFd && mSock->isValid()) {
278 if (::listen(mSock->mSid, 3) < 0 ||
279 (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
280 mSock->close();
281 mConnFd = -1;
282 }
283 }
284 return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
285 }
286public:
287 inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
288 int32_t port) :
289 LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {}
290 inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);}
291};
292
293class LocIpcInetUdpRecver : public LocIpcInetRecver {
294protected:
295 inline virtual ssize_t recv() const override {
296 socklen_t size = sizeof(mAddr);
297 return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
298 }
299public:
300 inline LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
301 int32_t port) :
302 LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {}
303
304 inline virtual ~LocIpcInetUdpRecver() {}
305};
306
307class LocIpcRunnable : public LocRunnable {
308 bool mAbortCalled;
309 LocIpc& mLocIpc;
310 unique_ptr<LocIpcRecver> mIpcRecver;
311public:
312 inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
313 mAbortCalled(false),
314 mLocIpc(locIpc),
me-cafebabe62bdf522023-10-05 17:15:06 +0800315 mIpcRecver(std::move(ipcRecver)) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +0300316 inline virtual bool run() override {
317 if (mIpcRecver != nullptr) {
318 mLocIpc.startBlockingListening(*(mIpcRecver.get()));
319 if (!mAbortCalled) {
320 LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
321 }
322 }
323 // return false so the calling thread exits while loop
324 return false;
325 }
326 inline virtual void interrupt() override {
327 mAbortCalled = true;
328 if (mIpcRecver != nullptr) {
329 mIpcRecver->abort();
330 }
331 }
332};
333
334bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
335 if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
336 std::string threadName("LocIpc-");
337 threadName.append(ipcRecver->getName());
338 return mThread.start(threadName.c_str(), make_shared<LocIpcRunnable>(*this, ipcRecver));
339 } else {
340 LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
341 return false;
342 }
343}
344
345bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
346 if (ipcRecver.isRecvable()) {
347 // inform that the socket is ready to receive message
348 ipcRecver.onListenerReady();
349 while (ipcRecver.recvData());
350 return true;
351 } else {
352 LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
353 return false;
354 }
355}
356
357void LocIpc::stopNonBlockingListening() {
358 mThread.stop();
359}
360
361void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
362 if (ipcRecver.isRecvable()) {
363 ipcRecver.abort();
364 }
365}
366
367bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
368 return sender.sendData(data, length, msgId);
369}
370
371shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
372 return make_shared<LocIpcLocalSender>(localSockName);
373}
374unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
375 const char* localSockName) {
376 return make_unique<LocIpcLocalRecver>(listener, localSockName);
377}
378static void* sLibQrtrHandle = nullptr;
379static const char* sLibQrtrName = "libloc_socket.so";
380shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
381 typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
382 static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
383 "_ZN8loc_util22createLocIpcQrtrSenderEii");
384 return (nullptr == creator) ? nullptr : creator(service, instance);
385}
386unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
387 int service, int instance,
388 const shared_ptr<LocIpcQrtrWatcher>& watcher) {
389 typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int,
390 const shared_ptr<LocIpcQrtrWatcher>& watcher);
391 static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
392#ifdef USE_GLIB
393 "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEiiRKS0_INS_17LocIpcQrtrWatcherEE");
394#else
395 "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEiiRKNS1_INS_17LocIpcQrtrWatcherEEE");
396#endif
397 return (nullptr == creator) ? nullptr : creator(listener, service, instance, watcher);
398}
399shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
400 return make_shared<LocIpcInetTcpSender>(serverName, port);
401}
402unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
403 const char* serverName, int32_t port) {
404 return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
405}
406shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) {
407 return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM);
408}
409unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
410 const char* serverName, int32_t port) {
411 return make_unique<LocIpcInetUdpRecver>(listener, serverName, port);
412}
413pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
414 LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
415 typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
416 static void* sLibEmuHandle = nullptr;
417 static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
418#ifdef USE_GLIB
419 "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
420 "ERKSt10shared_ptrIN8loc_util15ILocIpcListenerEEi");
421#else
422 "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
423 "ERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
424#endif
425 return (nullptr == creator) ?
426 make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
427 creator(listener, instance);
428}
429
430}