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