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