aboutsummaryrefslogtreecommitdiff
path: root/gps/utils/LocIpc.cpp
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2024-10-14 20:38:19 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2024-10-14 20:38:19 +0530
commit86a968c3f424cb70e03cccb24cabf9751f6f636d (patch)
tree5aedd15a754e4c0de8a015a4fd2c2e5c0698a22b /gps/utils/LocIpc.cpp
parentea30e6e77df9c7a651f22bcc5797b8a3f33703dc (diff)
update gps stack
Diffstat (limited to 'gps/utils/LocIpc.cpp')
-rw-r--r--gps/utils/LocIpc.cpp481
1 files changed, 329 insertions, 152 deletions
diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp
index 675664a..64d27cb 100644
--- a/gps/utils/LocIpc.cpp
+++ b/gps/utils/LocIpc.cpp
@@ -30,8 +30,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <loc_misc_utils.h>
#include <log_util.h>
-#include "LocIpc.h"
+#include <LocIpc.h>
+#include <algorithm>
+
+using namespace std;
namespace loc_util {
@@ -40,198 +46,369 @@ namespace loc_util {
#endif
#define LOG_TAG "LocSvc_LocIpc"
-#define LOC_MSG_BUF_LEN 8192
-#define LOC_MSG_HEAD "$MSGLEN$"
-#define LOC_MSG_ABORT "LocIpcMsg::ABORT"
+#define SOCK_OP_AND_LOG(buf, length, opable, rtv, exe) \
+ if (nullptr == (buf) || 0 == (length)) { \
+ LOC_LOGe("Invalid inputs: buf - %p, length - %u", (buf), (length)); \
+ } else if (!(opable)) { \
+ LOC_LOGe("Invalid object: operable - %d", (opable)); \
+ } else { \
+ rtv = (exe); \
+ if (-1 == rtv) { \
+ LOC_LOGw("failed reason: %s", strerror(errno)); \
+ } \
+ }
-class LocIpcRunnable : public LocRunnable {
-friend LocIpc;
-public:
- LocIpcRunnable(LocIpc& locIpc, const std::string& ipcName)
- : mLocIpc(locIpc), mIpcName(ipcName) {}
- bool run() override {
- if (!mLocIpc.startListeningBlocking(mIpcName)) {
- LOC_LOGe("listen to socket failed");
+const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT";
+const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$";
+ssize_t Sock::send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const {
+ ssize_t rtv = -1;
+ SOCK_OP_AND_LOG(buf, len, isValid(), rtv, sendto(buf, len, flags, destAddr, addrlen));
+ return rtv;
+}
+ssize_t Sock::recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
+ struct sockaddr *srcAddr, socklen_t *addrlen, int sid) const {
+ ssize_t rtv = -1;
+ if (-1 == sid) {
+ sid = mSid;
+ } // else it sid would be connection based socket id for recv
+ SOCK_OP_AND_LOG(dataCb.get(), mMaxTxSize, isValid(), rtv,
+ recvfrom(recver, dataCb, sid, flags, srcAddr, addrlen));
+ return rtv;
+}
+ssize_t Sock::sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const {
+ ssize_t rtv = -1;
+ if (len <= mMaxTxSize) {
+ rtv = ::sendto(mSid, buf, len, flags, destAddr, addrlen);
+ } else {
+ std::string head(LOC_IPC_HEAD + to_string(len));
+ rtv = ::sendto(mSid, head.c_str(), head.length(), flags, destAddr, addrlen);
+ if (rtv > 0) {
+ for (size_t offset = 0; offset < len && rtv > 0; offset += rtv) {
+ rtv = ::sendto(mSid, (char*)buf + offset, min(len - offset, (size_t)mMaxTxSize),
+ flags, destAddr, addrlen);
+ }
+ rtv = (rtv > 0) ? (head.length() + len) : -1;
}
-
- return false;
}
-private:
- LocIpc& mLocIpc;
- const std::string mIpcName;
-};
-
-bool LocIpc::startListeningNonBlocking(const std::string& name) {
- mRunnable = new LocIpcRunnable(*this, name);
- std::string threadName("LocIpc-");
- threadName.append(name);
- return mThread.start(threadName.c_str(), mRunnable);
+ return rtv;
}
+ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
+ int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const {
+ std::string msg(mMaxTxSize, 0);
+ ssize_t nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen);
+ if (nBytes > 0) {
+ if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) {
+ LOC_LOGi("recvd abort msg.data %s", msg.data());
+ nBytes = 0;
+ } else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) {
+ // short message
+ msg.resize(nBytes);
+ dataCb->onReceive(msg.data(), nBytes, &recver);
+ } else {
+ // long message
+ size_t msgLen = 0;
+ sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen);
+ msg.resize(msgLen);
+ for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0);
+ msgLenReceived += nBytes) {
+ nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived,
+ flags, srcAddr, addrlen);
+ }
+ if (nBytes > 0) {
+ nBytes = msgLen;
+ dataCb->onReceive(msg.data(), nBytes, &recver);
+ }
+ }
+ }
-bool LocIpc::startListeningBlocking(const std::string& name) {
+ return nBytes;
+}
+ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) {
+ return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen);
+}
- int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
- if (fd < 0) {
- LOC_LOGe("create socket error. reason:%s", strerror(errno));
- return false;
+class LocIpcLocalSender : public LocIpcSender {
+protected:
+ shared_ptr<Sock> mSock;
+ struct sockaddr_un mAddr;
+ inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
+ inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
}
+public:
+ inline LocIpcLocalSender(const char* name) : LocIpcSender(),
+ mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))),
+ mAddr({.sun_family = AF_UNIX, {}}) {
+ if (mSock != nullptr && mSock->isValid()) {
+ snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
+ }
+ }
+};
- if ((unlink(name.c_str()) < 0) && (errno != ENOENT)) {
- LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
+class LocIpcLocalRecver : public LocIpcLocalSender, public LocIpcRecver {
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
}
+public:
+ inline LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) :
+ LocIpcLocalSender(name), LocIpcRecver(listener, *this) {
- struct sockaddr_un addr = { .sun_family = AF_UNIX };
- snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name.c_str());
+ if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) {
+ LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
+ }
- umask(0157);
+ umask(0157);
+ if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
+ LOC_LOGe("bind socket error. sock fd: %d: %s, reason: %s", mSock->mSid,
+ mAddr.sun_path, strerror(errno));
+ mSock->close();
+ }
+ }
+ inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
+ inline virtual const char* getName() const override { return mAddr.sun_path; };
+ inline virtual void abort() const override {
+ if (isSendable()) {
+ mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+ }
+};
- if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- LOC_LOGe("bind socket error. reason:%s", strerror(errno));
- ::close(fd);
- fd = -1;
- return false;
+class LocIpcInetSender : public LocIpcSender {
+protected:
+ int mSockType;
+ shared_ptr<Sock> mSock;
+ const string mName;
+ sockaddr_in mAddr;
+ inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
+ virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+public:
+ inline LocIpcInetSender(const LocIpcInetSender& sender) :
+ mSockType(sender.mSockType), mSock(sender.mSock),
+ mName(sender.mName), mAddr(sender.mAddr) {
+ }
+ inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(),
+ mSockType(sockType),
+ mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))),
+ mName((nullptr == name) ? "" : name),
+ mAddr({.sin_family = AF_INET, .sin_port = htons(port),
+ .sin_addr = {htonl(INADDR_ANY)}}) {
+ if (mSock != nullptr && mSock->isValid() && nullptr != name) {
+ struct hostent* hp = gethostbyname(name);
+ if (nullptr != hp) {
+ memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
+ }
+ }
}
- mIpcFd = fd;
+ unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
+ return make_unique<SockRecver>(listener, *this, mSock);
+ }
+};
- // inform that the socket is ready to receive message
- onListenerReady();
+class LocIpcInetTcpSender : public LocIpcInetSender {
+protected:
+ mutable bool mFirstTime;
- ssize_t nBytes = 0;
- std::string msg = "";
- std::string abort = LOC_MSG_ABORT;
- while (1) {
- msg.resize(LOC_MSG_BUF_LEN);
- nBytes = ::recvfrom(mIpcFd, (void*)(msg.data()), msg.size(), 0, NULL, NULL);
- if (nBytes < 0) {
- break;
- } else if (nBytes == 0) {
- continue;
+ virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ if (mFirstTime) {
+ mFirstTime = false;
+ ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
}
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
- if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) {
- LOC_LOGi("recvd abort msg.data %s", msg.data());
- break;
+public:
+ inline LocIpcInetTcpSender(const char* name, int32_t port) :
+ LocIpcInetSender(name, port, SOCK_STREAM),
+ mFirstTime(true) {}
+};
+
+class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver {
+ int32_t mPort;
+protected:
+ virtual ssize_t recv() const = 0;
+public:
+ inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port, int sockType) :
+ LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this),
+ mPort(port) {
+ if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
+ LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
+ mSock->close();
+ }
+ }
+ inline virtual ~LocIpcInetRecver() {}
+ inline virtual const char* getName() const override { return mName.data(); };
+ inline virtual void abort() const override {
+ if (isSendable()) {
+ sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort),
+ .sin_addr = {htonl(INADDR_LOOPBACK)}};
+ mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr));
}
+ }
+ inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
+ return make_unique<LocIpcInetSender>(static_cast<const LocIpcInetSender&>(*this));
+ }
+};
- if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) {
- // short message
- msg.resize(nBytes);
- onReceive(msg);
- } else {
- // long message
- size_t msgLen = 0;
- sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen);
- msg.resize(msgLen);
- size_t msgLenReceived = 0;
- while ((msgLenReceived < msgLen) && (nBytes > 0)) {
- nBytes = recvfrom(mIpcFd, (void*)&(msg[msgLenReceived]),
- msg.size() - msgLenReceived, 0, NULL, NULL);
- msgLenReceived += nBytes;
- }
- if (nBytes > 0) {
- onReceive(msg);
- } else {
- break;
+class LocIpcInetTcpRecver : public LocIpcInetRecver {
+ mutable int32_t mConnFd;
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ if (-1 == mConnFd && mSock->isValid()) {
+ if (::listen(mSock->mSid, 3) < 0 ||
+ (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
+ mSock->close();
+ mConnFd = -1;
}
}
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
}
+public:
+ inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port) :
+ LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {}
+ inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);}
+};
- if (mStopRequested) {
- mStopRequested = false;
- return true;
- } else {
- LOC_LOGe("cannot read socket. reason:%s", strerror(errno));
- (void)::close(mIpcFd);
- mIpcFd = -1;
- return false;
+class LocIpcInetUdpRecver : public LocIpcInetRecver {
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
}
-}
-
-void LocIpc::stopListening() {
+public:
+ inline LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port) :
+ LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {}
- const char *socketName = nullptr;
- mStopRequested = true;
+ inline virtual ~LocIpcInetUdpRecver() {}
+};
- if (mRunnable) {
- std::string abort = LOC_MSG_ABORT;
- socketName = (reinterpret_cast<LocIpcRunnable *>(mRunnable))->mIpcName.c_str();
- send(socketName, abort);
- mRunnable = nullptr;
+class LocIpcRunnable : public LocRunnable {
+ bool mAbortCalled;
+ LocIpc& mLocIpc;
+ unique_ptr<LocIpcRecver> mIpcRecver;
+public:
+ inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
+ mAbortCalled(false),
+ mLocIpc(locIpc),
+ mIpcRecver(std::move(ipcRecver)) {}
+ inline bool run() override {
+ if (mIpcRecver != nullptr) {
+ mLocIpc.startBlockingListening(*(mIpcRecver.get()));
+ if (!mAbortCalled) {
+ LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
+ }
+ }
+ // return false so the calling thread exits while loop
+ return false;
}
-
- if (mIpcFd >= 0) {
- if (::close(mIpcFd)) {
- LOC_LOGe("cannot close socket:%s", strerror(errno));
+ inline void abort() {
+ mAbortCalled = true;
+ if (mIpcRecver != nullptr) {
+ mIpcRecver->abort();
}
- mIpcFd = -1;
}
+};
- //delete from the file system at the end
- if (socketName) {
- unlink(socketName);
+bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
+ if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
+ std::string threadName("LocIpc-");
+ threadName.append(ipcRecver->getName());
+ mRunnable = new LocIpcRunnable(*this, ipcRecver);
+ return mThread.start(threadName.c_str(), mRunnable);
+ } else {
+ LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
+ return false;
}
}
-bool LocIpc::send(const char name[], const std::string& data) {
- return send(name, (const uint8_t*)data.c_str(), data.length());
-}
-
-bool LocIpc::send(const char name[], const uint8_t data[], uint32_t length) {
-
- bool result = true;
- int fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
- if (fd < 0) {
- LOC_LOGe("create socket error. reason:%s", strerror(errno));
+bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
+ if (ipcRecver.isRecvable()) {
+ // inform that the socket is ready to receive message
+ ipcRecver.onListenerReady();
+ while (ipcRecver.recvData());
+ return true;
+ } else {
+ LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
return false;
}
-
- struct sockaddr_un addr = { .sun_family = AF_UNIX };
- snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name);
-
- result = sendData(fd, addr, data, length);
-
- (void)::close(fd);
- return result;
}
+void LocIpc::stopNonBlockingListening() {
+ if (mRunnable) {
+ mRunnable->abort();
+ mRunnable = nullptr;
+ }
+}
-bool LocIpc::sendData(int fd, const sockaddr_un &addr, const uint8_t data[], uint32_t length) {
+void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
+ if (ipcRecver.isRecvable()) {
+ ipcRecver.abort();
+ }
+}
- bool result = true;
+bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
+ return sender.sendData(data, length, msgId);
+}
- if (length <= LOC_MSG_BUF_LEN) {
- if (::sendto(fd, data, length, 0,
- (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- LOC_LOGe("cannot send to socket. reason:%s", strerror(errno));
- result = false;
- }
- } else {
- std::string head = LOC_MSG_HEAD;
- head.append(std::to_string(length));
- if (::sendto(fd, head.c_str(), head.length(), 0,
- (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- LOC_LOGe("cannot send to socket. reason:%s", strerror(errno));
- result = false;
- } else {
- size_t sentBytes = 0;
- while(sentBytes < length) {
- size_t partLen = length - sentBytes;
- if (partLen > LOC_MSG_BUF_LEN) {
- partLen = LOC_MSG_BUF_LEN;
- }
- ssize_t rv = ::sendto(fd, data + sentBytes, partLen, 0,
- (struct sockaddr*)&addr, sizeof(addr));
- if (rv < 0) {
- LOC_LOGe("cannot send to socket. reason:%s", strerror(errno));
- result = false;
- break;
- }
- sentBytes += rv;
- }
- }
- }
- return result;
+shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
+ return make_shared<LocIpcLocalSender>(localSockName);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* localSockName) {
+ return make_unique<LocIpcLocalRecver>(listener, localSockName);
+}
+static void* sLibQrtrHandle = nullptr;
+static const char* sLibQrtrName = "libloc_socket.so";
+shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
+ typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
+ "_ZN8loc_util22createLocIpcQrtrSenderEii");
+ return (nullptr == creator) ? nullptr : creator(service, instance);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
+ int service, int instance) {
+ typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
+#ifdef USE_GLIB
+ "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii");
+#else
+ "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii");
+#endif
+ return (nullptr == creator) ? nullptr : creator(listener, service, instance);
+}
+shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
+ return make_shared<LocIpcInetTcpSender>(serverName, port);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port) {
+ return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
+}
+shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) {
+ return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port) {
+ return make_unique<LocIpcInetUdpRecver>(listener, serverName, port);
+}
+pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
+ LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
+ typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
+ static void* sLibEmuHandle = nullptr;
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
+ "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
+ return (nullptr == creator) ?
+ make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
+ creator(listener, instance);
}
}