LocIpc.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /* Copyright (c) 2017-2018, 2020-2021 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. #ifndef __LOC_IPC__
  30. #define __LOC_IPC__
  31. #include <string>
  32. #include <memory>
  33. #include <unistd.h>
  34. #include <sys/socket.h>
  35. #include <sys/un.h>
  36. #include <mutex>
  37. #include <LocThread.h>
  38. using namespace std;
  39. #ifdef NO_UNORDERED_SET_OR_MAP
  40. #include <set>
  41. #define unordered_set set
  42. #else
  43. #include <unordered_set>
  44. #endif
  45. namespace loc_util {
  46. class LocIpcRecver;
  47. class LocIpcSender;
  48. class ILocIpcListener {
  49. protected:
  50. inline virtual ~ILocIpcListener() {}
  51. public:
  52. // LocIpc client can overwrite this function to get notification
  53. // when the socket for LocIpc is ready to receive messages.
  54. inline virtual void onListenerReady() {}
  55. virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0;
  56. };
  57. class LocIpcQrtrWatcher {
  58. const unordered_set<int> mServicesToWatch;
  59. unordered_set<int> mClientsToWatch;
  60. mutex mMutex;
  61. inline bool isInWatch(const unordered_set<int>& idsToWatch, int id) {
  62. return idsToWatch.find(id) != idsToWatch.end();
  63. }
  64. protected:
  65. inline virtual ~LocIpcQrtrWatcher() {}
  66. inline LocIpcQrtrWatcher(unordered_set<int> servicesToWatch)
  67. : mServicesToWatch(servicesToWatch) {}
  68. public:
  69. enum class ServiceStatus { UP, DOWN };
  70. inline bool isServiceInWatch(int serviceId) {
  71. return isInWatch(mServicesToWatch, serviceId);
  72. }
  73. inline bool isClientInWatch(int nodeId) {
  74. lock_guard<mutex> lock(mMutex);
  75. return isInWatch(mClientsToWatch, nodeId);
  76. }
  77. inline void addClientToWatch(int nodeId) {
  78. lock_guard<mutex> lock(mMutex);
  79. mClientsToWatch.emplace(nodeId);
  80. }
  81. virtual void onServiceStatusChange(int sericeId, int instanceId, ServiceStatus status,
  82. const LocIpcSender& sender) = 0;
  83. inline virtual void onClientGone(int nodeId __unused, int portId __unused) {}
  84. inline const unordered_set<int>& getServicesToWatch() { return mServicesToWatch; }
  85. };
  86. class LocIpc {
  87. public:
  88. inline LocIpc() = default;
  89. inline virtual ~LocIpc() {
  90. stopNonBlockingListening();
  91. }
  92. static shared_ptr<LocIpcSender>
  93. getLocIpcLocalSender(const char* localSockName);
  94. static shared_ptr<LocIpcSender>
  95. getLocIpcInetUdpSender(const char* serverName, int32_t port);
  96. static shared_ptr<LocIpcSender>
  97. getLocIpcInetTcpSender(const char* serverName, int32_t port);
  98. static shared_ptr<LocIpcSender>
  99. getLocIpcQrtrSender(int service, int instance);
  100. static unique_ptr<LocIpcRecver>
  101. getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
  102. const char* localSockName);
  103. static unique_ptr<LocIpcRecver>
  104. getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
  105. const char* serverName, int32_t port);
  106. static unique_ptr<LocIpcRecver>
  107. getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
  108. const char* serverName, int32_t port);
  109. inline static unique_ptr<LocIpcRecver>
  110. getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
  111. int service, int instance) {
  112. const shared_ptr<LocIpcQrtrWatcher> qrtrWatcher = nullptr;
  113. return getLocIpcQrtrRecver(listener, service, instance, qrtrWatcher);
  114. }
  115. static unique_ptr<LocIpcRecver>
  116. getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
  117. int service, int instance,
  118. const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher);
  119. static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
  120. getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener,
  121. int instance);
  122. // Listen for new messages in current thread. Calling this funciton will
  123. // block current thread.
  124. // The listening can be stopped by calling stopBlockingListening() passing
  125. // in the same ipcRecver obj handle.
  126. static bool startBlockingListening(LocIpcRecver& ipcRecver);
  127. static void stopBlockingListening(LocIpcRecver& ipcRecver);
  128. // Create a new LocThread and listen for new messages in it.
  129. // Calling this function will return immediately and won't block current thread.
  130. // The listening can be stopped by calling stopNonBlockingListening().
  131. bool startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver);
  132. void stopNonBlockingListening();
  133. // Send out a message.
  134. // Call this function to send a message in argument data to socket in argument name.
  135. //
  136. // Argument name contains the name of the target unix socket. data contains the
  137. // message to be sent out. Convert your message to a string before calling this function.
  138. // The function will return true on success, and false on failure.
  139. static bool send(LocIpcSender& sender, const uint8_t data[],
  140. uint32_t length, int32_t msgId = -1);
  141. private:
  142. static std::string generateThreadName(const std::string& recverName);
  143. private:
  144. LocThread mThread;
  145. };
  146. /* this is only when client needs to implement Sender / Recver that are not already provided by
  147. the factor methods prvoided by LocIpc. */
  148. class LocIpcSender {
  149. protected:
  150. LocIpcSender() = default;
  151. virtual bool isOperable() const = 0;
  152. virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0;
  153. public:
  154. virtual ~LocIpcSender() = default;
  155. inline bool isSendable() const { return isOperable(); }
  156. inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const {
  157. return isSendable() && (send(data, length, msgId) > 0);
  158. }
  159. virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener __unused) {
  160. return nullptr;
  161. }
  162. inline virtual bool copyDestAddrFrom(const LocIpcSender& otherSender __unused) { return true; }
  163. };
  164. class LocIpcRecver {
  165. LocIpcSender& mIpcSender;
  166. protected:
  167. const shared_ptr<ILocIpcListener> mDataCb;
  168. inline LocIpcRecver(const shared_ptr<ILocIpcListener>& listener, LocIpcSender& sender) :
  169. mIpcSender(sender), mDataCb(listener) {}
  170. LocIpcRecver(LocIpcRecver const& recver) = delete;
  171. LocIpcRecver& operator=(LocIpcRecver const& recver) = delete;
  172. virtual ssize_t recv() const = 0;
  173. public:
  174. virtual ~LocIpcRecver() = default;
  175. inline bool recvData() const { return isRecvable() && (recv() > 0); }
  176. inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); }
  177. virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); }
  178. inline virtual unique_ptr<LocIpcSender> getLastSender() const {
  179. return nullptr;
  180. }
  181. virtual void abort() const = 0;
  182. virtual const char* getName() const = 0;
  183. };
  184. class Sock {
  185. static const char MSG_ABORT[];
  186. static const char LOC_IPC_HEAD[];
  187. const uint32_t mMaxTxSize;
  188. ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
  189. socklen_t addrlen) const;
  190. ssize_t recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
  191. int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const;
  192. public:
  193. int mSid;
  194. inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {}
  195. inline ~Sock() { close(); }
  196. inline bool isValid() const { return -1 != mSid; }
  197. ssize_t send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
  198. socklen_t addrlen) const;
  199. ssize_t recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
  200. struct sockaddr *srcAddr, socklen_t *addrlen, int sid = -1) const;
  201. ssize_t sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen);
  202. inline void close() {
  203. if (isValid()) {
  204. ::close(mSid);
  205. mSid = -1;
  206. }
  207. }
  208. };
  209. class SockRecver : public LocIpcRecver {
  210. shared_ptr<Sock> mSock;
  211. protected:
  212. inline virtual ssize_t recv() const override {
  213. return mSock->recv(*this, mDataCb, 0, nullptr, nullptr);
  214. }
  215. public:
  216. inline SockRecver(const shared_ptr<ILocIpcListener>& listener,
  217. LocIpcSender& sender, shared_ptr<Sock> sock) :
  218. LocIpcRecver(listener, sender), mSock(sock) {
  219. }
  220. inline virtual const char* getName() const override {
  221. return "SockRecver";
  222. }
  223. inline virtual void abort() const override {}
  224. };
  225. }
  226. #endif //__LOC_IPC__