Provide API and VERB name of requests
[src/app-framework-binder.git] / src / afb-export.c
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 #define _GNU_SOURCE
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23
24 #include <json-c/json.h>
25
26 #define AFB_BINDING_VERSION 0
27 #include <afb/afb-binding.h>
28
29 #include "afb-api.h"
30 #include "afb-apiset.h"
31 #include "afb-api-dyn.h"
32 #include "afb-common.h"
33 #include "afb-cred.h"
34 #include "afb-evt.h"
35 #include "afb-export.h"
36 #include "afb-hook.h"
37 #include "afb-msg-json.h"
38 #include "afb-session.h"
39 #include "afb-xreq.h"
40 #include "jobs.h"
41 #include "verbose.h"
42
43 /*************************************************************************
44  * internal types and structures
45  ************************************************************************/
46
47 enum afb_api_version
48 {
49         Api_Version_Dyn = 0,
50         Api_Version_1 = 1,
51         Api_Version_2 = 2,
52 };
53
54 enum afb_api_state
55 {
56         Api_State_Pre_Init,
57         Api_State_Init,
58         Api_State_Run
59 };
60
61 struct afb_export
62 {
63         /* keep it first */
64         struct afb_dynapi dynapi;
65
66         /* name of the api */
67         char *apiname;
68
69         /* version of the api */
70         unsigned version: 4;
71
72         /* current state */
73         unsigned state: 4;
74
75         /* hooking flags */
76         int hookditf;
77         int hooksvc;
78
79         /* dynamic api */
80         struct afb_api_dyn *apidyn;
81
82         /* session for service */
83         struct afb_session *session;
84
85         /* apiset for service */
86         struct afb_apiset *apiset;
87
88         /* event listener for service or NULL */
89         struct afb_evt_listener *listener;
90
91         /* start function */
92         union {
93                 int (*v1)(struct afb_service);
94                 int (*v2)();
95                 int (*vdyn)(struct afb_dynapi *dynapi);
96         } init;
97
98         /* event handling */
99         union {
100                 void (*v12)(const char *event, struct json_object *object);
101                 void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object);
102         } on_event;
103
104         /* exported data */
105         union {
106                 struct afb_binding_interface_v1 v1;
107                 struct afb_binding_data_v2 *v2;
108         } export;
109 };
110
111 /************************************************************************************************************/
112
113 static inline struct afb_dynapi *to_dynapi(struct afb_export *export)
114 {
115         return (struct afb_dynapi*)export;
116 }
117
118 static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi)
119 {
120         return (struct afb_export*)dynapi;
121 }
122
123 /*************************************************************************************************************
124  *************************************************************************************************************
125  *************************************************************************************************************
126  *************************************************************************************************************
127                                            F R O M     D I T F
128  *************************************************************************************************************
129  *************************************************************************************************************
130  *************************************************************************************************************
131  *************************************************************************************************************/
132
133 /**********************************************
134 * normal flow
135 **********************************************/
136 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
137 {
138         char *p;
139         struct afb_export *export = closure;
140
141         if (!fmt || vasprintf(&p, fmt, args) < 0)
142                 vverbose(level, file, line, function, fmt, args);
143         else {
144                 verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
145                 free(p);
146         }
147 }
148
149 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
150 {
151         vverbose_cb(closure, level, file, line, NULL, fmt, args);
152 }
153
154 static struct afb_eventid *eventid_make_cb(void *closure, const char *name)
155 {
156         size_t plen, nlen;
157         char *event;
158         struct afb_export *export = closure;
159
160         /* check daemon state */
161         if (export->state == Api_State_Pre_Init) {
162                 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
163                 errno = EINVAL;
164                 return NULL;
165         }
166
167         /* makes the event name */
168         plen = strlen(export->apiname);
169         nlen = strlen(name);
170         event = alloca(nlen + plen + 2);
171         memcpy(event, export->apiname, plen);
172         event[plen] = '/';
173         memcpy(event + plen + 1, name, nlen + 1);
174
175         /* create the event */
176         return afb_evt_create_event(event);
177 }
178
179 static struct afb_event event_make_cb(void *closure, const char *name)
180 {
181         struct afb_eventid *eventid = eventid_make_cb(closure, name);
182         return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
183 }
184
185 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
186 {
187         size_t plen, nlen;
188         char *event;
189         struct afb_export *export = closure;
190
191         /* check daemon state */
192         if (export->state == Api_State_Pre_Init) {
193                 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->apiname, name, json_object_to_json_string(object));
194                 errno = EINVAL;
195                 return 0;
196         }
197
198         /* makes the event name */
199         plen = strlen(export->apiname);
200         nlen = strlen(name);
201         event = alloca(nlen + plen + 2);
202         memcpy(event, export->apiname, plen);
203         event[plen] = '/';
204         memcpy(event + plen + 1, name, nlen + 1);
205
206         /* broadcast the event */
207         return afb_evt_broadcast(event, object);
208 }
209
210 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
211 {
212         return afb_common_rootdir_open_locale(filename, flags, locale);
213 }
214
215 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
216 {
217         return jobs_queue(group, timeout, callback, argument);
218 }
219
220 static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
221 {
222         return afb_xreq_unstore(sreq);
223 }
224
225 static int require_api_cb(void *closure, const char *name, int initialized)
226 {
227         struct afb_export *export = closure;
228         if (export->state != Api_State_Init) {
229                 ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
230                 errno = EINVAL;
231                 return -1;
232         }
233         return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
234 }
235
236 static int rename_api_cb(void *closure, const char *name)
237 {
238         struct afb_export *export = closure;
239         if (export->state != Api_State_Pre_Init) {
240                 ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
241                 errno = EINVAL;
242                 return -1;
243         }
244         if (!afb_api_is_valid_name(name)) {
245                 ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
246                 errno = EINVAL;
247                 return -1;
248         }
249         NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
250         afb_export_rename(export, name);
251         return 0;
252 }
253
254 static int api_new_api_cb(
255                 void *closure,
256                 const char *api,
257                 const char *info,
258                 int (*preinit)(void*, struct afb_dynapi *),
259                 void *preinit_closure)
260 {
261         struct afb_export *export = closure;
262         return afb_api_dyn_add(export->apiset, api, info, preinit, preinit_closure);
263 }
264
265 /**********************************************
266 * hooked flow
267 **********************************************/
268 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
269 {
270         struct afb_export *export = closure;
271         va_list ap;
272         va_copy(ap, args);
273         vverbose_cb(closure, level, file, line, function, fmt, args);
274         afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
275         va_end(ap);
276 }
277
278 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
279 {
280         hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
281 }
282
283 static struct afb_eventid *hooked_eventid_make_cb(void *closure, const char *name)
284 {
285         struct afb_export *export = closure;
286         struct afb_eventid *r = eventid_make_cb(closure, name);
287         afb_hook_ditf_event_make(export, name, r);
288         return r;
289 }
290
291 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
292 {
293         struct afb_eventid *eventid = hooked_eventid_make_cb(closure, name);
294         return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
295 }
296
297 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
298 {
299         int r;
300         struct afb_export *export = closure;
301         json_object_get(object);
302         afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
303         r = event_broadcast_cb(closure, name, object);
304         afb_hook_ditf_event_broadcast_after(export, name, object, r);
305         json_object_put(object);
306         return r;
307 }
308
309 static struct sd_event *hooked_get_event_loop(void *closure)
310 {
311         struct afb_export *export = closure;
312         struct sd_event *r = afb_common_get_event_loop();
313         return afb_hook_ditf_get_event_loop(export, r);
314 }
315
316 static struct sd_bus *hooked_get_user_bus(void *closure)
317 {
318         struct afb_export *export = closure;
319         struct sd_bus *r = afb_common_get_user_bus();
320         return afb_hook_ditf_get_user_bus(export, r);
321 }
322
323 static struct sd_bus *hooked_get_system_bus(void *closure)
324 {
325         struct afb_export *export = closure;
326         struct sd_bus *r = afb_common_get_system_bus();
327         return afb_hook_ditf_get_system_bus(export, r);
328 }
329
330 static int hooked_rootdir_get_fd(void *closure)
331 {
332         struct afb_export *export = closure;
333         int r = afb_common_rootdir_get_fd();
334         return afb_hook_ditf_rootdir_get_fd(export, r);
335 }
336
337 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
338 {
339         struct afb_export *export = closure;
340         int r = rootdir_open_locale_cb(closure, filename, flags, locale);
341         return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
342 }
343
344 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
345 {
346         struct afb_export *export = closure;
347         int r = queue_job_cb(closure, callback, argument, group, timeout);
348         return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
349 }
350
351 static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
352 {
353         struct afb_export *export = closure;
354         afb_hook_ditf_unstore_req(export, sreq);
355         return unstore_req_cb(closure, sreq);
356 }
357
358 static int hooked_require_api_cb(void *closure, const char *name, int initialized)
359 {
360         int result;
361         struct afb_export *export = closure;
362         afb_hook_ditf_require_api(export, name, initialized);
363         result = require_api_cb(closure, name, initialized);
364         return afb_hook_ditf_require_api_result(export, name, initialized, result);
365 }
366
367 static int hooked_rename_api_cb(void *closure, const char *name)
368 {
369         struct afb_export *export = closure;
370         const char *oldname = export->apiname;
371         int result = rename_api_cb(closure, name);
372         return afb_hook_ditf_rename_api(export, oldname, name, result);
373 }
374
375 static int hooked_api_new_api_cb(
376                 void *closure,
377                 const char *api,
378                 const char *info,
379                 int (*preinit)(void*, struct afb_dynapi *),
380                 void *preinit_closure)
381 {
382         /* TODO */
383         return api_new_api_cb(closure, api, info, preinit, preinit_closure);
384 }
385 /**********************************************
386 * vectors
387 **********************************************/
388 static const struct afb_daemon_itf daemon_itf = {
389         .vverbose_v1 = old_vverbose_cb,
390         .vverbose_v2 = vverbose_cb,
391         .event_make = event_make_cb,
392         .event_broadcast = event_broadcast_cb,
393         .get_event_loop = afb_common_get_event_loop,
394         .get_user_bus = afb_common_get_user_bus,
395         .get_system_bus = afb_common_get_system_bus,
396         .rootdir_get_fd = afb_common_rootdir_get_fd,
397         .rootdir_open_locale = rootdir_open_locale_cb,
398         .queue_job = queue_job_cb,
399         .unstore_req = unstore_req_cb,
400         .require_api = require_api_cb,
401         .rename_api = rename_api_cb,
402         .new_api = api_new_api_cb,
403 };
404
405 static const struct afb_daemon_itf hooked_daemon_itf = {
406         .vverbose_v1 = hooked_old_vverbose_cb,
407         .vverbose_v2 = hooked_vverbose_cb,
408         .event_make = hooked_event_make_cb,
409         .event_broadcast = hooked_event_broadcast_cb,
410         .get_event_loop = hooked_get_event_loop,
411         .get_user_bus = hooked_get_user_bus,
412         .get_system_bus = hooked_get_system_bus,
413         .rootdir_get_fd = hooked_rootdir_get_fd,
414         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
415         .queue_job = hooked_queue_job_cb,
416         .unstore_req = hooked_unstore_req_cb,
417         .require_api = hooked_require_api_cb,
418         .rename_api = hooked_rename_api_cb,
419         .new_api = hooked_api_new_api_cb,
420 };
421
422 /*************************************************************************************************************
423  *************************************************************************************************************
424  *************************************************************************************************************
425  *************************************************************************************************************
426                                            F R O M     S V C
427  *************************************************************************************************************
428  *************************************************************************************************************
429  *************************************************************************************************************
430  *************************************************************************************************************/
431
432 /* the common session for services sharing their session */
433 static struct afb_session *common_session;
434
435 /*************************************************************************************************************
436  *************************************************************************************************************
437  *************************************************************************************************************
438  *************************************************************************************************************
439                                            F R O M     S V C
440  *************************************************************************************************************
441  *************************************************************************************************************
442  *************************************************************************************************************
443  *************************************************************************************************************/
444
445 /*
446  * Structure for requests initiated by the service
447  */
448 struct call_req
449 {
450         struct afb_xreq xreq;
451
452         struct afb_export *export;
453
454         /* the args */
455         union {
456                 void (*callback)(void*, int, struct json_object*);
457                 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
458         };
459         void *closure;
460
461         /* sync */
462         struct jobloop *jobloop;
463         struct json_object *result;
464         int status;
465 };
466
467 /*
468  * destroys the call_req
469  */
470 static void callreq_destroy(struct afb_xreq *xreq)
471 {
472         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
473
474         afb_context_disconnect(&callreq->xreq.context);
475         json_object_put(callreq->xreq.json);
476         afb_cred_unref(callreq->xreq.cred);
477         free(callreq);
478 }
479
480 static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj)
481 {
482         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
483         if (callreq->callback)
484                 callreq->callback(callreq->closure, status, obj);
485         json_object_put(obj);
486 }
487
488 static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj)
489 {
490         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
491         if (callreq->callback_dynapi)
492                 callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export));
493         json_object_put(obj);
494 }
495
496 static void callreq_sync_leave(struct call_req *callreq)
497 {
498         struct jobloop *jobloop = callreq->jobloop;
499
500         if (jobloop) {
501                 callreq->jobloop = NULL;
502                 jobs_leave(jobloop);
503         }
504 }
505
506 static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
507 {
508         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
509         callreq->status = status;
510         callreq->result = obj;
511         callreq_sync_leave(callreq);
512 }
513
514 static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
515 {
516         struct call_req *callreq = closure;
517
518         if (!signum) {
519                 callreq->jobloop = jobloop;
520                 afb_xreq_process(&callreq->xreq, callreq->export->apiset);
521         } else {
522                 callreq->result = afb_msg_json_internal_error();
523                 callreq->status = -1;
524                 callreq_sync_leave(callreq);
525         }
526 }
527
528 /* interface for requests of services */
529 const struct afb_xreq_query_itf afb_export_xreq_async_itf = {
530         .unref = callreq_destroy,
531         .reply = callreq_reply_async
532 };
533
534 /* interface for requests of services */
535 const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = {
536         .unref = callreq_destroy,
537         .reply = callreq_reply_async_dynapi
538 };
539
540 /* interface for requests of services */
541 const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
542         .unref = callreq_destroy,
543         .reply = callreq_reply_sync
544 };
545
546 /*
547  * create an call_req
548  */
549 static struct call_req *callreq_create(
550                 struct afb_export *export,
551                 const char *api,
552                 const char *verb,
553                 struct json_object *args,
554                 const struct afb_xreq_query_itf *itf)
555 {
556         struct call_req *callreq;
557         size_t lenapi, lenverb;
558         char *copy;
559
560         /* allocates the request */
561         lenapi = 1 + strlen(api);
562         lenverb = 1 + strlen(verb);
563         callreq = malloc(lenapi + lenverb + sizeof *callreq);
564         if (callreq != NULL) {
565                 /* initialises the request */
566                 afb_xreq_init(&callreq->xreq, itf);
567                 afb_context_init(&callreq->xreq.context, export->session, NULL);
568                 callreq->xreq.context.validated = 1;
569                 copy = (char*)&callreq[1];
570                 memcpy(copy, api, lenapi);
571                 callreq->xreq.request.api = copy;
572                 copy = &copy[lenapi];
573                 memcpy(copy, verb, lenverb);
574                 callreq->xreq.request.verb = copy;
575                 callreq->xreq.listener = export->listener;
576                 callreq->xreq.json = args;
577                 callreq->export = export;
578         }
579         return callreq;
580 }
581
582 /*
583  * Initiates a call for the service
584  */
585 static void svc_call(
586                 void *closure,
587                 const char *api,
588                 const char *verb,
589                 struct json_object *args,
590                 void (*callback)(void*, int, struct json_object*),
591                 void *cbclosure)
592 {
593         struct afb_export *export = closure;
594         struct call_req *callreq;
595         struct json_object *ierr;
596
597         /* allocates the request */
598         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf);
599         if (callreq == NULL) {
600                 ERROR("out of memory");
601                 json_object_put(args);
602                 ierr = afb_msg_json_internal_error();
603                 if (callback)
604                         callback(cbclosure, -1, ierr);
605                 json_object_put(ierr);
606                 return;
607         }
608
609         /* initialises the request */
610         callreq->jobloop = NULL;
611         callreq->callback = callback;
612         callreq->closure = cbclosure;
613
614         /* terminates and frees ressources if needed */
615         afb_xreq_process(&callreq->xreq, export->apiset);
616 }
617
618 static void svc_call_dynapi(
619                 struct afb_dynapi *dynapi,
620                 const char *api,
621                 const char *verb,
622                 struct json_object *args,
623                 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
624                 void *cbclosure)
625 {
626         struct afb_export *export = from_dynapi(dynapi);
627         struct call_req *callreq;
628         struct json_object *ierr;
629
630         /* allocates the request */
631         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf);
632         if (callreq == NULL) {
633                 ERROR("out of memory");
634                 json_object_put(args);
635                 ierr = afb_msg_json_internal_error();
636                 if (callback)
637                         callback(cbclosure, -1, ierr, to_dynapi(export));
638                 json_object_put(ierr);
639                 return;
640         }
641
642         /* initialises the request */
643         callreq->jobloop = NULL;
644         callreq->callback_dynapi = callback;
645         callreq->closure = cbclosure;
646
647         /* terminates and frees ressources if needed */
648         afb_xreq_process(&callreq->xreq, export->apiset);
649 }
650
651 static int svc_call_sync(
652                 void *closure,
653                 const char *api,
654                 const char *verb,
655                 struct json_object *args,
656                 struct json_object **result)
657 {
658         struct afb_export *export = closure;
659         struct call_req *callreq;
660         struct json_object *resu;
661         int rc;
662
663         /* allocates the request */
664         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
665         if (callreq == NULL) {
666                 ERROR("out of memory");
667                 errno = ENOMEM;
668                 json_object_put(args);
669                 resu = afb_msg_json_internal_error();
670                 rc = -1;
671         } else {
672                 /* initialises the request */
673                 callreq->jobloop = NULL;
674                 callreq->callback = NULL;
675                 callreq->result = NULL;
676                 callreq->status = 0;
677                 afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
678                 rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
679                 if (rc >= 0)
680                         rc = callreq->status;
681                 resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
682                 afb_xreq_unhooked_unref(&callreq->xreq);
683         }
684         if (result)
685                 *result = resu;
686         else
687                 json_object_put(resu);
688         return rc;
689 }
690
691 struct hooked_call
692 {
693         struct afb_export *export;
694         union {
695                 void (*callback)(void*, int, struct json_object*);
696                 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
697         };
698         void *cbclosure;
699 };
700
701 static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
702 {
703         struct hooked_call *hc = closure;
704         afb_hook_svc_call_result(hc->export, status, result);
705         hc->callback(hc->cbclosure, status, result);
706         free(hc);
707 }
708
709 static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi)
710 {
711         struct hooked_call *hc = closure;
712         afb_hook_svc_call_result(hc->export, status, result);
713         hc->callback_dynapi(hc->cbclosure, status, result, dynapi);
714         free(hc);
715 }
716
717 static void svc_hooked_call(
718                 void *closure,
719                 const char *api,
720                 const char *verb,
721                 struct json_object *args,
722                 void (*callback)(void*, int, struct json_object*),
723                 void *cbclosure)
724 {
725         struct afb_export *export = closure;
726         struct hooked_call *hc;
727
728         if (export->hooksvc & afb_hook_flag_svc_call)
729                 afb_hook_svc_call(export, api, verb, args);
730
731         if (export->hooksvc & afb_hook_flag_svc_call_result) {
732                 hc = malloc(sizeof *hc);
733                 if (!hc)
734                         WARNING("allocation failed");
735                 else {
736                         hc->export = export;
737                         hc->callback = callback;
738                         hc->cbclosure = cbclosure;
739                         callback = svc_hooked_call_result;
740                         cbclosure = hc;
741                 }
742         }
743         svc_call(closure, api, verb, args, callback, cbclosure);
744 }
745
746 static void svc_hooked_call_dynapi(
747                 struct afb_dynapi *dynapi,
748                 const char *api,
749                 const char *verb,
750                 struct json_object *args,
751                 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
752                 void *cbclosure)
753 {
754         struct afb_export *export = from_dynapi(dynapi);
755         struct hooked_call *hc;
756
757         if (export->hooksvc & afb_hook_flag_svc_call)
758                 afb_hook_svc_call(export, api, verb, args);
759
760         if (export->hooksvc & afb_hook_flag_svc_call_result) {
761                 hc = malloc(sizeof *hc);
762                 if (!hc)
763                         WARNING("allocation failed");
764                 else {
765                         hc->export = export;
766                         hc->callback_dynapi = callback;
767                         hc->cbclosure = cbclosure;
768                         callback = svc_hooked_call_dynapi_result;
769                         cbclosure = hc;
770                 }
771         }
772         svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure);
773 }
774
775 static int svc_hooked_call_sync(
776                 void *closure,
777                 const char *api,
778                 const char *verb,
779                 struct json_object *args,
780                 struct json_object **result)
781 {
782         struct afb_export *export = closure;
783         struct json_object *resu;
784         int rc;
785
786         if (export->hooksvc & afb_hook_flag_svc_callsync)
787                 afb_hook_svc_callsync(export, api, verb, args);
788
789         rc = svc_call_sync(closure, api, verb, args, &resu);
790
791         if (export->hooksvc & afb_hook_flag_svc_callsync_result)
792                 afb_hook_svc_callsync_result(export, rc, resu);
793
794         if (result)
795                 *result = resu;
796         else
797                 json_object_put(resu);
798
799         return rc;
800 }
801
802 /* the interface for services */
803 static const struct afb_service_itf service_itf = {
804         .call = svc_call,
805         .call_sync = svc_call_sync
806 };
807
808 /* the interface for services */
809 static const struct afb_service_itf hooked_service_itf = {
810         .call = svc_hooked_call,
811         .call_sync = svc_hooked_call_sync
812 };
813
814 /*************************************************************************************************************
815  *************************************************************************************************************
816  *************************************************************************************************************
817  *************************************************************************************************************
818                                            F R O M     D Y N A P I
819  *************************************************************************************************************
820  *************************************************************************************************************
821  *************************************************************************************************************
822  *************************************************************************************************************/
823
824 static int api_set_verbs_v2_cb(
825                 struct afb_dynapi *dynapi,
826                 const struct afb_verb_v2 *verbs)
827 {
828         struct afb_export *export = from_dynapi(dynapi);
829
830         if (export->apidyn) {
831                 afb_api_dyn_set_verbs_v2(export->apidyn, verbs);
832                 return 0;
833         }
834
835         errno = EPERM;
836         return -1;
837 }
838
839 static int api_add_verb_cb(
840                 struct afb_dynapi *dynapi,
841                 const char *verb,
842                 const char *info,
843                 void (*callback)(struct afb_request *request),
844                 void *vcbdata,
845                 const struct afb_auth *auth,
846                 uint32_t session)
847 {
848         struct afb_export *export = from_dynapi(dynapi);
849
850         if (export->apidyn)
851                 return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, vcbdata, auth, session);
852
853         errno = EPERM;
854         return -1;
855 }
856
857 static int api_sub_verb_cb(
858                 struct afb_dynapi *dynapi,
859                 const char *verb)
860 {
861         struct afb_export *export = from_dynapi(dynapi);
862
863         if (export->apidyn)
864                 return afb_api_dyn_sub_verb(export->apidyn, verb);
865
866         errno = EPERM;
867         return -1;
868 }
869
870 static int api_set_on_event_cb(
871                 struct afb_dynapi *dynapi,
872                 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
873 {
874         struct afb_export *export = from_dynapi(dynapi);
875         return afb_export_handle_events_vdyn(export, onevent);
876 }
877
878 static int api_set_on_init_cb(
879                 struct afb_dynapi *dynapi,
880                 int (*oninit)(struct afb_dynapi *dynapi))
881 {
882         struct afb_export *export = from_dynapi(dynapi);
883
884         return afb_export_handle_init_vdyn(export, oninit);
885 }
886
887 static void api_seal_cb(
888                 struct afb_dynapi *dynapi)
889 {
890         struct afb_export *export = from_dynapi(dynapi);
891
892         export->apidyn = NULL;
893 }
894
895 static int hooked_api_set_verbs_v2_cb(
896                 struct afb_dynapi *dynapi,
897                 const struct afb_verb_v2 *verbs)
898 {
899         /* TODO */
900         return api_set_verbs_v2_cb(dynapi, verbs);
901 }
902
903 static int hooked_api_add_verb_cb(
904                 struct afb_dynapi *dynapi,
905                 const char *verb,
906                 const char *info,
907                 void (*callback)(struct afb_request *request),
908                 void *vcbdata,
909                 const struct afb_auth *auth,
910                 uint32_t session)
911 {
912         /* TODO */
913         return api_add_verb_cb(dynapi, verb, info, callback, vcbdata, auth, session);
914 }
915
916 static int hooked_api_sub_verb_cb(
917                 struct afb_dynapi *dynapi,
918                 const char *verb)
919 {
920         /* TODO */
921         return api_sub_verb_cb(dynapi, verb);
922 }
923
924 static int hooked_api_set_on_event_cb(
925                 struct afb_dynapi *dynapi,
926                 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
927 {
928         /* TODO */
929         return api_set_on_event_cb(dynapi, onevent);
930 }
931
932 static int hooked_api_set_on_init_cb(
933                 struct afb_dynapi *dynapi,
934                 int (*oninit)(struct afb_dynapi *dynapi))
935 {
936         /* TODO */
937         return api_set_on_init_cb(dynapi, oninit);
938 }
939
940 static void hooked_api_seal_cb(
941                 struct afb_dynapi *dynapi)
942 {
943         /* TODO */
944         api_seal_cb(dynapi);
945 }
946
947 static const struct afb_dynapi_itf dynapi_itf = {
948
949         .vverbose = (void*)vverbose_cb,
950
951         .get_event_loop = afb_common_get_event_loop,
952         .get_user_bus = afb_common_get_user_bus,
953         .get_system_bus = afb_common_get_system_bus,
954         .rootdir_get_fd = afb_common_rootdir_get_fd,
955         .rootdir_open_locale = rootdir_open_locale_cb,
956         .queue_job = queue_job_cb,
957
958         .require_api = require_api_cb,
959         .rename_api = rename_api_cb,
960
961         .event_broadcast = event_broadcast_cb,
962         .eventid_make = eventid_make_cb,
963
964         .call = svc_call_dynapi,
965         .call_sync = svc_call_sync,
966
967         .api_new_api = api_new_api_cb,
968         .api_set_verbs_v2 = api_set_verbs_v2_cb,
969         .api_add_verb = api_add_verb_cb,
970         .api_sub_verb = api_sub_verb_cb,
971         .api_set_on_event = api_set_on_event_cb,
972         .api_set_on_init = api_set_on_init_cb,
973         .api_seal = api_seal_cb,
974 };
975
976 static const struct afb_dynapi_itf hooked_dynapi_itf = {
977
978         .vverbose = hooked_vverbose_cb,
979
980         .get_event_loop = hooked_get_event_loop,
981         .get_user_bus = hooked_get_user_bus,
982         .get_system_bus = hooked_get_system_bus,
983         .rootdir_get_fd = hooked_rootdir_get_fd,
984         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
985         .queue_job = hooked_queue_job_cb,
986
987         .require_api = hooked_require_api_cb,
988         .rename_api = hooked_rename_api_cb,
989
990         .event_broadcast = hooked_event_broadcast_cb,
991         .eventid_make = hooked_eventid_make_cb,
992
993         .call = svc_hooked_call_dynapi,
994         .call_sync = svc_hooked_call_sync,
995
996         .api_new_api = hooked_api_new_api_cb,
997         .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
998         .api_add_verb = hooked_api_add_verb_cb,
999         .api_sub_verb = hooked_api_sub_verb_cb,
1000         .api_set_on_event = hooked_api_set_on_event_cb,
1001         .api_set_on_init = hooked_api_set_on_init_cb,
1002         .api_seal = hooked_api_seal_cb,
1003 };
1004
1005 /*************************************************************************************************************
1006  *************************************************************************************************************
1007  *************************************************************************************************************
1008  *************************************************************************************************************
1009                                            F R O M     S V C
1010  *************************************************************************************************************
1011  *************************************************************************************************************
1012  *************************************************************************************************************
1013  *************************************************************************************************************/
1014
1015 /*
1016  * Propagates the event to the service
1017  */
1018 static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
1019 {
1020         struct afb_export *export = closure;
1021
1022         if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1023                 afb_hook_svc_on_event_before(export, event, eventid, object);
1024         export->on_event.v12(event, object);
1025         if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1026                 afb_hook_svc_on_event_after(export, event, eventid, object);
1027         json_object_put(object);
1028 }
1029
1030 /* the interface for events */
1031 static const struct afb_evt_itf evt_v12_itf = {
1032         .broadcast = export_on_event_v12,
1033         .push = export_on_event_v12
1034 };
1035
1036 /*
1037  * Propagates the event to the service
1038  */
1039 static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object)
1040 {
1041         struct afb_export *export = closure;
1042
1043         if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1044                 afb_hook_svc_on_event_before(export, event, eventid, object);
1045         export->on_event.vdyn(to_dynapi(export), event, object);
1046         if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1047                 afb_hook_svc_on_event_after(export, event, eventid, object);
1048         json_object_put(object);
1049 }
1050
1051 /* the interface for events */
1052 static const struct afb_evt_itf evt_vdyn_itf = {
1053         .broadcast = export_on_event_vdyn,
1054         .push = export_on_event_vdyn
1055 };
1056
1057 /*************************************************************************************************************
1058  *************************************************************************************************************
1059  *************************************************************************************************************
1060  *************************************************************************************************************
1061                                            M E R G E D
1062  *************************************************************************************************************
1063  *************************************************************************************************************
1064  *************************************************************************************************************
1065  *************************************************************************************************************/
1066
1067 static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
1068 {
1069         struct afb_export *export;
1070
1071         /* session shared with other exports */
1072         if (common_session == NULL) {
1073                 common_session = afb_session_create (NULL, 0);
1074                 if (common_session == NULL)
1075                         return NULL;
1076         }
1077         export = calloc(1, sizeof *export);
1078         if (!export)
1079                 errno = ENOMEM;
1080         else {
1081                 memset(export, 0, sizeof *export);
1082                 export->apiname = strdup(apiname);
1083                 export->dynapi.apiname = export->apiname;
1084                 export->version = version;
1085                 export->state = Api_State_Pre_Init;
1086                 export->session = afb_session_addref(common_session);
1087                 export->apiset = afb_apiset_addref(apiset);
1088         }
1089         return export;
1090 }
1091
1092 void afb_export_destroy(struct afb_export *export)
1093 {
1094         if (export) {
1095                 if (export->listener != NULL)
1096                         afb_evt_listener_unref(export->listener);
1097                 afb_session_unref(export->session);
1098                 afb_apiset_unref(export->apiset);
1099                 free(export->apiname);
1100                 free(export);
1101         }
1102 }
1103
1104 struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *apiname, int (*init)(struct afb_service), void (*onevent)(const char*, struct json_object*))
1105 {
1106         struct afb_export *export = create(apiset, apiname, Api_Version_1);
1107         if (export) {
1108                 export->init.v1 = init;
1109                 export->on_event.v12 = onevent;
1110                 export->export.v1.mode = AFB_MODE_LOCAL;
1111                 export->export.v1.daemon.closure = export;
1112                 afb_export_verbosity_set(export, verbosity);
1113                 afb_export_update_hook(export);
1114         }
1115         return export;
1116 }
1117
1118 struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *apiname, struct afb_binding_data_v2 *data, int (*init)(), void (*onevent)(const char*, struct json_object*))
1119 {
1120         struct afb_export *export = create(apiset, apiname, Api_Version_2);
1121         if (export) {
1122                 export->init.v2 = init;
1123                 export->on_event.v12 = onevent;
1124                 export->export.v2 = data;
1125                 data->daemon.closure = export;
1126                 data->service.closure = export;
1127                 afb_export_verbosity_set(export, verbosity);
1128                 afb_export_update_hook(export);
1129         }
1130         return export;
1131 }
1132
1133 struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn)
1134 {
1135         struct afb_export *export = create(apiset, apiname, Api_Version_Dyn);
1136         if (export) {
1137                 export->apidyn = apidyn;
1138                 afb_export_verbosity_set(export, verbosity);
1139                 afb_export_update_hook(export);
1140         }
1141         return export;
1142 }
1143
1144 void afb_export_rename(struct afb_export *export, const char *apiname)
1145 {
1146         free(export->apiname);
1147         export->apiname = strdup(apiname);
1148         export->dynapi.apiname = export->apiname;
1149         afb_export_update_hook(export);
1150 }
1151
1152 const char *afb_export_apiname(const struct afb_export *export)
1153 {
1154         return export->apiname;
1155 }
1156
1157 void afb_export_update_hook(struct afb_export *export)
1158 {
1159         export->hookditf = afb_hook_flags_ditf(export->apiname);
1160         export->hooksvc = afb_hook_flags_svc(export->apiname);
1161         export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf;
1162
1163         switch (export->version) {
1164         case Api_Version_1:
1165                 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1166                 break;
1167         case Api_Version_2:
1168                 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1169                 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1170                 break;
1171         }
1172 }
1173
1174 struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
1175 {
1176         return export->version == Api_Version_1 ? &export->export.v1 : NULL;
1177 }
1178
1179 int afb_export_unshare_session(struct afb_export *export)
1180 {
1181         if (export->session == common_session) {
1182                 export->session = afb_session_create (NULL, 0);
1183                 if (export->session)
1184                         afb_session_unref(common_session);
1185                 else {
1186                         export->session = common_session;
1187                         return -1;
1188                 }
1189         }
1190         return 0;
1191 }
1192
1193 void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
1194 {
1195         struct afb_apiset *prvset = export->apiset;
1196         export->apiset = afb_apiset_addref(apiset);
1197         afb_apiset_unref(prvset);
1198 }
1199
1200 struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
1201 {
1202         return export->apiset;
1203 }
1204
1205 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1206 {
1207         /* check version */
1208         switch (export->version) {
1209         case Api_Version_1: case Api_Version_2: break;
1210         default:
1211                 ERROR("invalid version 12 for API %s", export->apiname);
1212                 errno = EINVAL;
1213                 return -1;
1214         }
1215
1216         /* set the event handler */
1217         if (!on_event) {
1218                 if (export->listener) {
1219                         afb_evt_listener_unref(export->listener);
1220                         export->listener = NULL;
1221                 }
1222                 export->on_event.v12 = on_event;
1223         } else {
1224                 export->on_event.v12 = on_event;
1225                 if (!export->listener) {
1226                         export->listener = afb_evt_listener_create(&evt_v12_itf, export);
1227                         if (export->listener == NULL)
1228                                 return -1;
1229                 }
1230         }
1231         return 0;
1232 }
1233
1234 int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
1235 {
1236         /* check version */
1237         switch (export->version) {
1238         case Api_Version_Dyn: break;
1239         default:
1240                 ERROR("invalid version Dyn for API %s", export->apiname);
1241                 errno = EINVAL;
1242                 return -1;
1243         }
1244
1245         /* set the event handler */
1246         if (!on_event) {
1247                 if (export->listener) {
1248                         afb_evt_listener_unref(export->listener);
1249                         export->listener = NULL;
1250                 }
1251                 export->on_event.vdyn = on_event;
1252         } else {
1253                 export->on_event.vdyn = on_event;
1254                 if (!export->listener) {
1255                         export->listener = afb_evt_listener_create(&evt_vdyn_itf, export);
1256                         if (export->listener == NULL)
1257                                 return -1;
1258                 }
1259         }
1260         return 0;
1261 }
1262
1263 int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi))
1264 {
1265         if (export->state != Api_State_Pre_Init) {
1266                 ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname);
1267                 errno = EINVAL;
1268                 return -1;
1269         }
1270
1271         export->init.vdyn  = oninit;
1272         return 0;
1273 }
1274
1275 /*
1276  * Starts a new service (v1)
1277  */
1278 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1279 {
1280         return regfun(&export->export.v1);
1281 }
1282
1283 int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure)
1284 {
1285         return preinit(closure, to_dynapi(export));
1286 }
1287
1288 int afb_export_verbosity_get(const struct afb_export *export)
1289 {
1290         return export->dynapi.verbosity;
1291 }
1292
1293 void afb_export_verbosity_set(struct afb_export *export, int level)
1294 {
1295         export->dynapi.verbosity = level;
1296         switch (export->version) {
1297         case Api_Version_1: export->export.v1.verbosity = level; break;
1298         case Api_Version_2: export->export.v2->verbosity = level; break;
1299         }
1300 }
1301
1302 /*************************************************************************************************************
1303  *************************************************************************************************************
1304  *************************************************************************************************************
1305  *************************************************************************************************************
1306                                            N E W
1307  *************************************************************************************************************
1308  *************************************************************************************************************
1309  *************************************************************************************************************
1310  *************************************************************************************************************/
1311
1312 int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
1313 {
1314         int rc;
1315
1316         /* check state */
1317         if (export->state != Api_State_Pre_Init) {
1318                 /* not an error when onneed */
1319                 if (onneed != 0)
1320                         goto done;
1321
1322                 /* already started: it is an error */
1323                 ERROR("Service of API %s already started", export->apiname);
1324                 return -1;
1325         }
1326
1327         /* unshare the session if asked */
1328         if (!share_session) {
1329                 rc = afb_export_unshare_session(export);
1330                 if (rc < 0) {
1331                         ERROR("Can't unshare the session for %s", export->apiname);
1332                         return -1;
1333                 }
1334         }
1335
1336         /* set event handling */
1337         switch (export->version) {
1338         case Api_Version_1:
1339         case Api_Version_2:
1340                 rc = afb_export_handle_events_v12(export, export->on_event.v12);
1341                 break;
1342         default:
1343                 rc = 0;
1344                 break;
1345         }
1346         if (rc < 0) {
1347                 ERROR("Can't set event handler for %s", export->apiname);
1348                 return -1;
1349         }
1350
1351         /* Starts the service */
1352         if (export->hooksvc & afb_hook_flag_svc_start_before)
1353                 afb_hook_svc_start_before(export);
1354         export->state = Api_State_Init;
1355         switch (export->version) {
1356         case Api_Version_1:
1357                 rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
1358                 break;
1359         case Api_Version_2:
1360                 rc = export->init.v2 ? export->init.v2() : 0;
1361                 break;
1362         case Api_Version_Dyn:
1363                 rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0;
1364                 break;
1365         default:
1366                 break;
1367         }
1368         export->state = Api_State_Run;
1369         if (export->hooksvc & afb_hook_flag_svc_start_after)
1370                 afb_hook_svc_start_after(export, rc);
1371         if (rc < 0) {
1372                 /* initialisation error */
1373                 ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);
1374                 return rc;
1375         }
1376
1377 done:
1378         return 0;
1379 }
1380