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