1533985fec4b0b97446dece818dc3f6d5921eb06
[src/app-framework-binder.git] / include / afb / afb-req.h
1 /*
2  * Copyright (C) 2016, 2017 "IoT.bzh"
3  * Author: José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #pragma once
19
20 #include "afb-req-itf.h"
21 #include "afb-event.h"
22
23 /*
24  * Converts the 'req' to an afb_request.
25  */
26 static inline struct afb_request *afb_req_to_request(struct afb_req req)
27 {
28         return req.closure;
29 }
30
31 /*
32  * Checks whether the request 'req' is valid or not.
33  *
34  * Returns 0 if not valid or 1 if valid.
35  */
36 static inline int afb_req_is_valid(struct afb_req req)
37 {
38         return !!req.itf;
39 }
40
41 /*
42  * Gets from the request 'req' the argument of 'name'.
43  * Returns a PLAIN structure of type 'struct afb_arg'.
44  * When the argument of 'name' is not found, all fields of result are set to NULL.
45  * When the argument of 'name' is found, the fields are filled,
46  * in particular, the field 'result.name' is set to 'name'.
47  *
48  * There is a special name value: the empty string.
49  * The argument of name "" is defined only if the request was made using
50  * an HTTP POST of Content-Type "application/json". In that case, the
51  * argument of name "" receives the value of the body of the HTTP request.
52  */
53 static inline struct afb_arg afb_req_get(struct afb_req req, const char *name)
54 {
55         return req.itf->get(req.closure, name);
56 }
57
58 /*
59  * Gets from the request 'req' the string value of the argument of 'name'.
60  * Returns NULL if when there is no argument of 'name'.
61  * Returns the value of the argument of 'name' otherwise.
62  *
63  * Shortcut for: afb_req_get(req, name).value
64  */
65 static inline const char *afb_req_value(struct afb_req req, const char *name)
66 {
67         return afb_req_get(req, name).value;
68 }
69
70 /*
71  * Gets from the request 'req' the path for file attached to the argument of 'name'.
72  * Returns NULL if when there is no argument of 'name' or when there is no file.
73  * Returns the path of the argument of 'name' otherwise.
74  *
75  * Shortcut for: afb_req_get(req, name).path
76  */
77 static inline const char *afb_req_path(struct afb_req req, const char *name)
78 {
79         return afb_req_get(req, name).path;
80 }
81
82 /*
83  * Gets from the request 'req' the json object hashing the arguments.
84  * The returned object must not be released using 'json_object_put'.
85  */
86 static inline struct json_object *afb_req_json(struct afb_req req)
87 {
88         return req.itf->json(req.closure);
89 }
90
91 /*
92  * Sends a reply of kind success to the request 'req'.
93  * The status of the reply is automatically set to "success".
94  * Its send the object 'obj' (can be NULL) with an
95  * informationnal comment 'info (can also be NULL).
96  *
97  * For convenience, the function calls 'json_object_put' for 'obj'.
98  * Thus, in the case where 'obj' should remain available after
99  * the function returns, the function 'json_object_get' shall be used.
100  */
101 static inline void afb_req_success(struct afb_req req, struct json_object *obj, const char *info)
102 {
103         req.itf->success(req.closure, obj, info);
104 }
105
106 /*
107  * Same as 'afb_req_success' but the 'info' is a formatting
108  * string followed by arguments.
109  *
110  * For convenience, the function calls 'json_object_put' for 'obj'.
111  * Thus, in the case where 'obj' should remain available after
112  * the function returns, the function 'json_object_get' shall be used.
113  */
114 static inline void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...) __attribute__((format(printf, 3, 4)));
115 static inline void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...)
116 {
117         va_list args;
118         va_start(args, info);
119         req.itf->vsuccess(req.closure, obj, info, args);
120         va_end(args);
121 }
122
123 /*
124  * Same as 'afb_req_success_f' but the arguments to the format 'info'
125  * are given as a variable argument list instance.
126  *
127  * For convenience, the function calls 'json_object_put' for 'obj'.
128  * Thus, in the case where 'obj' should remain available after
129  * the function returns, the function 'json_object_get' shall be used.
130  */
131 static inline void afb_req_success_v(struct afb_req req, struct json_object *obj, const char *info, va_list args)
132 {
133         req.itf->vsuccess(req.closure, obj, info, args);
134 }
135
136 /*
137  * Sends a reply of kind failure to the request 'req'.
138  * The status of the reply is set to 'status' and an
139  * informationnal comment 'info' (can also be NULL) can be added.
140  *
141  * Note that calling afb_req_fail("success", info) is equivalent
142  * to call afb_req_success(NULL, info). Thus even if possible it
143  * is strongly recommanded to NEVER use "success" for status.
144  */
145 static inline void afb_req_fail(struct afb_req req, const char *status, const char *info)
146 {
147         req.itf->fail(req.closure, status, info);
148 }
149
150 /*
151  * Same as 'afb_req_fail' but the 'info' is a formatting
152  * string followed by arguments.
153  */
154 static inline void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...) __attribute__((format(printf, 3, 4)));
155 static inline void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...)
156 {
157         va_list args;
158         va_start(args, info);
159         req.itf->vfail(req.closure, status, info, args);
160         va_end(args);
161 }
162
163 /*
164  * Same as 'afb_req_fail_f' but the arguments to the format 'info'
165  * are given as a variable argument list instance.
166  */
167 static inline void afb_req_fail_v(struct afb_req req, const char *status, const char *info, va_list args)
168 {
169         req.itf->vfail(req.closure, status, info, args);
170 }
171
172 /*
173  * Gets the pointer stored by the binding for the session of 'req'.
174  * When the binding has not yet recorded a pointer, NULL is returned.
175  */
176 static inline void *afb_req_context_get(struct afb_req req)
177 {
178         return req.itf->context_get(req.closure);
179 }
180
181 /*
182  * Stores for the binding the pointer 'context' to the session of 'req'.
183  * The function 'free_context' will be called when the session is closed
184  * or if binding stores an other pointer.
185  */
186 static inline void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*))
187 {
188         req.itf->context_set(req.closure, context, free_context);
189 }
190
191 /*
192  * Gets the pointer stored by the binding for the session of 'req'.
193  * If the stored pointer is NULL, indicating that no pointer was
194  * already stored, afb_req_context creates a new context by calling
195  * the function 'create_context' and stores it with the freeing function
196  * 'free_context'.
197  */
198 static inline void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*))
199 {
200         return req.itf->context_make(req.closure, 0, (void *(*)(void*))(void*)create_context, free_context, 0);
201 }
202
203 /*
204  * Gets the pointer stored by the binding for the session of 'request'.
205  * If no previous pointer is stored or if 'replace' is not zero, a new value
206  * is generated using the function 'create_context' called with the 'closure'.
207  * If 'create_context' is NULL the generated value is 'closure'.
208  * When a value is created, the function 'free_context' is recorded and will
209  * be called (with the created value as argument) to free the created value when
210  * it is not more used.
211  * This function is atomic: it ensures that 2 threads will not race together.
212  */
213 static inline void *afb_req_context_make(struct afb_req req, int replace, void *(*create_context)(void *closure), void (*free_context)(void*), void *closure)
214 {
215         return req.itf->context_make(req.closure, replace, create_context, free_context, closure);
216 }
217
218 /*
219  * Frees the pointer stored by the binding for the session of 'req'
220  * and sets it to NULL.
221  *
222  * Shortcut for: afb_req_context_set(req, NULL, NULL)
223  */
224 static inline void afb_req_context_clear(struct afb_req req)
225 {
226         afb_req_context_set(req, 0, 0);
227 }
228
229 /*
230  * Adds one to the count of references of 'req'.
231  * This function MUST be called by asynchronous implementations
232  * of verbs if no reply was sent before returning.
233  */
234 static inline void afb_req_addref(struct afb_req req)
235 {
236         req.itf->addref(req.closure);
237 }
238
239 /*
240  * Substracts one to the count of references of 'req'.
241  * This function MUST be called by asynchronous implementations
242  * of verbs after sending the asynchronous reply.
243  */
244 static inline void afb_req_unref(struct afb_req req)
245 {
246         req.itf->unref(req.closure);
247 }
248
249 /*
250  * Closes the session associated with 'req'
251  * and delete all associated contexts.
252  */
253 static inline void afb_req_session_close(struct afb_req req)
254 {
255         req.itf->session_close(req.closure);
256 }
257
258 /*
259  * Sets the level of assurance of the session of 'req'
260  * to 'level'. The effect of this function is subject of
261  * security policies.
262  * Returns 1 on success or 0 if failed.
263  */
264 static inline int afb_req_session_set_LOA(struct afb_req req, unsigned level)
265 {
266         return req.itf->session_set_LOA(req.closure, level);
267 }
268
269 /*
270  * Establishes for the client link identified by 'req' a subscription
271  * to the 'event'.
272  * Returns 0 in case of successful subscription or -1 in case of error.
273  */
274 static inline int afb_req_subscribe(struct afb_req req, struct afb_event event)
275 {
276         return req.itf->subscribe(req.closure, event);
277 }
278
279 /*
280  * Revokes the subscription established to the 'event' for the client
281  * link identified by 'req'.
282  * Returns 0 in case of successful subscription or -1 in case of error.
283  */
284 static inline int afb_req_unsubscribe(struct afb_req req, struct afb_event event)
285 {
286         return req.itf->unsubscribe(req.closure, event);
287 }
288
289 /*
290  * Makes a call to the method of name 'api' / 'verb' with the object 'args'.
291  * This call is made in the context of the request 'req'.
292  * On completion, the function 'callback' is invoked with the
293  * 'closure' given at call and two other parameters: 'iserror' and 'result'.
294  * 'status' is 0 on success or negative when on an error reply.
295  * 'result' is the json object of the reply, you must not call json_object_put
296  * on the result.
297  *
298  * For convenience, the function calls 'json_object_put' for 'args'.
299  * Thus, in the case where 'args' should remain available after
300  * the function returns, the function 'json_object_get' shall be used.
301  *
302  * See also:
303  *  - 'afb_req_subcall_req' that is convenient to keep request alive automatically.
304  *  - 'afb_req_subcall_sync' the synchronous version
305  */
306 static inline void afb_req_subcall(struct afb_req req, const char *api, const char *verb, struct json_object *args, void (*callback)(void *closure, int iserror, struct json_object *result), void *closure)
307 {
308         req.itf->subcall(req.closure, api, verb, args, callback, closure);
309 }
310
311 /*
312  * Makes a call to the method of name 'api' / 'verb' with the object 'args'.
313  * This call is made in the context of the request 'req'.
314  * On completion, the function 'callback' is invoked with the
315  * original request 'req', the 'closure' given at call and two
316  * other parameters: 'iserror' and 'result'.
317  * 'status' is 0 on success or negative when on an error reply.
318  * 'result' is the json object of the reply, you must not call json_object_put
319  * on the result.
320  *
321  * For convenience, the function calls 'json_object_put' for 'args'.
322  * Thus, in the case where 'args' should remain available after
323  * the function returns, the function 'json_object_get' shall be used.
324  *
325  * See also:
326  *  - 'afb_req_subcall' that doesn't keep request alive automatically.
327  *  - 'afb_req_subcall_sync' the synchronous version
328  */
329 static inline void afb_req_subcall_req(struct afb_req req, const char *api, const char *verb, struct json_object *args, void (*callback)(void *closure, int iserror, struct json_object *result, struct afb_req req), void *closure)
330 {
331         req.itf->subcall_req(req.closure, api, verb, args, callback, closure);
332 }
333
334 /*
335  * Makes a call to the method of name 'api' / 'verb' with the object 'args'.
336  * This call is made in the context of the request 'req'.
337  * This call is synchronous, it waits untill completion of the request.
338  * It returns 0 on success or a negative value on error answer.
339  * The object pointed by 'result' is filled and must be released by the caller
340  * after its use by calling 'json_object_put'.
341  *
342  * For convenience, the function calls 'json_object_put' for 'args'.
343  * Thus, in the case where 'args' should remain available after
344  * the function returns, the function 'json_object_get' shall be used.
345  *
346  * See also:
347  *  - 'afb_req_subcall_req' that is convenient to keep request alive automatically.
348  *  - 'afb_req_subcall' that doesn't keep request alive automatically.
349  */
350 static inline int afb_req_subcall_sync(struct afb_req req, const char *api, const char *verb, struct json_object *args, struct json_object **result)
351 {
352         return req.itf->subcallsync(req.closure, api, verb, args, result);
353 }
354
355 /*
356  * Send associated to 'req' a message described by 'fmt' and following parameters
357  * to the journal for the verbosity 'level'.
358  *
359  * 'file', 'line' and 'func' are indicators of position of the code in source files
360  * (see macros __FILE__, __LINE__ and __func__).
361  *
362  * 'level' is defined by syslog standard:
363  *      EMERGENCY         0        System is unusable
364  *      ALERT             1        Action must be taken immediately
365  *      CRITICAL          2        Critical conditions
366  *      ERROR             3        Error conditions
367  *      WARNING           4        Warning conditions
368  *      NOTICE            5        Normal but significant condition
369  *      INFO              6        Informational
370  *      DEBUG             7        Debug-level messages
371  */
372 static inline void afb_req_verbose(struct afb_req req, int level, const char *file, int line, const char * func, const char *fmt, ...) __attribute__((format(printf, 6, 7)));
373 static inline void afb_req_verbose(struct afb_req req, int level, const char *file, int line, const char * func, const char *fmt, ...)
374 {
375         va_list args;
376         va_start(args, fmt);
377         req.itf->vverbose(req.closure, level, file, line, func, fmt, args);
378         va_end(args);
379 }
380
381 /* macro for setting file, line and function automatically */
382 # if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_DETAILS)
383 #define AFB_REQ_VERBOSE(req,level,...) afb_req_verbose(req,level,__FILE__,__LINE__,__func__,__VA_ARGS__)
384 #else
385 #define AFB_REQ_VERBOSE(req,level,...) afb_req_verbose(req,level,NULL,0,NULL,__VA_ARGS__)
386 #endif
387
388 /*
389  * Check whether the 'permission' is granted or not to the client
390  * identified by 'req'.
391  *
392  * Returns 1 if the permission is granted or 0 otherwise.
393  */
394 static inline int afb_req_has_permission(struct afb_req req, const char *permission)
395 {
396         return req.itf->has_permission(req.closure, permission);
397 }
398
399 /*
400  * Get the application identifier of the client application for the
401  * request 'req'.
402  *
403  * Returns the application identifier or NULL when the application
404  * can not be identified.
405  *
406  * The returned value if not NULL must be freed by the caller
407  */
408 static inline char *afb_req_get_application_id(struct afb_req req)
409 {
410         return req.itf->get_application_id(req.closure);
411 }
412
413 /*
414  * Get the user identifier (UID) of the client application for the
415  * request 'req'.
416  *
417  * Returns -1 when the application can not be identified.
418  */
419 static inline int afb_req_get_uid(struct afb_req req)
420 {
421         return req.itf->get_uid(req.closure);
422 }
423