xref: /aosp_15_r20/system/chre/chpp/include/chpp/app.h (revision 84e339476a462649f82315436d70fd732297a399)
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