blob: 40ed5a3d3601217a9d66637b7065788aec318151 [file] [log] [blame]
Michael Bestas3a0209e2023-05-04 01:15:47 +03001/* 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
42using namespace std;
43
44namespace loc_util {
45
46class LocIpcRecver;
47class LocIpcSender;
48
49class ILocIpcListener {
50protected:
51 inline virtual ~ILocIpcListener() {}
52public:
53 // LocIpc client can overwrite this function to get notification
54 // when the socket for LocIpc is ready to receive messages.
55 inline virtual void onListenerReady() {}
56 virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0;
57};
58
59class LocIpcQrtrWatcher {
60 const unordered_set<int> mServicesToWatch;
61 unordered_set<int> mClientsToWatch;
62 mutex mMutex;
63 inline bool isInWatch(const unordered_set<int>& idsToWatch, int id) {
64 return idsToWatch.find(id) != idsToWatch.end();
65 }
66protected:
67 inline virtual ~LocIpcQrtrWatcher() {}
68 inline LocIpcQrtrWatcher(unordered_set<int> servicesToWatch)
69 : mServicesToWatch(servicesToWatch) {}
70public:
71 enum class ServiceStatus { UP, DOWN };
72 inline bool isServiceInWatch(int serviceId) {
73 return isInWatch(mServicesToWatch, serviceId);
74 }
75 inline bool isClientInWatch(int nodeId) {
76 lock_guard<mutex> lock(mMutex);
77 return isInWatch(mClientsToWatch, nodeId);
78 }
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;
Michael Bestasdb7342c2021-01-06 19:23:51 +020085 inline virtual void onClientGone(int nodeId __unused, int portId __unused) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +030086 inline const unordered_set<int>& getServicesToWatch() { return mServicesToWatch; }
87};
88
89class LocIpc {
90public:
91 inline LocIpc() = default;
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>
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
151private:
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
158class LocIpcSender {
159protected:
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;
163public:
164 virtual ~LocIpcSender() = default;
165 inline bool isSendable() const { return isOperable(); }
166 inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const {
167 return isSendable() && (send(data, length, msgId) > 0);
168 }
Michael Bestasdb7342c2021-01-06 19:23:51 +0200169 virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener __unused) {
Michael Bestas3a0209e2023-05-04 01:15:47 +0300170 return nullptr;
171 }
Michael Bestasdb7342c2021-01-06 19:23:51 +0200172 inline virtual void copyDestAddrFrom(const LocIpcSender& otherSender __unused) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +0300173};
174
175class LocIpcRecver {
176 LocIpcSender& mIpcSender;
177protected:
178 const shared_ptr<ILocIpcListener> mDataCb;
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;
184public:
185 virtual ~LocIpcRecver() = default;
186 inline bool recvData() const { return isRecvable() && (recv() > 0); }
187 inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); }
188 virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); }
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
196class 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;
204public:
205 int mSid;
206 inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {}
207 inline ~Sock() { close(); }
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);
214 inline void close() {
215 if (isValid()) {
216 ::close(mSid);
217 mSid = -1;
218 }
219 }
220};
221
222class SockRecver : public LocIpcRecver {
223 shared_ptr<Sock> mSock;
224protected:
225 inline virtual ssize_t recv() const override {
226 return mSock->recv(*this, mDataCb, 0, nullptr, nullptr);
227 }
228public:
229 inline SockRecver(const shared_ptr<ILocIpcListener>& listener,
230 LocIpcSender& sender, shared_ptr<Sock> sock) :
231 LocIpcRecver(listener, sender), mSock(sock) {
232 }
233 inline virtual const char* getName() const override {
234 return "SockRecver";
235 }
236 inline virtual void abort() const override {}
237};
238
239}
240
241#endif //__LOC_IPC__