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 #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 <LocThread.h> 39 40 using namespace std; 41 42 namespace loc_util { 43 44 45 class LocIpcRecver; 46 class LocIpcSender; 47 class LocIpcRunnable; 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 length)= 0; 57 }; 58 59 60 class LocIpc { 61 public: LocIpc()62 inline LocIpc() : mRunnable(nullptr) {} ~LocIpc()63 inline virtual ~LocIpc() { 64 stopNonBlockingListening(); 65 } 66 67 static shared_ptr<LocIpcSender> 68 getLocIpcLocalSender(const char* localSockName); 69 static shared_ptr<LocIpcSender> 70 getLocIpcInetUdpSender(const char* serverName, int32_t port); 71 static shared_ptr<LocIpcSender> 72 getLocIpcInetTcpSender(const char* serverName, int32_t port); 73 static shared_ptr<LocIpcSender> 74 getLocIpcQrtrSender(int service, int instance); 75 76 static unique_ptr<LocIpcRecver> 77 getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, 78 const char* localSockName); 79 static unique_ptr<LocIpcRecver> 80 getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, 81 const char* serverName, int32_t port); 82 static unique_ptr<LocIpcRecver> 83 getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, 84 const char* serverName, int32_t port); 85 static unique_ptr<LocIpcRecver> 86 getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener, 87 int service, int instance); 88 89 static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> 90 getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, 91 int instance); 92 93 // Listen for new messages in current thread. Calling this funciton will 94 // block current thread. 95 // The listening can be stopped by calling stopBlockingListening() passing 96 // in the same ipcRecver obj handle. 97 static bool startBlockingListening(LocIpcRecver& ipcRecver); 98 static void stopBlockingListening(LocIpcRecver& ipcRecver); 99 100 // Create a new LocThread and listen for new messages in it. 101 // Calling this function will return immediately and won't block current thread. 102 // The listening can be stopped by calling stopNonBlockingListening(). 103 bool startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver); 104 void stopNonBlockingListening(); 105 106 // Send out a message. 107 // Call this function to send a message in argument data to socket in argument name. 108 // 109 // Argument name contains the name of the target unix socket. data contains the 110 // message to be sent out. Convert your message to a string before calling this function. 111 // The function will return true on success, and false on failure. 112 static bool send(LocIpcSender& sender, const uint8_t data[], 113 uint32_t length, int32_t msgId = -1); 114 115 private: 116 LocThread mThread; 117 LocIpcRunnable *mRunnable; 118 }; 119 120 /* this is only when client needs to implement Sender / Recver that are not already provided by 121 the factor methods prvoided by LocIpc. */ 122 123 class LocIpcSender { 124 protected: 125 LocIpcSender() = default; 126 virtual ~LocIpcSender() = default; 127 virtual bool isOperable() const = 0; 128 virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0; 129 public: informRecverRestarted()130 virtual void informRecverRestarted() {} isSendable()131 inline bool isSendable() const { return isOperable(); } sendData(const uint8_t data[],uint32_t length,int32_t msgId)132 inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const { 133 return isSendable() && (send(data, length, msgId) > 0); 134 } 135 }; 136 137 class LocIpcRecver { 138 LocIpcSender& mIpcSender; 139 protected: 140 const shared_ptr<ILocIpcListener> mDataCb; LocIpcRecver(const shared_ptr<ILocIpcListener> & listener,LocIpcSender & sender)141 inline LocIpcRecver(const shared_ptr<ILocIpcListener>& listener, LocIpcSender& sender) : 142 mIpcSender(sender), mDataCb(listener) {} 143 LocIpcRecver(LocIpcRecver const& recver) = delete; 144 LocIpcRecver& operator=(LocIpcRecver const& recver) = delete; 145 virtual ssize_t recv() const = 0; 146 public: 147 virtual ~LocIpcRecver() = default; recvData()148 inline bool recvData() const { return isRecvable() && (recv() > 0); } isRecvable()149 inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); } onListenerReady()150 virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); } 151 virtual void abort() const = 0; 152 virtual const char* getName() const = 0; 153 }; 154 155 class Sock { 156 static const char MSG_ABORT[]; 157 static const char LOC_IPC_HEAD[]; 158 const uint32_t mMaxTxSize; 159 ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr, 160 socklen_t addrlen) const; 161 ssize_t recvfrom(const shared_ptr<ILocIpcListener>& dataCb, int sid, int flags, 162 struct sockaddr *srcAddr, socklen_t *addrlen) const; 163 public: 164 int mSid; mMaxTxSize(maxTxSize)165 inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {} ~Sock()166 inline ~Sock() { close(); } isValid()167 inline bool isValid() const { return -1 != mSid; } 168 ssize_t send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr, 169 socklen_t addrlen) const; 170 ssize_t recv(const shared_ptr<ILocIpcListener>& dataCb, int flags, struct sockaddr *srcAddr, 171 socklen_t *addrlen, int sid = -1) const; 172 ssize_t sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen); close()173 inline void close() { 174 if (isValid()) { 175 ::close(mSid); 176 mSid = -1; 177 } 178 } 179 }; 180 181 } 182 183 #endif //__LOC_IPC__ 184