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 bool vendorClients : 1; 482 bool vendorServices : 1; 483 }; 484 485 struct ChppLoopbackClientState; 486 struct ChppTimesyncClientState; 487 488 /** 489 * CHPP state of a client or a service. 490 * 491 * This is the CHPP internal client/service state. 492 * Their private state is store in the context field. 493 */ 494 struct ChppEndpointState { 495 struct ChppAppState *appContext; // Pointer to app layer context 496 497 // State for the outgoing requests. 498 // It must accommodate Chpp{Client,Service}.outReqCount elements. 499 // It also tracks corresponding incoming responses. 500 // NULL when outReqCount = 0. 501 struct ChppOutgoingRequestState *outReqStates; 502 503 void *context; //!< Private state of the endpoint. 504 505 struct ChppSyncResponse syncResponse; 506 507 uint8_t index; //!< Index (in ChppAppState lists). 508 uint8_t handle; //!< Handle used to match client and service. 509 uint8_t transaction; //!< Next Transaction ID to be used. 510 511 uint8_t openState; //!< see enum ChppOpenState 512 513 bool pseudoOpen : 1; //!< Client to be opened upon a reset 514 bool initialized : 1; //!< Client is initialized 515 bool everInitialized : 1; //!< Client sync primitives initialized 516 }; 517 518 struct ChppAppState { 519 struct ChppTransportState *transportContext; // Pointing to transport context 520 521 const struct chrePalSystemApi *systemApi; // Pointing to the PAL system APIs 522 523 uint8_t registeredServiceCount; // Number of services currently registered 524 525 const struct ChppService *registeredServices[CHPP_MAX_REGISTERED_SERVICES]; 526 527 struct ChppEndpointState 528 *registeredServiceStates[CHPP_MAX_REGISTERED_SERVICES]; 529 530 uint8_t registeredClientCount; // Number of clients currently registered 531 532 const struct ChppClient *registeredClients[CHPP_MAX_REGISTERED_CLIENTS]; 533 534 struct ChppEndpointState *registeredClientStates[CHPP_MAX_REGISTERED_CLIENTS]; 535 536 // When the first outstanding request sent from the client timeouts. 537 uint64_t nextClientRequestTimeoutNs; 538 // When the first outstanding request sent from the service timeouts. 539 uint64_t nextServiceRequestTimeoutNs; 540 541 uint8_t 542 clientIndexOfServiceIndex[CHPP_MAX_DISCOVERED_SERVICES]; // Lookup table 543 544 struct ChppClientServiceSet clientServiceSet; // Enabled client/services 545 546 // Pointers to the contexts of basic clients, which are allocated if and when 547 // they are initialized 548 struct ChppLoopbackClientState *loopbackClientContext; 549 struct ChppTimesyncClientState *timesyncClientContext; 550 551 // For discovery clients 552 bool isDiscoveryClientEverInitialized; 553 bool isDiscoveryClientInitialized; 554 bool isDiscoveryComplete; 555 556 // The number of clients that matched a service during discovery. 557 uint8_t matchedClientCount; 558 559 // The number of services that were found during discovery. 560 uint8_t discoveredServiceCount; 561 562 struct ChppMutex discoveryMutex; 563 struct ChppConditionVariable discoveryCv; 564 }; 565 566 #define CHPP_SERVICE_INDEX_OF_HANDLE(handle) \ 567 ((handle)-CHPP_HANDLE_NEGOTIATED_RANGE_START) 568 569 #define CHPP_SERVICE_HANDLE_OF_INDEX(index) \ 570 ((index) + CHPP_HANDLE_NEGOTIATED_RANGE_START) 571 572 /************************************************ 573 * Public functions 574 ***********************************************/ 575 576 /** 577 * Initializes the CHPP app layer state stored in the parameter appContext. 578 * It is necessary to initialize state for each app layer instance on 579 * every platform. 580 * 581 * @param appContext Maintains status for each app layer instance. 582 * @param transportContext The transport layer status struct associated with 583 * this app layer instance. 584 */ 585 void chppAppInit(struct ChppAppState *appContext, 586 struct ChppTransportState *transportContext); 587 588 /** 589 * Same as chppAppInit(), but specifies the client/service endpoints to be 590 * enabled. 591 * 592 * @param appContext Maintains status for each app layer instance. 593 * @param transportContext The transport layer status struct associated with 594 * this app layer instance. 595 * @param clientServiceSet Bitmap specifying the client/service endpoints to be 596 * enabled. 597 */ 598 void chppAppInitWithClientServiceSet( 599 struct ChppAppState *appContext, 600 struct ChppTransportState *transportContext, 601 struct ChppClientServiceSet clientServiceSet); 602 603 /** 604 * Deinitializes the CHPP app layer for e.g. clean shutdown. 605 * 606 * @param appContext A non-null pointer to ChppAppState initialized previously 607 * in chppAppInit(). 608 */ 609 void chppAppDeinit(struct ChppAppState *appContext); 610 611 /** 612 * Processes an Rx Datagram from the transport layer. 613 * 614 * @param context Maintains status for each app layer instance. 615 * @param buf Input data. Cannot be null. 616 * @param len Length of input data in bytes. 617 */ 618 void chppAppProcessRxDatagram(struct ChppAppState *context, uint8_t *buf, 619 size_t len); 620 621 /** 622 * Used by the transport layer to notify the app layer of a reset during 623 * operation. This function is called after the transport layer has sent a reset 624 * or reset-ack packet. 625 * In turn, this function notifies clients and services to allow them to reset 626 * or recover state as necessary. 627 * 628 * @param context Maintains status for each app layer instance. 629 */ 630 void chppAppProcessReset(struct ChppAppState *context); 631 632 /** 633 * Convert UUID to a human-readable, null-terminated string. 634 * 635 * @param uuid Input UUID 636 * @param strOut Output null-terminated string 637 */ 638 void chppUuidToStr(const uint8_t uuid[CHPP_SERVICE_UUID_LEN], 639 char strOut[CHPP_SERVICE_UUID_STRING_LEN]); 640 641 /** 642 * Maps a CHPP app layer error to a CHRE error. 643 * 644 * @param chppError CHPP app layer error (from enum ChppAppErrorCode). 645 * 646 * @return CHRE error (from enum chreError). 647 */ 648 uint8_t chppAppErrorToChreError(uint8_t error); 649 650 /** 651 * Handles logging and error conversion when an app layer response is too short. 652 * 653 * @param buf Input data. Cannot be null. 654 * @param len Length of input data in bytes. 655 * @param responseName Name of the request/response to be logged. 656 * 657 * @return CHRE error (from enum chreError). 658 */ 659 uint8_t chppAppShortResponseErrorHandler(uint8_t *buf, size_t len, 660 const char *responseName); 661 662 /** 663 * Allocates a notification of a specified length. 664 * 665 * This function is internal. Instead use either 666 * - chppAllocClientNotification 667 * - or chppAllocServiceNotification 668 * 669 * The caller must initialize at least the handle and command fields of the 670 * ChppAppHeader. 671 * 672 * @param type CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION or 673 * CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION. 674 * @param len Length of the notification (including header) in bytes. Note 675 * that the specified length must be at least equal to the length of the 676 * app layer header. 677 * 678 * @return Pointer to allocated memory. 679 */ 680 struct ChppAppHeader *chppAllocNotification(uint8_t type, size_t len); 681 682 /** 683 * Allocates a request message. 684 * 685 * This function is internal. Instead use either: 686 * - chppAllocClientRequest 687 * - or chppAllocServiceRequest 688 * 689 * @param type CHPP_MESSAGE_TYPE_CLIENT_REQUEST or 690 * CHPP_MESSAGE_TYPE_SERVICE_REQUEST. 691 * @param endpointState State of the endpoint. 692 * @param len Length of the response message (including header) in bytes. Note 693 * that the specified length must be at least equal to the length of the 694 * app layer header. 695 * 696 * @return Pointer to allocated memory. 697 */ 698 struct ChppAppHeader *chppAllocRequest(uint8_t type, 699 struct ChppEndpointState *endpointState, 700 size_t len); 701 702 /** 703 * Allocates a response message of a specified length, populating the (app 704 * layer) response header according to the provided request (app layer) header. 705 * 706 * This function can be used to allocate either client or service response. 707 * 708 * @param requestHeader request header. 709 * @param len Length of the response message (including header) in bytes. Note 710 * that the specified length must be at least equal to the length of the 711 * app layer header. 712 * 713 * @return Pointer to allocated memory. 714 */ 715 struct ChppAppHeader *chppAllocResponse( 716 const struct ChppAppHeader *requestHeader, size_t len); 717 718 /** 719 * This function shall be called for all incoming requests in order to 720 * A) Timestamp them, and 721 * B) Save their Transaction ID 722 * 723 * This function prints an error message if a duplicate request is received 724 * while outstanding request is still pending without a response. 725 * 726 * @param inReqState State of the request/response. 727 * @param requestHeader Request header. 728 */ 729 void chppTimestampIncomingRequest(struct ChppIncomingRequestState *inReqState, 730 const struct ChppAppHeader *requestHeader); 731 732 /** 733 * This function shall be called for all outgoing requests in order to 734 * A) Timestamp them, and 735 * B) Save their Transaction ID 736 * 737 * This function prints an error message if a duplicate request is sent 738 * while outstanding request is still pending without a response. 739 * 740 * @param appState App layer state. 741 * @param outReqState state of the request/response. 742 * @param requestHeader Client request header. 743 * @param timeoutNs The timeout. 744 */ 745 void chppTimestampOutgoingRequest(struct ChppAppState *appState, 746 struct ChppOutgoingRequestState *outReqState, 747 const struct ChppAppHeader *requestHeader, 748 uint64_t timeoutNs); 749 750 /** 751 * This function shall be called for incoming responses to a request in 752 * order to 753 * A) Verify the correct transaction ID 754 * B) Timestamp them, and 755 * C) Mark them as fulfilled 756 * 757 * This function prints an error message if a response is received without an 758 * outstanding request. 759 * 760 * @param appState App layer state. 761 * @param outReqState state of the request/response. 762 * @param requestHeader Request header. 763 * 764 * @return false if there is an error. true otherwise. 765 */ 766 bool chppTimestampIncomingResponse(struct ChppAppState *appState, 767 struct ChppOutgoingRequestState *outReqState, 768 const struct ChppAppHeader *responseHeader); 769 770 /** 771 * This function shall be called for the outgoing response to a request in order 772 * to: 773 * A) Timestamp them, and 774 * B) Mark them as fulfilled part of the request/response's 775 * ChppOutgoingRequestState struct. 776 * 777 * For most responses, it is expected that chppSendTimestampedResponseOrFail() 778 * shall be used to both timestamp and send the response in one shot. 779 * 780 * @param inReqState State of the request/response. 781 * @return The last response time (CHPP_TIME_NONE for the first response). 782 */ 783 uint64_t chppTimestampOutgoingResponse( 784 struct ChppIncomingRequestState *inReqState); 785 786 /** 787 * Timestamps a response using chppTimestampOutgoingResponse() and enqueues it 788 * using chppEnqueueTxDatagramOrFail(). 789 * 790 * Refer to their respective documentation for details. 791 * 792 * This function logs an error message if a response is attempted without an 793 * outstanding request. 794 * 795 * @param appState App layer state. 796 * @param inReqState State of the request/response. 797 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 798 * @param len Datagram length in bytes. 799 * 800 * @return whether the datagram was successfully enqueued. false means that the 801 * queue was full and the payload discarded. 802 */ 803 bool chppSendTimestampedResponseOrFail( 804 struct ChppAppState *appState, struct ChppIncomingRequestState *inReqState, 805 void *buf, size_t len); 806 807 /** 808 * Timestamps and enqueues a request. 809 * 810 * This function is internal. User either: 811 * - chppClientSendTimestampedRequestOrFail 812 * - or chppServiceSendTimestampedRequestOrFail 813 * 814 * Note that the ownership of buf is taken from the caller when this method is 815 * invoked. 816 * 817 * @param endpointState state of the endpoint. 818 * @param outReqState state of the request/response. 819 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 820 * @param len Datagram length in bytes. 821 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 822 * Zero means no timeout response. 823 * 824 * @return True informs the sender that the datagram was successfully enqueued. 825 * False informs the sender that the queue was full and the payload 826 * discarded. 827 */ 828 bool chppSendTimestampedRequestOrFail( 829 struct ChppEndpointState *endpointState, 830 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len, 831 uint64_t timeoutNs); 832 833 /** 834 * Wait for a response to be received. 835 * 836 * @param syncResponse sync primitives. 837 * @param outReqState state of the request/response. 838 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 839 */ 840 bool chppWaitForResponseWithTimeout( 841 struct ChppSyncResponse *syncResponse, 842 struct ChppOutgoingRequestState *outReqState, uint64_t timeoutNs); 843 844 /** 845 * Returns the state of a registered endpoint. 846 * 847 * @param appState State of the app layer. 848 * @param index Index of the client or service. 849 * @param type Type of the endpoint to return. 850 * @return state of the client or service. 851 */ 852 struct ChppEndpointState *getRegisteredEndpointState( 853 struct ChppAppState *appState, uint8_t index, enum ChppEndpointType type); 854 855 /** 856 * Returns the number of possible outgoing requests. 857 * 858 * @param appState State of the app layer. 859 * @param index Index of the client or service. 860 * @param type Type of the endpoint to return. 861 * @return The number of possible outgoing requests. 862 */ 863 uint16_t getRegisteredEndpointOutReqCount(struct ChppAppState *appState, 864 uint8_t index, 865 enum ChppEndpointType type); 866 867 /** 868 * Returns the number of registered endpoints of the given type. 869 * 870 * @param appState State of the app layer. 871 * @param type Type of the endpoint to return. 872 * @return The number of endpoints. 873 */ 874 uint8_t getRegisteredEndpointCount(struct ChppAppState *appState, 875 enum ChppEndpointType type); 876 877 /** 878 * Recalculates the next upcoming request timeout. 879 * 880 * The timeout is updated in the app layer state. 881 * 882 * @param appState State of the app layer. 883 * @param type Type of the endpoint. 884 */ 885 void chppRecalculateNextTimeout(struct ChppAppState *appState, 886 enum ChppEndpointType type); 887 888 /** 889 * Returns a pointer to the next request timeout for the given endpoint type. 890 * 891 * @param appState State of the app layer. 892 * @param type Type of the endpoint. 893 * @return Pointer to the timeout in nanoseconds. 894 */ 895 uint64_t *getNextRequestTimeoutNs(struct ChppAppState *appState, 896 enum ChppEndpointType type); 897 898 /** 899 * Closes any remaining open requests by simulating a timeout. 900 * 901 * This function is used when an endpoint is reset. 902 * 903 * @param endpointState State of the endpoint. 904 * @param type The type of the endpoint. 905 * @param clearOnly If true, indicates that a timeout response shouldn't be 906 * sent. This must only be set if the requests are being cleared as 907 * part of the closing. 908 */ 909 void chppCloseOpenRequests(struct ChppEndpointState *endpointState, 910 enum ChppEndpointType type, bool clearOnly); 911 912 #ifdef __cplusplus 913 } 914 #endif 915 916 #endif // CHPP_APP_H_ 917