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_CLIENTS_H_
18 #define CHPP_CLIENTS_H_
19 
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 #include "chpp/app.h"
25 #include "chpp/condition_variable.h"
26 #include "chpp/macros.h"
27 #include "chpp/mutex.h"
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /************************************************
34  *  Public Definitions
35  ***********************************************/
36 
37 /**
38  * Allocates a client request message of a specific type and its corresponding
39  * length.
40  *
41  * @param clientState State of the client.
42  * @param type Type of response.
43  *
44  * @return Pointer to allocated memory
45  */
46 #define chppAllocClientRequestFixed(clientState, type) \
47   (type *)chppAllocClientRequest(clientState, sizeof(type))
48 
49 /**
50  * Allocates a variable-length client request message of a specific type.
51  *
52  * @param clientState State of the client.
53  * @param type Type of response which includes an arrayed member.
54  * @param count number of items in the array of arrayField.
55  * @param arrayField The arrayed member field.
56  *
57  * @return Pointer to allocated memory
58  */
59 #define chppAllocClientRequestTypedArray(clientState, type, count, arrayField) \
60   (type *)chppAllocClientRequest(                                              \
61       clientState, sizeof(type) + (count)*sizeof_member(type, arrayField[0]))
62 
63 /**
64  * Allocates a variable-length notification of a specific type.
65  *
66  * @param type Type of notification which includes an arrayed member.
67  * @param count number of items in the array of arrayField.
68  * @param arrayField The arrayed member field.
69  *
70  * @return Pointer to allocated memory
71  */
72 #define chppAllocClientNotificationTypedArray(type, count, arrayField) \
73   (type *)chppAllocClientNotification(                                 \
74       sizeof(type) + (count)*sizeof_member(type, arrayField[0]))
75 
76 /**
77  * Allocates a notification of a specific type and its corresponding length.
78  *
79  * @param type Type of notification.
80  *
81  * @return Pointer to allocated memory
82  */
83 #define chppAllocClientNotificationFixed(type) \
84   (type *)chppAllocClientNotification(sizeof(type))
85 
86 #ifdef CHPP_CLIENT_ENABLED_CHRE_WWAN
87 #define CHPP_CLIENT_ENABLED_WWAN
88 #endif
89 
90 #ifdef CHPP_CLIENT_ENABLED_CHRE_WIFI
91 #define CHPP_CLIENT_ENABLED_WIFI
92 #endif
93 
94 #ifdef CHPP_CLIENT_ENABLED_CHRE_GNSS
95 #define CHPP_CLIENT_ENABLED_GNSS
96 #endif
97 
98 #if defined(CHPP_CLIENT_ENABLED_LOOPBACK) ||                                  \
99     defined(CHPP_CLIENT_ENABLED_TIMESYNC) ||                                  \
100     defined(CHPP_CLIENT_ENABLED_DISCOVERY) ||                                 \
101     defined(CHPP_CLIENT_ENABLED_WWAN) || defined(CHPP_CLIENT_ENABLED_WIFI) || \
102     defined(CHPP_CLIENT_ENABLED_GNSS)
103 #define CHPP_CLIENT_ENABLED
104 #endif
105 
106 // Default timeout for discovery completion.
107 #ifndef CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS
108 #define CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS UINT64_C(10000)  // 10s
109 #endif
110 
111 /************************************************
112  *  Public functions
113  ***********************************************/
114 
115 /**
116  * Registers common clients with the CHPP app layer. These clients are enabled
117  * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically
118  * called by chppAppInit().
119  *
120  * @param context State of the app layer.
121  */
122 void chppRegisterCommonClients(struct ChppAppState *context);
123 
124 /**
125  * Deregisters common clients with the CHPP app layer. These clients are enabled
126  * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically
127  * called by chppAppDeinit().
128  *
129  * @param context State of the app layer.
130  */
131 void chppDeregisterCommonClients(struct ChppAppState *context);
132 
133 /**
134  * Registers a new client on CHPP.
135  *
136  * This function is to be called by the platform initialization code for every
137  * non-common client available on a server (if any), i.e. except those that are
138  * registered through chppRegisterCommonClients().
139  *
140  * Registered clients are matched with discovered services during discovery.
141  * When a match succeeds, the client's initialization function (pointer) is
142  * called, assigning them their handle number.
143  *
144  * outReqStates must point to an array of ChppOutgoingRequestState with
145  * ChppEndpointState.outReqCount elements. It must be NULL when the client
146  * does not send requests (ChppEndpointState.outReqCount = 0).
147  *
148  * inReqStates must point to an array of ChppIncomingRequestState with
149  * as many elements as the corresponding service can send. It must be NULL when
150  * the service does not send requests (ChppEndpointState.outReqCount = 0).
151  *
152  * Note that the maximum number of clients that can be registered on a platform
153  * can specified as CHPP_MAX_REGISTERED_CLIENTS by the initialization code.
154  * Otherwise, a default value will be used.
155  *
156  * @param appContext State of the app layer.
157  * @param clientContext State of the client instance.
158  * @param clientState State of the client.
159  * @param outReqStates List of outgoing request states.
160  * @param newClient The client to be registered on this platform.
161  */
162 void chppRegisterClient(struct ChppAppState *appContext, void *clientContext,
163                         struct ChppEndpointState *clientState,
164                         struct ChppOutgoingRequestState *outReqStates,
165                         const struct ChppClient *newClient);
166 
167 /**
168  * Initializes basic CHPP clients.
169  *
170  * @param context State of the app layer.
171  */
172 void chppInitBasicClients(struct ChppAppState *context);
173 
174 /**
175  * Initializes a client. This function must be called when a client is matched
176  * with a service during discovery to provides its handle number.
177  *
178  * @param clientState State of the client.
179  * @param handle Handle number for this client.
180  */
181 void chppClientInit(struct ChppEndpointState *clientState, uint8_t handle);
182 
183 /**
184  * Deinitializes a client.
185  *
186  * @param clientState State of the client.
187  */
188 void chppClientDeinit(struct ChppEndpointState *clientState);
189 
190 /**
191  * Deinitializes basic clients.
192  *
193  * @param context State of the app layer.
194  */
195 void chppDeinitBasicClients(struct ChppAppState *context);
196 
197 /**
198  * Deinitializes all matched clients.
199  *
200  * @param context State of the app layer.
201  */
202 void chppDeinitMatchedClients(struct ChppAppState *context);
203 
204 /**
205  * Allocates a client request message of a specified length.
206  *
207  * It populates the request header, including the transaction number which is
208  * then incremented.
209  *
210  * For most use cases, the chppAllocClientRequestFixed() or
211  * chppAllocClientRequestTypedArray() macros shall be preferred.
212  *
213  * @param clientState State of the client.
214  * @param len Length of the response message (including header) in bytes. Note
215  *        that the specified length must be at least equal to the length of the
216  *        app layer header.
217  *
218  * @return Pointer to allocated memory
219  */
220 struct ChppAppHeader *chppAllocClientRequest(
221     struct ChppEndpointState *clientState, size_t len);
222 
223 /**
224  * Allocates a specific client request command without any additional payload.
225  *
226  * @param clientState State of the client.
227  * @param command Type of response.
228  *
229  * @return Pointer to allocated memory
230  */
231 struct ChppAppHeader *chppAllocClientRequestCommand(
232     struct ChppEndpointState *clientState, uint16_t command);
233 
234 /**
235  * Timestamps and enqueues a request.
236  *
237  * Note that the ownership of buf is taken from the caller when this method is
238  * invoked.
239  *
240  * @param clientState State of the client sending the request.
241  * @param outReqState State of the request/response
242  * @param buf Datagram payload allocated through chppMalloc. Cannot be null.
243  * @param len Datagram length in bytes.
244  * @param timeoutNs Time in nanoseconds before a timeout response is generated.
245  *        Zero means no timeout response.
246  *
247  * @return True informs the sender that the datagram was successfully enqueued.
248  *         False informs the sender that the queue was full and the payload
249  *         discarded.
250  */
251 bool chppClientSendTimestampedRequestOrFail(
252     struct ChppEndpointState *clientState,
253     struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
254     uint64_t timeoutNs);
255 
256 /**
257  * Similar to chppClientSendTimestampedRequestOrFail() but blocks execution
258  * until a response is received. Used for synchronous requests.
259  *
260  * In order to use this function, clientState->responseNotifier must have been
261  * initialized using chppNotifierInit() upon initialization of the client.
262  *
263  * @param clientState State of the client sending the request.
264  * @param outReqState State of the request/response.
265  * @param buf Datagram payload allocated through chppMalloc. Cannot be null.
266  * @param len Datagram length in bytes.
267  *
268  * @return True informs the sender that the datagram was successfully enqueued.
269  *         False informs the sender that the payload was discarded because
270  *         either the queue was full, or the request timed out.
271  */
272 bool chppClientSendTimestampedRequestAndWait(
273     struct ChppEndpointState *clientState,
274     struct ChppOutgoingRequestState *outReqState, void *buf, size_t len);
275 
276 /**
277  * Same as chppClientSendTimestampedRequestAndWait() but with a specified
278  * timeout.
279  *
280  * @param clientState State of the client sending the request.
281  * @param outReqState State of the request/response.
282  * @param buf Datagram payload allocated through chppMalloc. Cannot be null.
283  * @param len Datagram length in bytes.
284  *
285  * @return True informs the sender that the datagram was successfully enqueued.
286  *         False informs the sender that the payload was discarded because
287  *         either the queue was full, or the request timed out.
288  */
289 bool chppClientSendTimestampedRequestAndWaitTimeout(
290     struct ChppEndpointState *clientState,
291     struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
292     uint64_t timeoutNs);
293 
294 /**
295  * Marks a closed client as pseudo-open, so that it would be opened upon a
296  * reset.
297  *
298  * @param clientState State of the client.
299  */
300 void chppClientPseudoOpen(struct ChppEndpointState *clientState);
301 
302 /**
303  * Sends a client request for the open command in a blocking or non-blocking
304  * manner.
305  * A non-blocking open is used to for reopening a service after a reset or for
306  * opening a pseudo-open service.
307  *
308  * @param clientState State of the client.
309  * @param openReqState State of the request/response for the open command.
310  * @param openCommand Open command to be sent.
311  * @param blocking Indicates a blocking (vs. non-blocking) open request.
312  *
313  * @return Indicates success or failure.
314  */
315 bool chppClientSendOpenRequest(struct ChppEndpointState *clientState,
316                                struct ChppOutgoingRequestState *openReqState,
317                                uint16_t openCommand, bool blocking);
318 
319 /**
320  * Processes a service response for the open command.
321  *
322  * @param clientState State of the client.
323  */
324 void chppClientProcessOpenResponse(struct ChppEndpointState *clientState,
325                                    uint8_t *buf, size_t len);
326 
327 /**
328  * Closes any remaining open requests by simulating a timeout.
329 
330  * This function is used when a client is reset.
331  *
332  * @param clientState State of the client.
333  * @param client The client for which to clear out open requests.
334  * @param clearOnly If true, indicates that a timeout response shouldn't be
335  *        sent. This must only be set if the requests are being cleared as part
336  *        of the client closing.
337  */
338 void chppClientCloseOpenRequests(struct ChppEndpointState *clientState,
339                                  const struct ChppClient *client,
340                                  bool clearOnly);
341 
342 /**
343  * Allocates a client notification of a specified length.
344  *
345  * It is expected that for most use cases, the
346  * chppAllocClientNotificationFixed() or
347  * chppAllocClientNotificationTypedArray() macros shall be used rather than
348  * calling this function directly.
349  *
350  * The caller must initialize at least the handle and command fields of the
351  * ChppAppHeader.
352  *
353  * @param len Length of the notification (including header) in bytes. Note
354  *        that the specified length must be at least equal to the length of the
355  *        app layer header.
356  *
357  * @return Pointer to allocated memory.
358  */
359 struct ChppAppHeader *chppAllocClientNotification(size_t len);
360 
361 #ifdef __cplusplus
362 }
363 #endif
364 
365 #endif  // CHPP_CLIENTS_H_
366