1 /* 2 * Copyright (C) 2020 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 CHPP_APP_H_ 18 #define CHPP_APP_H_ 19 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 24 #include "chpp/condition_variable.h" 25 #include "chpp/macros.h" 26 #include "chpp/transport.h" 27 #include "chre_api/chre/common.h" 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 /************************************************ 34 * Public Definitions 35 ***********************************************/ 36 37 /** 38 * Allocates a variable-length response message of a specific type. 39 * 40 * @param requestHeader request header, as per chppAllocResponse(). 41 * @param type Type of response which includes an arrayed member. 42 * @param count number of items in the array of arrayField. 43 * @param arrayField The arrayed member field. 44 * 45 * @return Pointer to allocated memory. 46 */ 47 #define chppAllocResponseTypedArray(requestHeader, type, count, arrayField) \ 48 (type *)chppAllocResponse( \ 49 requestHeader, \ 50 sizeof(type) + (count)*sizeof_member(type, arrayField[0])) 51 52 /** 53 * Allocates a response message of a specific type and its corresponding length. 54 * 55 * @param requestHeader request header, as per chppAllocResponse(). 56 * @param type Type of response. 57 * 58 * @return Pointer to allocated memory. 59 */ 60 #define chppAllocResponseFixed(requestHeader, type) \ 61 (type *)chppAllocResponse(requestHeader, sizeof(type)) 62 63 /** 64 * Maximum number of services that can be registered by CHPP (not including 65 * predefined services), if not defined by the build system. 66 */ 67 #ifndef CHPP_MAX_REGISTERED_SERVICES 68 #define CHPP_MAX_REGISTERED_SERVICES 1 69 #endif 70 71 /** 72 * Maximum number of clients that can be registered by CHPP (not including 73 * predefined clients), if not defined by the build system. 74 */ 75 #ifndef CHPP_MAX_REGISTERED_CLIENTS 76 #define CHPP_MAX_REGISTERED_CLIENTS 1 77 #endif 78 79 /** 80 * Maximum number of services that can be discovered by CHPP (not including 81 * predefined services), if not defined by the build system. 82 */ 83 #ifndef CHPP_MAX_DISCOVERED_SERVICES 84 #define CHPP_MAX_DISCOVERED_SERVICES \ 85 MAX(CHPP_MAX_REGISTERED_SERVICES, CHPP_MAX_REGISTERED_CLIENTS) 86 #endif 87 88 #define CHPP_REQUEST_TIMEOUT_INFINITE CHPP_TIME_MAX 89 90 #if defined(CHPP_REQUEST_TIMEOUT_DEFAULT) && \ 91 defined(CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT) 92 // Build systems should prefer to only set CHPP_REQUEST_TIMEOUT_DEFAULT 93 #error Can not set both CHPP_REQUEST_TIMEOUT_DEFAULT and CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT 94 #endif 95 96 // For backwards compatibility with vendor build systems 97 #ifdef CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT 98 #define CHPP_REQUEST_TIMEOUT_DEFAULT CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT 99 #undef CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT 100 #endif 101 102 // If not customized in the build, we default to CHRE expectations 103 #ifndef CHPP_REQUEST_TIMEOUT_DEFAULT 104 #define CHPP_REQUEST_TIMEOUT_DEFAULT CHRE_ASYNC_RESULT_TIMEOUT_NS 105 #endif 106 107 /** 108 * Default value for reserved fields. 109 */ 110 #define CHPP_RESERVED 0 111 112 /** 113 * Client index number when there is no matching client 114 */ 115 #define CHPP_CLIENT_INDEX_NONE 0xff 116 117 /** 118 * App layer command at initialization. 119 */ 120 #define CHPP_APP_COMMAND_NONE 0 121 122 /** 123 * Type of endpoint (either client or service) 124 */ 125 enum ChppEndpointType { 126 CHPP_ENDPOINT_CLIENT = 0, 127 CHPP_ENDPOINT_SERVICE = 1, 128 }; 129 130 /** 131 * Handle Numbers in ChppAppHeader 132 */ 133 enum ChppHandleNumber { 134 //! Handleless communication 135 CHPP_HANDLE_NONE = 0x00, 136 137 //! Loopback Service 138 CHPP_HANDLE_LOOPBACK = 0x01, 139 140 //! Time Service 141 CHPP_HANDLE_TIMESYNC = 0x02, 142 143 //! Discovery Service 144 CHPP_HANDLE_DISCOVERY = 0x0F, 145 146 //! Negotiated Services (starting from this offset) 147 CHPP_HANDLE_NEGOTIATED_RANGE_START = 0x10, 148 }; 149 150 /** 151 * Message Types as used in ChppAppHeader 152 */ 153 #define CHPP_APP_MASK_MESSAGE_TYPE LEAST_SIGNIFICANT_NIBBLE 154 #define CHPP_APP_GET_MESSAGE_TYPE(value) \ 155 ((enum ChppMessageType)( \ 156 (value)&CHPP_APP_MASK_MESSAGE_TYPE)) // TODO: Consider checking if this 157 // maps into a valid enum 158 enum ChppMessageType { 159 //! Request from client. Needs response from service. 160 CHPP_MESSAGE_TYPE_CLIENT_REQUEST = 0, 161 162 //! Response from service (with the same Command and Transaction ID as the 163 //! client request). 164 CHPP_MESSAGE_TYPE_SERVICE_RESPONSE = 1, 165 166 //! Notification from client. Service shall not respond. 167 CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION = 2, 168 169 //! Notification from service. Client shall not respond. 170 CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION = 3, 171 172 //! Request from service. Needs response from client. 173 CHPP_MESSAGE_TYPE_SERVICE_REQUEST = 4, 174 175 //! Response from client (with the same Command and Transaction ID as the 176 //! service request). 177 CHPP_MESSAGE_TYPE_CLIENT_RESPONSE = 5, 178 }; 179 180 /** 181 * Error codes used by the app layer / clients / services. 182 */ 183 enum ChppAppErrorCode { 184 //! Success (no error) 185 CHPP_APP_ERROR_NONE = 0, 186 //! Invalid command 187 CHPP_APP_ERROR_INVALID_COMMAND = 1, 188 //! Invalid argument(s) 189 CHPP_APP_ERROR_INVALID_ARG = 2, 190 //! Busy 191 CHPP_APP_ERROR_BUSY = 3, 192 //! Out of memory 193 CHPP_APP_ERROR_OOM = 4, 194 //! Feature not supported 195 CHPP_APP_ERROR_UNSUPPORTED = 5, 196 //! Timeout 197 CHPP_APP_ERROR_TIMEOUT = 6, 198 //! Functionality disabled (e.g. per user configuration) 199 CHPP_APP_ERROR_DISABLED = 7, 200 //! Rate limit exceeded (try again later) 201 CHPP_APP_ERROR_RATELIMITED = 8, 202 //! Function in use / blocked by another entity (e.g. the AP) 203 CHPP_APP_ERROR_BLOCKED = 9, 204 //! Invalid length 205 CHPP_APP_ERROR_INVALID_LENGTH = 10, 206 //! CHPP Not Ready 207 CHPP_APP_ERROR_NOT_READY = 11, 208 //! Error outside of CHPP (e.g. PAL API) 209 CHPP_APP_ERROR_BEYOND_CHPP = 12, 210 //! Response not matching a pending request 211 CHPP_APP_ERROR_UNEXPECTED_RESPONSE = 13, 212 //! Conversion failed 213 CHPP_APP_ERROR_CONVERSION_FAILED = 14, 214 //! Unspecified failure 215 CHPP_APP_ERROR_UNSPECIFIED = 255 216 }; 217 218 /** 219 * Open status for clients / services. 220 */ 221 enum ChppOpenState { 222 CHPP_OPEN_STATE_CLOSED = 0, // Closed 223 CHPP_OPEN_STATE_OPENING = 1, // Enables the open request to pass 224 CHPP_OPEN_STATE_WAITING_TO_OPEN = 2, // Waiting for open response 225 CHPP_OPEN_STATE_OPENED = 3, // Opened 226 }; 227 228 /** 229 * CHPP Application Layer header 230 */ 231 CHPP_PACKED_START 232 struct ChppAppHeader { 233 //! Service Handle 234 uint8_t handle; 235 236 //! Most significant nibble (MSN): Reserved 237 //! Least significant nibble (LSN): Message Type from enum ChppMessageType 238 uint8_t type; 239 240 //! Transaction ID 241 uint8_t transaction; 242 243 //! Error if any, from enum ChppAppErrorCode 244 uint8_t error; 245 246 //! Command 247 uint16_t command; 248 249 } CHPP_PACKED_ATTR; 250 CHPP_PACKED_END 251 252 /** 253 * Function type that dispatches incoming datagrams for any client or service. 254 * 255 * The buffer is freed shortly after the function returns. 256 * User code must make a copy for later processing if needed. 257 */ 258 typedef enum ChppAppErrorCode(ChppDispatchFunction)(void *context, uint8_t *buf, 259 size_t len); 260 261 /** 262 * Function type that initializes a client and assigns it its handle number 263 */ 264 typedef bool(ChppClientInitFunction)(void *context, uint8_t handle, 265 struct ChppVersion serviceVersion); 266 267 /** 268 * Function type that deinitializes a client. 269 */ 270 typedef void(ChppClientDeinitFunction)(void *context); 271 272 /** 273 * Function type that dispatches a reset notification to any client or service 274 */ 275 typedef void(ChppNotifierFunction)(void *context); 276 277 /** 278 * Length of a service UUID and its human-readable printed form in bytes 279 */ 280 #define CHPP_SERVICE_UUID_LEN 16 281 #define CHPP_SERVICE_UUID_STRING_LEN (16 * 2 + 4 + 1) 282 283 /** 284 * Length of a version number, in bytes (major + minor + revision), per CHPP 285 * spec. 286 */ 287 #define CHPP_SERVICE_VERSION_LEN (1 + 1 + 2) 288 289 /** 290 * Maximum length of a human-readable service name, per CHPP spec. 291 * (15 ASCII characters + null) 292 */ 293 #define CHPP_SERVICE_NAME_MAX_LEN (15 + 1) 294 295 /** 296 * Support for sync response. 297 * 298 * @see chppClientSendTimestampedRequestAndWaitTimeout. 299 */ 300 struct ChppSyncResponse { 301 struct ChppMutex mutex; 302 struct ChppConditionVariable condVar; 303 bool ready; 304 }; 305 306 /** 307 * CHPP definition of a service descriptor as sent over the wire. 308 */ 309 CHPP_PACKED_START 310 struct ChppServiceDescriptor { 311 //! UUID of the service. 312 //! Must be generated according to RFC 4122, UUID version 4 (random). 313 uint8_t uuid[CHPP_SERVICE_UUID_LEN]; 314 315 //! Human-readable name of the service for debugging. 316 char name[CHPP_SERVICE_NAME_MAX_LEN]; 317 318 //! Version of the service. 319 struct ChppVersion version; 320 } CHPP_PACKED_ATTR; 321 CHPP_PACKED_END 322 323 /** 324 * CHPP definition of a service as supported on a server. 325 */ 326 struct ChppService { 327 //! Service Descriptor as sent over the wire. 328 struct ChppServiceDescriptor descriptor; 329 330 //! Notifies the service if CHPP is reset. 331 ChppNotifierFunction *resetNotifierFunctionPtr; 332 333 //! Dispatches incoming client requests. 334 //! When an error is returned by the dispatch function it is logged and an 335 //! error response is automatically sent to the remote endpoint. 336 ChppDispatchFunction *requestDispatchFunctionPtr; 337 338 //! Dispatches incoming client notifications. 339 //! Errors returned by the dispatch function are logged. 340 ChppDispatchFunction *notificationDispatchFunctionPtr; 341 342 //! Dispatches incoming client responses. 343 //! Errors returned by the dispatch function are logged. 344 ChppDispatchFunction *responseDispatchFunctionPtr; 345 346 //! Number of outgoing requests supported by this service. 347 //! ChppAppHeader.command must be in the range [0, outReqCount - 1] 348 //! ChppEndpointState.outReqStates must contains that many elements. 349 uint16_t outReqCount; 350 351 //! Minimum valid length of datagrams for the service: 352 //! - client requests 353 //! - client notifications 354 //! - client responses 355 size_t minLength; 356 }; 357 358 /** 359 * CHPP definition of a client descriptor. 360 */ 361 struct ChppClientDescriptor { 362 //! UUID of the client. 363 //! Must be generated according to RFC 4122, UUID version 4 (random). 364 uint8_t uuid[CHPP_SERVICE_UUID_LEN]; 365 366 //! Version of the client. 367 struct ChppVersion version; 368 }; 369 370 /** 371 * CHPP definition of a client. 372 */ 373 struct ChppClient { 374 //! Client descriptor. 375 struct ChppClientDescriptor descriptor; 376 377 //! Notifies the client if CHPP is reset. 378 ChppNotifierFunction *resetNotifierFunctionPtr; 379 380 //! Notifies the client if CHPP is matched to a service. 381 ChppNotifierFunction *matchNotifierFunctionPtr; 382 383 //! Dispatches incoming service responses. 384 //! Service responses are only dispatched to clients that have been opened or 385 //! are in the process of being (re)opened. @see ChppOpenState. 386 //! Errors returned by the dispatch function are logged. 387 ChppDispatchFunction *responseDispatchFunctionPtr; 388 389 //! Dispatches incoming service notifications. 390 //! Service notifications are only dispatched to clients that have been 391 //! opened. @see ChppOpenState 392 //! Errors returned by the dispatch function are logged. 393 ChppDispatchFunction *notificationDispatchFunctionPtr; 394 395 //! Dispatches incoming service requests. 396 //! When an error is returned by the dispatch function it is logged and an 397 //! error response is automatically sent to the remote endpoint. 398 ChppDispatchFunction *requestDispatchFunctionPtr; 399 400 //! Initializes the client (after it is matched with a service at discovery) 401 //! and assigns it its handle number. 402 ChppClientInitFunction *initFunctionPtr; 403 404 //! Deinitializes the client. 405 ChppClientDeinitFunction *deinitFunctionPtr; 406 407 //! Number of outgoing requests supported by this client. 408 //! ChppAppHeader.command must be in the range [0, outReqCount - 1] 409 //! ChppEndpointState.outReqStates must contains that many elements. 410 uint16_t outReqCount; 411 412 //! Minimum valid length of datagrams for the service: 413 //! - service responses 414 //! - service notifications 415 //! - service requests 416 size_t minLength; 417 }; 418 419 /** 420 * Request status for clients. 421 */ 422 enum ChppRequestState { 423 CHPP_REQUEST_STATE_NONE = 0, //!< No request sent ever 424 CHPP_REQUEST_STATE_REQUEST_SENT = 1, //!< Sent, waiting for a response 425 CHPP_REQUEST_STATE_RESPONSE_RCV = 2, //!< Sent and response received 426 CHPP_REQUEST_STATE_RESPONSE_TIMEOUT = 3, //!< Timeout. Responded as need be 427 }; 428 429 /** 430 * State of each outgoing request and their response. 431 * 432 * There must be as many ChppOutgoingRequestState in the client or service state 433 * (ChppEndpointState) as the number of commands they support. 434 */ 435 struct ChppOutgoingRequestState { 436 uint64_t requestTimeNs; // Time of the last request 437 // When requestState is CHPP_REQUEST_STATE_REQUEST_SENT, 438 // indicates the timeout time for the request. 439 // When requestState is CHPP_REQUEST_STATE_RESPONSE_RCV, 440 // indicates when the response was received. 441 uint64_t responseTimeNs; 442 uint8_t requestState; // From enum ChppRequestState 443 uint8_t transaction; // Transaction ID for the last request/response 444 }; 445 446 /** 447 * State of each incoming request and their response. 448 * 449 * There must be as many ChppIncomingRequestState in the client or service state 450 * as the number of commands supported by the other side (corresponding service 451 * for a client and corresponding client for a service). 452 * 453 * Contrary to ChppOutgoingRequestState those are not part of 454 * CChppEndpointState. They must be stored to and retrieved from the context 455 * passed to chppRegisterClient / chppRegisterService. 456 * 457 * Note: while ChppIncomingRequestState and ChppOutgoingRequestState have the 458 * same layout, we want the types to be distinct to be enforced at compile time. 459 * Using a typedef would make both types equivalent. 460 * 461 * @see ChppOutgoingRequestState for field details. 462 */ 463 struct ChppIncomingRequestState { 464 uint64_t requestTimeNs; 465 uint64_t responseTimeNs; 466 uint8_t requestState; 467 uint8_t transaction; 468 }; 469 470 /** 471 * Enabled clients and services. 472 */ 473 struct ChppClientServiceSet { 474 bool wifiService : 1; 475 bool gnssService : 1; 476 bool wwanService : 1; 477 bool wifiClient : 1; 478 bool gnssClient : 1; 479 bool wwanClient : 1; 480 bool loopbackClient : 1; 481 }; 482 483 struct ChppLoopbackClientState; 484 struct ChppTimesyncClientState; 485 486 /** 487 * CHPP state of a client or a service. 488 * 489 * This is the CHPP internal client/service state. 490 * Their private state is store in the context field. 491 */ 492 struct ChppEndpointState { 493 struct ChppAppState *appContext; // Pointer to app layer context 494 495 // State for the outgoing requests. 496 // It must accommodate Chpp{Client,Service}.outReqCount elements. 497 // It also tracks corresponding incoming responses. 498 // NULL when outReqCount = 0. 499 struct ChppOutgoingRequestState *outReqStates; 500 501 void *context; //!< Private state of the endpoint. 502 503 struct ChppSyncResponse syncResponse; 504 505 uint8_t index; //!< Index (in ChppAppState lists). 506 uint8_t handle; //!< Handle used to match client and service. 507 uint8_t transaction; //!< Next Transaction ID to be used. 508 509 uint8_t openState; //!< see enum ChppOpenState 510 511 bool pseudoOpen : 1; //!< Client to be opened upon a reset 512 bool initialized : 1; //!< Client is initialized 513 bool everInitialized : 1; //!< Client sync primitives initialized 514 }; 515 516 struct ChppAppState { 517 struct ChppTransportState *transportContext; // Pointing to transport context 518 519 const struct chrePalSystemApi *systemApi; // Pointing to the PAL system APIs 520 521 uint8_t registeredServiceCount; // Number of services currently registered 522 523 const struct ChppService *registeredServices[CHPP_MAX_REGISTERED_SERVICES]; 524 525 struct ChppEndpointState 526 *registeredServiceStates[CHPP_MAX_REGISTERED_SERVICES]; 527 528 uint8_t registeredClientCount; // Number of clients currently registered 529 530 const struct ChppClient *registeredClients[CHPP_MAX_REGISTERED_CLIENTS]; 531 532 struct ChppEndpointState *registeredClientStates[CHPP_MAX_REGISTERED_CLIENTS]; 533 534 // When the first outstanding request sent from the client timeouts. 535 uint64_t nextClientRequestTimeoutNs; 536 // When the first outstanding request sent from the service timeouts. 537 uint64_t nextServiceRequestTimeoutNs; 538 539 uint8_t 540 clientIndexOfServiceIndex[CHPP_MAX_DISCOVERED_SERVICES]; // Lookup table 541 542 struct ChppClientServiceSet clientServiceSet; // Enabled client/services 543 544 // Pointers to the contexts of basic clients, which are allocated if and when 545 // they are initialized 546 struct ChppLoopbackClientState *loopbackClientContext; 547 struct ChppTimesyncClientState *timesyncClientContext; 548 549 // For discovery clients 550 bool isDiscoveryClientEverInitialized; 551 bool isDiscoveryClientInitialized; 552 bool isDiscoveryComplete; 553 554 // The number of clients that matched a service during discovery. 555 uint8_t matchedClientCount; 556 557 // The number of services that were found during discovery. 558 uint8_t discoveredServiceCount; 559 560 struct ChppMutex discoveryMutex; 561 struct ChppConditionVariable discoveryCv; 562 }; 563 564 #define CHPP_SERVICE_INDEX_OF_HANDLE(handle) \ 565 ((handle)-CHPP_HANDLE_NEGOTIATED_RANGE_START) 566 567 #define CHPP_SERVICE_HANDLE_OF_INDEX(index) \ 568 ((index) + CHPP_HANDLE_NEGOTIATED_RANGE_START) 569 570 /************************************************ 571 * Public functions 572 ***********************************************/ 573 574 /** 575 * Initializes the CHPP app layer state stored in the parameter appContext. 576 * It is necessary to initialize state for each app layer instance on 577 * every platform. 578 * 579 * @param appContext Maintains status for each app layer instance. 580 * @param transportContext The transport layer status struct associated with 581 * this app layer instance. 582 */ 583 void chppAppInit(struct ChppAppState *appContext, 584 struct ChppTransportState *transportContext); 585 586 /** 587 * Same as chppAppInit(), but specifies the client/service endpoints to be 588 * enabled. 589 * 590 * @param appContext Maintains status for each app layer instance. 591 * @param transportContext The transport layer status struct associated with 592 * this app layer instance. 593 * @param clientServiceSet Bitmap specifying the client/service endpoints to be 594 * enabled. 595 */ 596 void chppAppInitWithClientServiceSet( 597 struct ChppAppState *appContext, 598 struct ChppTransportState *transportContext, 599 struct ChppClientServiceSet clientServiceSet); 600 601 /** 602 * Deinitializes the CHPP app layer for e.g. clean shutdown. 603 * 604 * @param appContext A non-null pointer to ChppAppState initialized previously 605 * in chppAppInit(). 606 */ 607 void chppAppDeinit(struct ChppAppState *appContext); 608 609 /** 610 * Processes an Rx Datagram from the transport layer. 611 * 612 * @param context Maintains status for each app layer instance. 613 * @param buf Input data. Cannot be null. 614 * @param len Length of input data in bytes. 615 */ 616 void chppAppProcessRxDatagram(struct ChppAppState *context, uint8_t *buf, 617 size_t len); 618 619 /** 620 * Used by the transport layer to notify the app layer of a reset during 621 * operation. This function is called after the transport layer has sent a reset 622 * or reset-ack packet. 623 * In turn, this function notifies clients and services to allow them to reset 624 * or recover state as necessary. 625 * 626 * @param context Maintains status for each app layer instance. 627 */ 628 void chppAppProcessReset(struct ChppAppState *context); 629 630 /** 631 * Convert UUID to a human-readable, null-terminated string. 632 * 633 * @param uuid Input UUID 634 * @param strOut Output null-terminated string 635 */ 636 void chppUuidToStr(const uint8_t uuid[CHPP_SERVICE_UUID_LEN], 637 char strOut[CHPP_SERVICE_UUID_STRING_LEN]); 638 639 /** 640 * Maps a CHPP app layer error to a CHRE error. 641 * 642 * @param chppError CHPP app layer error (from enum ChppAppErrorCode). 643 * 644 * @return CHRE error (from enum chreError). 645 */ 646 uint8_t chppAppErrorToChreError(uint8_t error); 647 648 /** 649 * Handles logging and error conversion when an app layer response is too short. 650 * 651 * @param buf Input data. Cannot be null. 652 * @param len Length of input data in bytes. 653 * @param responseName Name of the request/response to be logged. 654 * 655 * @return CHRE error (from enum chreError). 656 */ 657 uint8_t chppAppShortResponseErrorHandler(uint8_t *buf, size_t len, 658 const char *responseName); 659 660 /** 661 * Allocates a notification of a specified length. 662 * 663 * This function is internal. Instead use either 664 * - chppAllocClientNotification 665 * - or chppAllocServiceNotification 666 * 667 * The caller must initialize at least the handle and command fields of the 668 * ChppAppHeader. 669 * 670 * @param type CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION or 671 * CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION. 672 * @param len Length of the notification (including header) in bytes. Note 673 * that the specified length must be at least equal to the length of the 674 * app layer header. 675 * 676 * @return Pointer to allocated memory. 677 */ 678 struct ChppAppHeader *chppAllocNotification(uint8_t type, size_t len); 679 680 /** 681 * Allocates a request message. 682 * 683 * This function is internal. Instead use either: 684 * - chppAllocClientRequest 685 * - or chppAllocServiceRequest 686 * 687 * @param type CHPP_MESSAGE_TYPE_CLIENT_REQUEST or 688 * CHPP_MESSAGE_TYPE_SERVICE_REQUEST. 689 * @param endpointState State of the endpoint. 690 * @param len Length of the response message (including header) in bytes. Note 691 * that the specified length must be at least equal to the length of the 692 * app layer header. 693 * 694 * @return Pointer to allocated memory. 695 */ 696 struct ChppAppHeader *chppAllocRequest(uint8_t type, 697 struct ChppEndpointState *endpointState, 698 size_t len); 699 700 /** 701 * Allocates a response message of a specified length, populating the (app 702 * layer) response header according to the provided request (app layer) header. 703 * 704 * This function can be used to allocate either client or service response. 705 * 706 * @param requestHeader request header. 707 * @param len Length of the response message (including header) in bytes. Note 708 * that the specified length must be at least equal to the length of the 709 * app layer header. 710 * 711 * @return Pointer to allocated memory. 712 */ 713 struct ChppAppHeader *chppAllocResponse( 714 const struct ChppAppHeader *requestHeader, size_t len); 715 716 /** 717 * This function shall be called for all incoming requests in order to 718 * A) Timestamp them, and 719 * B) Save their Transaction ID 720 * 721 * This function prints an error message if a duplicate request is received 722 * while outstanding request is still pending without a response. 723 * 724 * @param inReqState State of the request/response. 725 * @param requestHeader Request header. 726 */ 727 void chppTimestampIncomingRequest(struct ChppIncomingRequestState *inReqState, 728 const struct ChppAppHeader *requestHeader); 729 730 /** 731 * This function shall be called for all outgoing requests in order to 732 * A) Timestamp them, and 733 * B) Save their Transaction ID 734 * 735 * This function prints an error message if a duplicate request is sent 736 * while outstanding request is still pending without a response. 737 * 738 * @param appState App layer state. 739 * @param outReqState state of the request/response. 740 * @param requestHeader Client request header. 741 * @param timeoutNs The timeout. 742 */ 743 void chppTimestampOutgoingRequest(struct ChppAppState *appState, 744 struct ChppOutgoingRequestState *outReqState, 745 const struct ChppAppHeader *requestHeader, 746 uint64_t timeoutNs); 747 748 /** 749 * This function shall be called for incoming responses to a request in 750 * order to 751 * A) Verify the correct transaction ID 752 * B) Timestamp them, and 753 * C) Mark them as fulfilled 754 * 755 * This function prints an error message if a response is received without an 756 * outstanding request. 757 * 758 * @param appState App layer state. 759 * @param outReqState state of the request/response. 760 * @param requestHeader Request header. 761 * 762 * @return false if there is an error. true otherwise. 763 */ 764 bool chppTimestampIncomingResponse(struct ChppAppState *appState, 765 struct ChppOutgoingRequestState *outReqState, 766 const struct ChppAppHeader *responseHeader); 767 768 /** 769 * This function shall be called for the outgoing response to a request in order 770 * to: 771 * A) Timestamp them, and 772 * B) Mark them as fulfilled part of the request/response's 773 * ChppOutgoingRequestState struct. 774 * 775 * For most responses, it is expected that chppSendTimestampedResponseOrFail() 776 * shall be used to both timestamp and send the response in one shot. 777 * 778 * @param inReqState State of the request/response. 779 * @return The last response time (CHPP_TIME_NONE for the first response). 780 */ 781 uint64_t chppTimestampOutgoingResponse( 782 struct ChppIncomingRequestState *inReqState); 783 784 /** 785 * Timestamps a response using chppTimestampOutgoingResponse() and enqueues it 786 * using chppEnqueueTxDatagramOrFail(). 787 * 788 * Refer to their respective documentation for details. 789 * 790 * This function logs an error message if a response is attempted without an 791 * outstanding request. 792 * 793 * @param appState App layer state. 794 * @param inReqState State of the request/response. 795 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 796 * @param len Datagram length in bytes. 797 * 798 * @return whether the datagram was successfully enqueued. false means that the 799 * queue was full and the payload discarded. 800 */ 801 bool chppSendTimestampedResponseOrFail( 802 struct ChppAppState *appState, struct ChppIncomingRequestState *inReqState, 803 void *buf, size_t len); 804 805 /** 806 * Timestamps and enqueues a request. 807 * 808 * This function is internal. User either: 809 * - chppClientSendTimestampedRequestOrFail 810 * - or chppServiceSendTimestampedRequestOrFail 811 * 812 * Note that the ownership of buf is taken from the caller when this method is 813 * invoked. 814 * 815 * @param endpointState state of the endpoint. 816 * @param outReqState state of the request/response. 817 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 818 * @param len Datagram length in bytes. 819 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 820 * Zero means no timeout response. 821 * 822 * @return True informs the sender that the datagram was successfully enqueued. 823 * False informs the sender that the queue was full and the payload 824 * discarded. 825 */ 826 bool chppSendTimestampedRequestOrFail( 827 struct ChppEndpointState *endpointState, 828 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len, 829 uint64_t timeoutNs); 830 831 /** 832 * Wait for a response to be received. 833 * 834 * @param syncResponse sync primitives. 835 * @param outReqState state of the request/response. 836 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 837 */ 838 bool chppWaitForResponseWithTimeout( 839 struct ChppSyncResponse *syncResponse, 840 struct ChppOutgoingRequestState *outReqState, uint64_t timeoutNs); 841 842 /** 843 * Returns the state of a registered endpoint. 844 * 845 * @param appState State of the app layer. 846 * @param index Index of the client or service. 847 * @param type Type of the endpoint to return. 848 * @return state of the client or service. 849 */ 850 struct ChppEndpointState *getRegisteredEndpointState( 851 struct ChppAppState *appState, uint8_t index, enum ChppEndpointType type); 852 853 /** 854 * Returns the number of possible outgoing requests. 855 * 856 * @param appState State of the app layer. 857 * @param index Index of the client or service. 858 * @param type Type of the endpoint to return. 859 * @return The number of possible outgoing requests. 860 */ 861 uint16_t getRegisteredEndpointOutReqCount(struct ChppAppState *appState, 862 uint8_t index, 863 enum ChppEndpointType type); 864 865 /** 866 * Returns the number of registered endpoints of the given type. 867 * 868 * @param appState State of the app layer. 869 * @param type Type of the endpoint to return. 870 * @return The number of endpoints. 871 */ 872 uint8_t getRegisteredEndpointCount(struct ChppAppState *appState, 873 enum ChppEndpointType type); 874 875 /** 876 * Recalculates the next upcoming request timeout. 877 * 878 * The timeout is updated in the app layer state. 879 * 880 * @param appState State of the app layer. 881 * @param type Type of the endpoint. 882 */ 883 void chppRecalculateNextTimeout(struct ChppAppState *appState, 884 enum ChppEndpointType type); 885 886 /** 887 * Returns a pointer to the next request timeout for the given endpoint type. 888 * 889 * @param appState State of the app layer. 890 * @param type Type of the endpoint. 891 * @return Pointer to the timeout in nanoseconds. 892 */ 893 uint64_t *getNextRequestTimeoutNs(struct ChppAppState *appState, 894 enum ChppEndpointType type); 895 896 /** 897 * Closes any remaining open requests by simulating a timeout. 898 * 899 * This function is used when an endpoint is reset. 900 * 901 * @param endpointState State of the endpoint. 902 * @param type The type of the endpoint. 903 * @param clearOnly If true, indicates that a timeout response shouldn't be 904 * sent. This must only be set if the requests are being cleared as 905 * part of the closing. 906 */ 907 void chppCloseOpenRequests(struct ChppEndpointState *endpointState, 908 enum ChppEndpointType type, bool clearOnly); 909 910 #ifdef __cplusplus 911 } 912 #endif 913 914 #endif // CHPP_APP_H_ 915