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