• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHRE_UTIL_SYSTEM_MESSAGE_COMMON_H_
18 #define CHRE_UTIL_SYSTEM_MESSAGE_COMMON_H_
19 
20 #include "pw_allocator/unique_ptr.h"
21 
22 #include <cstddef>
23 #include <cstdint>
24 #include <cstring>
25 
26 namespace chre::message {
27 
28 //! The ID of a MessageHub
29 using MessageHubId = uint64_t;
30 
31 //! The ID of an endpoint
32 using EndpointId = uint64_t;
33 
34 //! The ID of a session
35 using SessionId = uint16_t;
36 
37 //! An invalid MessageHub ID
38 constexpr MessageHubId MESSAGE_HUB_ID_INVALID = 0;
39 
40 //! A MessageHub ID that matches any MessageHub
41 constexpr MessageHubId MESSAGE_HUB_ID_ANY = MESSAGE_HUB_ID_INVALID;
42 
43 //! An invalid endpoint ID
44 constexpr EndpointId ENDPOINT_ID_INVALID = 0;
45 
46 //! An endpoint ID that matches any endpoint
47 constexpr EndpointId ENDPOINT_ID_ANY = ENDPOINT_ID_INVALID;
48 
49 //! An invalid session ID
50 constexpr SessionId SESSION_ID_INVALID = UINT16_MAX;
51 
52 //! Endpoint types
53 enum class EndpointType : uint8_t {
54   HOST_FRAMEWORK = 1,
55   HOST_APP = 2,
56   HOST_NATIVE = 3,
57   NANOAPP = 4,
58   GENERIC = 5,
59 };
60 
61 //! Endpoint permissions
62 //! This should match the CHRE_MESSAGE_PERMISSION_* constants.
63 enum class EndpointPermission : uint32_t {
64   NONE = 0,
65   AUDIO = 1,
66   GNSS = 1 << 1,
67   WIFI = 1 << 2,
68   WWAN = 1 << 3,
69   BLE = 1 << 4,
70 };
71 
72 //! The reason for closing a session
73 enum class Reason : uint8_t {
74   UNSPECIFIED = 0,
75   OUT_OF_MEMORY,
76   TIMEOUT,
77   OPEN_ENDPOINT_SESSION_REQUEST_REJECTED,
78   CLOSE_ENDPOINT_SESSION_REQUESTED,
79   ENDPOINT_INVALID,
80   ENDPOINT_GONE,
81   ENDPOINT_CRASHED,
82   HUB_RESET,
83   PERMISSION_DENIED,
84 };
85 
86 //! The format of an RPC message sent using a service
87 enum class RpcFormat : uint8_t {
88   CUSTOM = 0,
89   AIDL,
90   PW_RPC_PROTOBUF,
91 };
92 
93 //! Represents a single endpoint connected to a MessageHub
94 struct Endpoint {
95   MessageHubId messageHubId;
96   EndpointId endpointId;
97 
EndpointEndpoint98   Endpoint()
99       : messageHubId(MESSAGE_HUB_ID_INVALID), endpointId(ENDPOINT_ID_INVALID) {}
100 
EndpointEndpoint101   Endpoint(MessageHubId messageHubId, EndpointId endpointId)
102       : messageHubId(messageHubId),
103         endpointId(endpointId) {}
104 
105   bool operator==(const Endpoint &other) const {
106     return messageHubId == other.messageHubId && endpointId == other.endpointId;
107   }
108 
109   bool operator!=(const Endpoint &other) const {
110     return !(*this == other);
111   }
112 };
113 
114 //! Represents a session between two endpoints
115 struct Session {
116   static constexpr size_t kMaxServiceDescriptorLength = 127;
117 
SessionSession118   Session()
119       : sessionId(SESSION_ID_INVALID),
120         isActive(false),
121         hasServiceDescriptor(false) {
122     serviceDescriptor[0] = '\0';
123   }
124 
SessionSession125   Session(SessionId sessionId, Endpoint initiator, Endpoint peer,
126           const char *serviceDescriptor)
127       : sessionId(sessionId),
128         isActive(false),
129         hasServiceDescriptor(serviceDescriptor != nullptr),
130         initiator(initiator),
131         peer(peer) {
132     if (serviceDescriptor != nullptr) {
133       std::strncpy(this->serviceDescriptor, serviceDescriptor,
134                    kMaxServiceDescriptorLength);
135     } else {
136       this->serviceDescriptor[0] = '\0';
137     }
138     this->serviceDescriptor[kMaxServiceDescriptorLength] = '\0';
139   }
140 
141   SessionId sessionId;
142   bool isActive;
143   bool hasServiceDescriptor;
144   Endpoint initiator;
145   Endpoint peer;
146   char serviceDescriptor[kMaxServiceDescriptorLength + 1];
147 
148   bool operator==(const Session &other) const {
149     return sessionId == other.sessionId && initiator == other.initiator &&
150            peer == other.peer && isActive == other.isActive &&
151            hasServiceDescriptor == other.hasServiceDescriptor &&
152            (!hasServiceDescriptor ||
153             std::strncmp(serviceDescriptor, other.serviceDescriptor,
154                          kMaxServiceDescriptorLength) == 0);
155   }
156 
157   bool operator!=(const Session &other) const {
158     return !(*this == other);
159   }
160 
161   //! @return true if the two sessions are equivalent, i.e. they have the same
162   //! endpoints and service descriptor (if present), false otherwise
isEquivalentSession163   bool isEquivalent(const Session &other) const {
164     bool sameEndpoints = (initiator == other.initiator && peer == other.peer) ||
165                          (initiator == other.peer && peer == other.initiator);
166     return hasServiceDescriptor == other.hasServiceDescriptor &&
167            sameEndpoints &&
168            (!hasServiceDescriptor ||
169             std::strncmp(serviceDescriptor, other.serviceDescriptor,
170                          kMaxServiceDescriptorLength) == 0);
171   }
172 };
173 
174 //! Represents a message sent using the MessageRouter
175 struct Message {
176   Endpoint sender;
177   Endpoint recipient;
178   SessionId sessionId;
179   pw::UniquePtr<std::byte[]> data;
180   uint32_t messageType;
181   uint32_t messagePermissions;
182 
MessageMessage183   Message()
184       : sessionId(SESSION_ID_INVALID),
185         data(nullptr),
186         messageType(0),
187         messagePermissions(0) {}
188 
MessageMessage189   Message(pw::UniquePtr<std::byte[]> &&data,
190           uint32_t messageType, uint32_t messagePermissions, Session session,
191           bool sentBySessionInitiator)
192       : sender(sentBySessionInitiator ? session.initiator : session.peer),
193         recipient(sentBySessionInitiator ? session.peer : session.initiator),
194         sessionId(session.sessionId),
195         data(std::move(data)),
196         messageType(messageType),
197         messagePermissions(messagePermissions) {}
198 
199   Message(const Message &) = delete;
200   Message &operator=(const Message &) = delete;
201 
MessageMessage202   Message(Message &&other)
203       : sender(other.sender),
204         recipient(other.recipient),
205         sessionId(other.sessionId),
206         data(std::move(other.data)),
207         messageType(other.messageType),
208         messagePermissions(other.messagePermissions) {}
209 
210   Message &operator=(Message &&other) {
211     sender = other.sender;
212     recipient = other.recipient;
213     sessionId = other.sessionId;
214     data = std::move(other.data);
215     messageType = other.messageType;
216     messagePermissions = other.messagePermissions;
217     return *this;
218   }
219 };
220 
221 //! Represents information about an endpoint
222 struct EndpointInfo {
223   static constexpr size_t kMaxNameLength = 50;
224 
EndpointInfoEndpointInfo225   EndpointInfo(EndpointId id, const char *name, uint32_t version,
226                EndpointType type, uint32_t requiredPermissions)
227       : id(id),
228         version(version),
229         type(type),
230         requiredPermissions(requiredPermissions) {
231     if (name != nullptr) {
232       std::strncpy(this->name, name, kMaxNameLength);
233     } else {
234       this->name[0] = '\0';
235     }
236     this->name[kMaxNameLength] = '\0';
237   }
238 
239   EndpointId id;
240   char name[kMaxNameLength + 1];
241   uint32_t version;
242   EndpointType type;
243   uint32_t requiredPermissions;
244 
245   bool operator==(const EndpointInfo &other) const {
246     return id == other.id && version == other.version && type == other.type &&
247            requiredPermissions == other.requiredPermissions &&
248            std::strncmp(name, other.name, kMaxNameLength) == 0;
249   }
250 
251   bool operator!=(const EndpointInfo &other) const {
252     return !(*this == other);
253   }
254 };
255 
256 //! Represents information about a service provided by an endpoint.
257 struct ServiceInfo {
ServiceInfoServiceInfo258   ServiceInfo(const char *serviceDescriptor, uint32_t majorVersion,
259               uint32_t minorVersion, RpcFormat format)
260       : serviceDescriptor(serviceDescriptor),
261         majorVersion(majorVersion),
262         minorVersion(minorVersion),
263         format(format) {}
264 
265   bool operator==(const ServiceInfo &other) const {
266     if (majorVersion != other.majorVersion ||
267         minorVersion != other.minorVersion || format != other.format) {
268       return false;
269     }
270 
271     if ((serviceDescriptor == nullptr) !=
272         (other.serviceDescriptor == nullptr)) {
273       return false;
274     }
275     if (serviceDescriptor != nullptr &&
276         std::strcmp(serviceDescriptor, other.serviceDescriptor) != 0) {
277       return false;
278     }
279     return true;
280   }
281 
282   bool operator!=(const ServiceInfo &other) const {
283     return !(*this == other);
284   }
285 
286   //! The service descriptor, a null-terminated ASCII string. This must be valid
287   //! only for the lifetime of the service iteration methods in MessageRouter.
288   const char *serviceDescriptor;
289 
290   //! Version of the service.
291   uint32_t majorVersion;
292   uint32_t minorVersion;
293 
294   //! The format of the RPC messages sent using this service.
295   RpcFormat format;
296 };
297 
298 //! Represents information about a MessageHub
299 struct MessageHubInfo {
300   MessageHubId id;
301   const char *name;
302 
303   bool operator==(const MessageHubInfo &other) const {
304     if (id != other.id) {
305       return false;
306     }
307 
308     if ((name == nullptr) != (other.name == nullptr)) {
309       return false;
310     }
311     if (name != nullptr && std::strcmp(name, other.name) != 0) {
312       return false;
313     }
314     return true;
315   }
316 
317   bool operator!=(const MessageHubInfo &other) const {
318     return !(*this == other);
319   }
320 };
321 
322 }  // namespace chre::message
323 
324 #endif  // CHRE_UTIL_SYSTEM_MESSAGE_COMMON_H_
325