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