Add ability to provide binding settings
[src/app-framework-binder.git] / src / afb-export.c
1 /*
2  * Copyright (C) 2016, 2017, 2018 "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 #include <fnmatch.h>
24 #include <ctype.h>
25
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
29 #endif
30
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
33
34 #include "afb-api.h"
35 #include "afb-apiset.h"
36 #if defined(WITH_LEGACY_BINDING_V1)
37 #include "afb-api-so-v1.h"
38 #endif
39 #include "afb-api-so-v2.h"
40 #include "afb-api-v3.h"
41 #include "afb-common.h"
42 #include "afb-systemd.h"
43 #include "afb-cred.h"
44 #include "afb-evt.h"
45 #include "afb-export.h"
46 #include "afb-hook.h"
47 #include "afb-msg-json.h"
48 #include "afb-session.h"
49 #include "afb-xreq.h"
50 #include "afb-calls.h"
51 #include "jobs.h"
52 #include "verbose.h"
53 #include "sig-monitor.h"
54 #include "wrap-json.h"
55
56 /*************************************************************************
57  * internal types
58  ************************************************************************/
59
60 /*
61  * structure for handling events
62  */
63 struct event_handler
64 {
65         /* link to the next event handler of the list */
66         struct event_handler *next;
67
68         /* function to call on the case of the event */
69         void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
70
71         /* closure for the callback */
72         void *closure;
73
74         /* the handled pattern */
75         char pattern[1];
76 };
77
78 /*
79  * Actually supported versions
80  */
81 enum afb_api_version
82 {
83         Api_Version_None = 0,
84 #if defined(WITH_LEGACY_BINDING_V1)
85         Api_Version_1 = 1,
86 #endif
87         Api_Version_2 = 2,
88         Api_Version_3 = 3
89 };
90
91 /*
92  * The states of exported APIs
93  */
94 enum afb_api_state
95 {
96         Api_State_Pre_Init,
97         Api_State_Init,
98         Api_State_Run
99 };
100
101 /*
102  * structure of the exported API
103  */
104 struct afb_export
105 {
106         /* keep it first */
107         struct afb_api_x3 api;
108
109         /* reference count */
110         int refcount;
111
112         /* version of the api */
113         unsigned version: 4;
114
115         /* current state */
116         unsigned state: 4;
117
118         /* declared */
119         unsigned declared: 1;
120
121         /* unsealed */
122         unsigned unsealed: 1;
123
124         /* hooking flags */
125         int hookditf;
126         int hooksvc;
127
128         /* session for service */
129         struct afb_session *session;
130
131         /* apiset the API is declared in */
132         struct afb_apiset *declare_set;
133
134         /* apiset for calls */
135         struct afb_apiset *call_set;
136
137         /* event listener for service or NULL */
138         struct afb_evt_listener *listener;
139
140         /* event handler list */
141         struct event_handler *event_handlers;
142
143         /* settings */
144         struct json_object *settings;
145
146         /* internal descriptors */
147         union {
148 #if defined(WITH_LEGACY_BINDING_V1)
149                 struct afb_binding_v1 *v1;
150 #endif
151                 const struct afb_binding_v2 *v2;
152                 struct afb_api_v3 *v3;
153         } desc;
154
155         /* start function */
156         union {
157 #if defined(WITH_LEGACY_BINDING_V1)
158                 int (*v1)(struct afb_service_x1);
159 #endif
160                 int (*v2)();
161                 int (*v3)(struct afb_api_x3 *api);
162         } init;
163
164         /* event handling */
165         void (*on_any_event_v12)(const char *event, struct json_object *object);
166         void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
167
168         /* exported data */
169         union {
170 #if defined(WITH_LEGACY_BINDING_V1)
171                 struct afb_binding_interface_v1 v1;
172 #endif
173                 struct afb_binding_data_v2 *v2;
174         } export;
175
176         /* initial name */
177         char name[1];
178 };
179
180 /*****************************************************************************/
181
182 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
183 {
184         return (struct afb_api_x3*)export;
185 }
186
187 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
188 {
189         return (struct afb_export*)api;
190 }
191
192 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
193 {
194         return from_api_x3(api);
195 }
196
197 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
198 {
199         return to_api_x3(export);
200 }
201
202 /******************************************************************************
203  ******************************************************************************
204  ******************************************************************************
205  ******************************************************************************
206         SETTINGS
207  ******************************************************************************
208  ******************************************************************************
209  ******************************************************************************
210  ******************************************************************************/
211
212 static struct json_object *configuration;
213
214 void afb_export_set_config(struct json_object *config)
215 {
216         struct json_object *save = configuration;
217         configuration = json_object_get(config);
218         json_object_put(save);
219 }
220
221 static struct json_object *get_settings(const char *name)
222 {
223         struct json_object *result;
224         struct json_object *obj;
225
226         if (json_object_object_get_ex(configuration, "*", &obj))
227                 result = wrap_json_clone(obj);
228         else
229                 result = json_object_new_object();
230
231         if (json_object_object_get_ex(configuration, name, &obj))
232                 wrap_json_object_add(result, obj);
233
234         return result;
235 }
236
237 /******************************************************************************
238  ******************************************************************************
239  ******************************************************************************
240  ******************************************************************************
241                                            F R O M     D I T F
242  ******************************************************************************
243  ******************************************************************************
244  ******************************************************************************
245  ******************************************************************************/
246
247 /**********************************************
248 * normal flow
249 **********************************************/
250 static void vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
251 {
252         char *p;
253         struct afb_export *export = from_api_x3(closure);
254
255         if (!fmt || vasprintf(&p, fmt, args) < 0)
256                 vverbose(level, file, line, function, fmt, args);
257         else {
258                 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
259                 free(p);
260         }
261 }
262
263 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
264 {
265         vverbose_cb(closure, level, file, line, NULL, fmt, args);
266 }
267
268 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
269 {
270         struct afb_export *export = from_api_x3(closure);
271
272         /* check daemon state */
273         if (export->state == Api_State_Pre_Init) {
274                 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
275                 errno = EINVAL;
276                 return NULL;
277         }
278
279         /* create the event */
280         return afb_evt_event_x2_create2(export->api.apiname, name);
281 }
282
283 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
284 {
285         struct afb_event_x2 *event = event_x2_make_cb(closure, name);
286         return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
287 }
288
289 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
290 {
291         size_t plen, nlen;
292         char *event;
293         struct afb_export *export = from_api_x3(closure);
294
295         /* check daemon state */
296         if (export->state == Api_State_Pre_Init) {
297                 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
298                         export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
299                 errno = EINVAL;
300                 return 0;
301         }
302
303         /* makes the event name */
304         plen = strlen(export->api.apiname);
305         nlen = strlen(name);
306         event = alloca(nlen + plen + 2);
307         memcpy(event, export->api.apiname, plen);
308         event[plen] = '/';
309         memcpy(event + plen + 1, name, nlen + 1);
310
311         /* broadcast the event */
312         return afb_evt_broadcast(event, object);
313 }
314
315 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
316 {
317         return afb_common_rootdir_open_locale(filename, flags, locale);
318 }
319
320 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
321 {
322         return jobs_queue(group, timeout, callback, argument);
323 }
324
325 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
326 {
327         return afb_xreq_unstore(sreq);
328 }
329
330 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
331 {
332         struct afb_export *export = from_api_x3(closure);
333         int rc, rc2;
334         char *iter, *end, save;
335
336         /* scan the names in a local copy */
337         rc = 0;
338         iter = strdupa(name);
339         for(;;) {
340                 /* skip any space */
341                 save = *iter;
342                 while(isspace(save))
343                         save = *++iter;
344                 if (!save) /* at end? */
345                         return rc;
346
347                 /* search for the end */
348                 end = iter;
349                 while (save && !isspace(save))
350                         save = *++end;
351                 *end = 0;
352
353                 /* check the required api */
354                 if (export->state == Api_State_Pre_Init)
355                         rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
356                 else
357                         rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
358                 if (rc2 < 0)
359                         rc = rc2;
360
361                 *end = save;
362                 iter = end;
363         }
364 }
365
366 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
367 {
368         struct afb_export *export = from_api_x3(closure);
369         if (!afb_api_is_valid_name(aliasname)) {
370                 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
371                 errno = EINVAL;
372                 return -1;
373         }
374         NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
375         afb_export_add_alias(export, apiname, aliasname);
376         return 0;
377 }
378
379 static struct afb_api_x3 *api_new_api_cb(
380                 struct afb_api_x3 *closure,
381                 const char *api,
382                 const char *info,
383                 int noconcurrency,
384                 int (*preinit)(void*, struct afb_api_x3 *),
385                 void *preinit_closure)
386 {
387         struct afb_export *export = from_api_x3(closure);
388         struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
389         return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
390 }
391
392 /**********************************************
393 * hooked flow
394 **********************************************/
395 static void hooked_vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
396 {
397         struct afb_export *export = from_api_x3(closure);
398         va_list ap;
399         va_copy(ap, args);
400         vverbose_cb(closure, level, file, line, function, fmt, args);
401         afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
402         va_end(ap);
403 }
404
405 static void legacy_hooked_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
406 {
407         hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
408 }
409
410 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
411 {
412         struct afb_export *export = from_api_x3(closure);
413         struct afb_event_x2 *r = event_x2_make_cb(closure, name);
414         afb_hook_api_event_make(export, name, r);
415         return r;
416 }
417
418 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
419 {
420         struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
421         struct afb_event_x1 e;
422         e.closure = event;
423         e.itf = event ? event->itf : NULL;
424         return e;
425 }
426
427 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
428 {
429         int r;
430         struct afb_export *export = from_api_x3(closure);
431         json_object_get(object);
432         afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
433         r = event_broadcast_cb(closure, name, object);
434         afb_hook_api_event_broadcast_after(export, name, object, r);
435         json_object_put(object);
436         return r;
437 }
438
439 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
440 {
441         struct afb_export *export = from_api_x3(closure);
442         struct sd_event *r = afb_systemd_get_event_loop();
443         return afb_hook_api_get_event_loop(export, r);
444 }
445
446 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
447 {
448         struct afb_export *export = from_api_x3(closure);
449         struct sd_bus *r = afb_systemd_get_user_bus();
450         return afb_hook_api_get_user_bus(export, r);
451 }
452
453 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
454 {
455         struct afb_export *export = from_api_x3(closure);
456         struct sd_bus *r = afb_systemd_get_system_bus();
457         return afb_hook_api_get_system_bus(export, r);
458 }
459
460 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
461 {
462         struct afb_export *export = from_api_x3(closure);
463         int r = afb_common_rootdir_get_fd();
464         return afb_hook_api_rootdir_get_fd(export, r);
465 }
466
467 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
468 {
469         struct afb_export *export = from_api_x3(closure);
470         int r = rootdir_open_locale_cb(closure, filename, flags, locale);
471         return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
472 }
473
474 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
475 {
476         struct afb_export *export = from_api_x3(closure);
477         int r = queue_job_cb(closure, callback, argument, group, timeout);
478         return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
479 }
480
481 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
482 {
483         struct afb_export *export = from_api_x3(closure);
484         afb_hook_api_legacy_unstore_req(export, sreq);
485         return legacy_unstore_req_cb(closure, sreq);
486 }
487
488 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
489 {
490         int result;
491         struct afb_export *export = from_api_x3(closure);
492         afb_hook_api_require_api(export, name, initialized);
493         result = require_api_cb(closure, name, initialized);
494         return afb_hook_api_require_api_result(export, name, initialized, result);
495 }
496
497 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
498 {
499         struct afb_export *export = from_api_x3(closure);
500         int result = add_alias_cb(closure, apiname, aliasname);
501         return afb_hook_api_add_alias(export, apiname, aliasname, result);
502 }
503
504 static struct afb_api_x3 *hooked_api_new_api_cb(
505                 struct afb_api_x3 *closure,
506                 const char *api,
507                 const char *info,
508                 int noconcurrency,
509                 int (*preinit)(void*, struct afb_api_x3 *),
510                 void *preinit_closure)
511 {
512         struct afb_api_x3 *result;
513         struct afb_export *export = from_api_x3(closure);
514         afb_hook_api_new_api_before(export, api, info, noconcurrency);
515         result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
516         afb_hook_api_new_api_after(export, -!result, api);
517         return result;
518 }
519
520 /**********************************************
521 * vectors
522 **********************************************/
523 static const struct afb_daemon_itf_x1 daemon_itf = {
524         .vverbose_v1 = legacy_vverbose_v1_cb,
525         .vverbose_v2 = vverbose_cb,
526         .event_make = legacy_event_x1_make_cb,
527         .event_broadcast = event_broadcast_cb,
528         .get_event_loop = afb_systemd_get_event_loop,
529         .get_user_bus = afb_systemd_get_user_bus,
530         .get_system_bus = afb_systemd_get_system_bus,
531         .rootdir_get_fd = afb_common_rootdir_get_fd,
532         .rootdir_open_locale = rootdir_open_locale_cb,
533         .queue_job = queue_job_cb,
534         .unstore_req = legacy_unstore_req_cb,
535         .require_api = require_api_cb,
536         .add_alias = add_alias_cb,
537         .new_api = api_new_api_cb,
538 };
539
540 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
541         .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
542         .vverbose_v2 = hooked_vverbose_cb,
543         .event_make = legacy_hooked_event_x1_make_cb,
544         .event_broadcast = hooked_event_broadcast_cb,
545         .get_event_loop = hooked_get_event_loop,
546         .get_user_bus = hooked_get_user_bus,
547         .get_system_bus = hooked_get_system_bus,
548         .rootdir_get_fd = hooked_rootdir_get_fd,
549         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
550         .queue_job = hooked_queue_job_cb,
551         .unstore_req = legacy_hooked_unstore_req_cb,
552         .require_api = hooked_require_api_cb,
553         .add_alias = hooked_add_alias_cb,
554         .new_api = hooked_api_new_api_cb,
555 };
556
557 /******************************************************************************
558  ******************************************************************************
559  ******************************************************************************
560  ******************************************************************************
561                                            F R O M     S V C
562  ******************************************************************************
563  ******************************************************************************
564  ******************************************************************************
565  ******************************************************************************/
566
567 /* the common session for services sharing their session */
568 static struct afb_session *common_session;
569
570 /******************************************************************************
571  ******************************************************************************
572  ******************************************************************************
573  ******************************************************************************
574                                            F R O M     S V C
575  ******************************************************************************
576  ******************************************************************************
577  ******************************************************************************
578  ******************************************************************************/
579
580 static void call_x3(
581                 struct afb_api_x3 *apix3,
582                 const char *api,
583                 const char *verb,
584                 struct json_object *args,
585                 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
586                 void *closure)
587 {
588         struct afb_export *export = from_api_x3(apix3);
589         return afb_calls_call(export, api, verb, args, callback, closure);
590 }
591
592 static int call_sync_x3(
593                 struct afb_api_x3 *apix3,
594                 const char *api,
595                 const char *verb,
596                 struct json_object *args,
597                 struct json_object **object,
598                 char **error,
599                 char **info)
600 {
601         struct afb_export *export = from_api_x3(apix3);
602         return afb_calls_call_sync(export, api, verb, args, object, error, info);
603 }
604
605 static void legacy_call_v12(
606                 struct afb_api_x3 *apix3,
607                 const char *api,
608                 const char *verb,
609                 struct json_object *args,
610                 void (*callback)(void*, int, struct json_object*),
611                 void *closure)
612 {
613         struct afb_export *export = from_api_x3(apix3);
614         afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
615 }
616
617 static void legacy_call_x3(
618                 struct afb_api_x3 *apix3,
619                 const char *api,
620                 const char *verb,
621                 struct json_object *args,
622                 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
623                 void *closure)
624 {
625         struct afb_export *export = from_api_x3(apix3);
626         afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
627 }
628
629 static int legacy_call_sync(
630                 struct afb_api_x3 *apix3,
631                 const char *api,
632                 const char *verb,
633                 struct json_object *args,
634                 struct json_object **result)
635 {
636         struct afb_export *export = from_api_x3(apix3);
637         return afb_calls_legacy_call_sync(export, api, verb, args, result);
638 }
639
640 static void hooked_call_x3(
641                 struct afb_api_x3 *apix3,
642                 const char *api,
643                 const char *verb,
644                 struct json_object *args,
645                 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
646                 void *closure)
647 {
648         struct afb_export *export = from_api_x3(apix3);
649         afb_calls_hooked_call(export, api, verb, args, callback, closure);
650 }
651
652 static int hooked_call_sync_x3(
653                 struct afb_api_x3 *apix3,
654                 const char *api,
655                 const char *verb,
656                 struct json_object *args,
657                 struct json_object **object,
658                 char **error,
659                 char **info)
660 {
661         struct afb_export *export = from_api_x3(apix3);
662         return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
663 }
664
665 static void legacy_hooked_call_v12(
666                 struct afb_api_x3 *apix3,
667                 const char *api,
668                 const char *verb,
669                 struct json_object *args,
670                 void (*callback)(void*, int, struct json_object*),
671                 void *closure)
672 {
673         struct afb_export *export = from_api_x3(apix3);
674         afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
675 }
676
677 static void legacy_hooked_call_x3(
678                 struct afb_api_x3 *apix3,
679                 const char *api,
680                 const char *verb,
681                 struct json_object *args,
682                 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
683                 void *closure)
684 {
685         struct afb_export *export = from_api_x3(apix3);
686         afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
687 }
688
689 static int legacy_hooked_call_sync(
690                 struct afb_api_x3 *apix3,
691                 const char *api,
692                 const char *verb,
693                 struct json_object *args,
694                 struct json_object **result)
695 {
696         struct afb_export *export = from_api_x3(apix3);
697         return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
698 }
699
700 /* the interface for services */
701 static const struct afb_service_itf_x1 service_itf = {
702         .call = legacy_call_v12,
703         .call_sync = legacy_call_sync
704 };
705
706 /* the interface for services */
707 static const struct afb_service_itf_x1 hooked_service_itf = {
708         .call = legacy_hooked_call_v12,
709         .call_sync = legacy_hooked_call_sync
710 };
711
712 /******************************************************************************
713  ******************************************************************************
714  ******************************************************************************
715  ******************************************************************************
716                                            F R O M     D Y N A P I
717  ******************************************************************************
718  ******************************************************************************
719  ******************************************************************************
720  ******************************************************************************/
721
722 static int api_set_verbs_v2_cb(
723                 struct afb_api_x3 *api,
724                 const struct afb_verb_v2 *verbs)
725 {
726         struct afb_export *export = from_api_x3(api);
727
728         if (export->unsealed) {
729                 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
730                 return 0;
731         }
732
733         errno = EPERM;
734         return -1;
735 }
736
737 static int api_set_verbs_v3_cb(
738                 struct afb_api_x3 *api,
739                 const struct afb_verb_v3 *verbs)
740 {
741         struct afb_export *export = from_api_x3(api);
742
743         if (!export->unsealed) {
744                 errno = EPERM;
745                 return -1;
746         }
747
748         afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
749         return 0;
750 }
751
752 static int api_add_verb_cb(
753                 struct afb_api_x3 *api,
754                 const char *verb,
755                 const char *info,
756                 void (*callback)(struct afb_req_x2 *req),
757                 void *vcbdata,
758                 const struct afb_auth *auth,
759                 uint32_t session,
760                 int glob)
761 {
762         struct afb_export *export = from_api_x3(api);
763
764         if (!export->unsealed) {
765                 errno = EPERM;
766                 return -1;
767         }
768
769         return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
770 }
771
772 static int api_del_verb_cb(
773                 struct afb_api_x3 *api,
774                 const char *verb,
775                 void **vcbdata)
776 {
777         struct afb_export *export = from_api_x3(api);
778
779         if (!export->unsealed) {
780                 errno = EPERM;
781                 return -1;
782         }
783
784         return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
785 }
786
787 static int api_set_on_event_cb(
788                 struct afb_api_x3 *api,
789                 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
790 {
791         struct afb_export *export = from_api_x3(api);
792         return afb_export_handle_events_v3(export, onevent);
793 }
794
795 static int api_set_on_init_cb(
796                 struct afb_api_x3 *api,
797                 int (*oninit)(struct afb_api_x3 *api))
798 {
799         struct afb_export *export = from_api_x3(api);
800
801         return afb_export_handle_init_v3(export, oninit);
802 }
803
804 static void api_seal_cb(
805                 struct afb_api_x3 *api)
806 {
807         struct afb_export *export = from_api_x3(api);
808
809         export->unsealed = 0;
810 }
811
812 static int event_handler_add_cb(
813                 struct afb_api_x3 *api,
814                 const char *pattern,
815                 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
816                 void *closure)
817 {
818         struct afb_export *export = from_api_x3(api);
819
820         return afb_export_event_handler_add(export, pattern, callback, closure);
821 }
822
823 static int event_handler_del_cb(
824                 struct afb_api_x3 *api,
825                 const char *pattern,
826                 void **closure)
827 {
828         struct afb_export *export = from_api_x3(api);
829
830         return afb_export_event_handler_del(export, pattern, closure);
831 }
832
833 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
834 {
835         struct afb_export *export = from_api_x3(api);
836
837         int rc = 0, rc2;
838         char *iter, *end, save;
839
840         iter = strdupa(name);
841         for(;;) {
842                 /* skip any space */
843                 save = *iter;
844                 while(isspace(save))
845                         save = *++iter;
846                 if (!save) /* at end? */
847                         return rc;
848
849                 /* search for the end */
850                 end = iter;
851                 while (save && !isspace(save))
852                         save = *++end;
853                 *end = 0;
854
855                 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
856                 if (rc2 < 0)
857                         rc = rc2;
858
859                 *end = save;
860                 iter = end;
861         }
862 }
863
864 static int class_require_cb(struct afb_api_x3 *api, const char *name)
865 {
866         struct afb_export *export = from_api_x3(api);
867
868         int rc = 0, rc2;
869         char *iter, *end, save;
870
871         iter = strdupa(name);
872         for(;;) {
873                 /* skip any space */
874                 save = *iter;
875                 while(isspace(save))
876                         save = *++iter;
877                 if (!save) /* at end? */
878                         return rc;
879
880                 /* search for the end */
881                 end = iter;
882                 while (save && !isspace(save))
883                         save = *++end;
884                 *end = 0;
885
886                 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
887                 if (rc2 < 0)
888                         rc = rc2;
889
890                 *end = save;
891                 iter = end;
892         }
893 }
894
895 static int delete_api_cb(struct afb_api_x3 *api)
896 {
897         struct afb_export *export = from_api_x3(api);
898
899         if (!export->unsealed) {
900                 errno = EPERM;
901                 return -1;
902         }
903
904         afb_export_undeclare(export);
905         afb_export_unref(export);
906         return 0;
907 }
908
909 static struct json_object *settings_cb(struct afb_api_x3 *api)
910 {
911         struct afb_export *export = from_api_x3(api);
912         struct json_object *result = export->settings;
913         if (!result) {
914                 result = get_settings(export->name);
915                 export->settings = result;
916         }
917         return result;
918 }
919
920 static int hooked_api_set_verbs_v2_cb(
921                 struct afb_api_x3 *api,
922                 const struct afb_verb_v2 *verbs)
923 {
924         struct afb_export *export = from_api_x3(api);
925         int result = api_set_verbs_v2_cb(api, verbs);
926         return afb_hook_api_api_set_verbs_v2(export, result, verbs);
927 }
928
929 static int hooked_api_set_verbs_v3_cb(
930                 struct afb_api_x3 *api,
931                 const struct afb_verb_v3 *verbs)
932 {
933         struct afb_export *export = from_api_x3(api);
934         int result = api_set_verbs_v3_cb(api, verbs);
935         return afb_hook_api_api_set_verbs_v3(export, result, verbs);
936 }
937
938 static int hooked_api_add_verb_cb(
939                 struct afb_api_x3 *api,
940                 const char *verb,
941                 const char *info,
942                 void (*callback)(struct afb_req_x2 *req),
943                 void *vcbdata,
944                 const struct afb_auth *auth,
945                 uint32_t session,
946                 int glob)
947 {
948         struct afb_export *export = from_api_x3(api);
949         int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
950         return afb_hook_api_api_add_verb(export, result, verb, info, glob);
951 }
952
953 static int hooked_api_del_verb_cb(
954                 struct afb_api_x3 *api,
955                 const char *verb,
956                 void **vcbdata)
957 {
958         struct afb_export *export = from_api_x3(api);
959         int result = api_del_verb_cb(api, verb, vcbdata);
960         return afb_hook_api_api_del_verb(export, result, verb);
961 }
962
963 static int hooked_api_set_on_event_cb(
964                 struct afb_api_x3 *api,
965                 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
966 {
967         struct afb_export *export = from_api_x3(api);
968         int result = api_set_on_event_cb(api, onevent);
969         return afb_hook_api_api_set_on_event(export, result);
970 }
971
972 static int hooked_api_set_on_init_cb(
973                 struct afb_api_x3 *api,
974                 int (*oninit)(struct afb_api_x3 *api))
975 {
976         struct afb_export *export = from_api_x3(api);
977         int result = api_set_on_init_cb(api, oninit);
978         return afb_hook_api_api_set_on_init(export, result);
979 }
980
981 static void hooked_api_seal_cb(
982                 struct afb_api_x3 *api)
983 {
984         struct afb_export *export = from_api_x3(api);
985         afb_hook_api_api_seal(export);
986         api_seal_cb(api);
987 }
988
989 static int hooked_event_handler_add_cb(
990                 struct afb_api_x3 *api,
991                 const char *pattern,
992                 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
993                 void *closure)
994 {
995         struct afb_export *export = from_api_x3(api);
996         int result = event_handler_add_cb(api, pattern, callback, closure);
997         return afb_hook_api_event_handler_add(export, result, pattern);
998 }
999
1000 static int hooked_event_handler_del_cb(
1001                 struct afb_api_x3 *api,
1002                 const char *pattern,
1003                 void **closure)
1004 {
1005         struct afb_export *export = from_api_x3(api);
1006         int result = event_handler_del_cb(api, pattern, closure);
1007         return afb_hook_api_event_handler_del(export, result, pattern);
1008 }
1009
1010 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1011 {
1012         struct afb_export *export = from_api_x3(api);
1013         int result = class_provide_cb(api, name);
1014         return afb_hook_api_class_provide(export, result, name);
1015 }
1016
1017 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1018 {
1019         struct afb_export *export = from_api_x3(api);
1020         int result = class_require_cb(api, name);
1021         return afb_hook_api_class_require(export, result, name);
1022 }
1023
1024 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1025 {
1026         struct afb_export *export = afb_export_addref(from_api_x3(api));
1027         int result = delete_api_cb(api);
1028         result = afb_hook_api_delete_api(export, result);
1029         afb_export_unref(export);
1030         return result;
1031 }
1032
1033 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1034 {
1035         struct afb_export *export = from_api_x3(api);
1036         struct json_object *result = settings_cb(api);
1037         result = afb_hook_api_settings(export, result);
1038         return result;
1039 }
1040
1041 static const struct afb_api_x3_itf api_x3_itf = {
1042
1043         .vverbose = (void*)vverbose_cb,
1044
1045         .get_event_loop = afb_systemd_get_event_loop,
1046         .get_user_bus = afb_systemd_get_user_bus,
1047         .get_system_bus = afb_systemd_get_system_bus,
1048         .rootdir_get_fd = afb_common_rootdir_get_fd,
1049         .rootdir_open_locale = rootdir_open_locale_cb,
1050         .queue_job = queue_job_cb,
1051
1052         .require_api = require_api_cb,
1053         .add_alias = add_alias_cb,
1054
1055         .event_broadcast = event_broadcast_cb,
1056         .event_make = event_x2_make_cb,
1057
1058         .legacy_call = legacy_call_x3,
1059         .legacy_call_sync = legacy_call_sync,
1060
1061         .api_new_api = api_new_api_cb,
1062         .api_set_verbs_v2 = api_set_verbs_v2_cb,
1063         .api_add_verb = api_add_verb_cb,
1064         .api_del_verb = api_del_verb_cb,
1065         .api_set_on_event = api_set_on_event_cb,
1066         .api_set_on_init = api_set_on_init_cb,
1067         .api_seal = api_seal_cb,
1068         .api_set_verbs_v3 = api_set_verbs_v3_cb,
1069         .event_handler_add = event_handler_add_cb,
1070         .event_handler_del = event_handler_del_cb,
1071
1072         .call = call_x3,
1073         .call_sync = call_sync_x3,
1074
1075         .class_provide = class_provide_cb,
1076         .class_require = class_require_cb,
1077
1078         .delete_api = delete_api_cb,
1079         .settings = settings_cb,
1080 };
1081
1082 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1083
1084         .vverbose = hooked_vverbose_cb,
1085
1086         .get_event_loop = hooked_get_event_loop,
1087         .get_user_bus = hooked_get_user_bus,
1088         .get_system_bus = hooked_get_system_bus,
1089         .rootdir_get_fd = hooked_rootdir_get_fd,
1090         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1091         .queue_job = hooked_queue_job_cb,
1092
1093         .require_api = hooked_require_api_cb,
1094         .add_alias = hooked_add_alias_cb,
1095
1096         .event_broadcast = hooked_event_broadcast_cb,
1097         .event_make = hooked_event_x2_make_cb,
1098
1099         .legacy_call = legacy_hooked_call_x3,
1100         .legacy_call_sync = legacy_hooked_call_sync,
1101
1102         .api_new_api = hooked_api_new_api_cb,
1103         .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1104         .api_add_verb = hooked_api_add_verb_cb,
1105         .api_del_verb = hooked_api_del_verb_cb,
1106         .api_set_on_event = hooked_api_set_on_event_cb,
1107         .api_set_on_init = hooked_api_set_on_init_cb,
1108         .api_seal = hooked_api_seal_cb,
1109         .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1110         .event_handler_add = hooked_event_handler_add_cb,
1111         .event_handler_del = hooked_event_handler_del_cb,
1112
1113         .call = hooked_call_x3,
1114         .call_sync = hooked_call_sync_x3,
1115
1116         .class_provide = hooked_class_provide_cb,
1117         .class_require = hooked_class_require_cb,
1118
1119         .delete_api = hooked_delete_api_cb,
1120         .settings = hooked_settings_cb,
1121 };
1122
1123 /******************************************************************************
1124  ******************************************************************************
1125  ******************************************************************************
1126  ******************************************************************************
1127                       L I S T E N E R S
1128  ******************************************************************************
1129  ******************************************************************************
1130  ******************************************************************************
1131  ******************************************************************************/
1132
1133 /*
1134  * Propagates the event to the service
1135  */
1136 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1137 {
1138         struct event_handler *handler;
1139         struct afb_export *export = from_api_x3(closure);
1140
1141         /* hook the event before */
1142         if (export->hooksvc & afb_hook_flag_api_on_event)
1143                 afb_hook_api_on_event_before(export, event, eventid, object);
1144
1145         /* transmit to specific handlers */
1146         /* search the handler */
1147         handler = export->event_handlers;
1148         while (handler) {
1149                 if (fnmatch(handler->pattern, event, 0)) {
1150                         if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1151                                 handler->callback(handler->closure, event, object, to_api_x3(export));
1152                         else {
1153                                 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1154                                 handler->callback(handler->closure, event, object, to_api_x3(export));
1155                                 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1156                         }
1157                 }
1158                 handler = handler->next;
1159         }
1160
1161         /* transmit to default handler */
1162         if (export->on_any_event_v3)
1163                 export->on_any_event_v3(to_api_x3(export), event, object);
1164         else if (export->on_any_event_v12)
1165                 export->on_any_event_v12(event, object);
1166
1167         /* hook the event after */
1168         if (export->hooksvc & afb_hook_flag_api_on_event)
1169                 afb_hook_api_on_event_after(export, event, eventid, object);
1170         json_object_put(object);
1171 }
1172
1173 /* the interface for events */
1174 static const struct afb_evt_itf evt_itf = {
1175         .broadcast = listener_of_events,
1176         .push = listener_of_events
1177 };
1178
1179 /* ensure an existing listener */
1180 static int ensure_listener(struct afb_export *export)
1181 {
1182         if (!export->listener) {
1183                 export->listener = afb_evt_listener_create(&evt_itf, export);
1184                 if (export->listener == NULL)
1185                         return -1;
1186         }
1187         return 0;
1188 }
1189
1190 int afb_export_event_handler_add(
1191                         struct afb_export *export,
1192                         const char *pattern,
1193                         void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1194                         void *closure)
1195 {
1196         int rc;
1197         struct event_handler *handler, **previous;
1198
1199         rc = ensure_listener(export);
1200         if (rc < 0)
1201                 return rc;
1202
1203         /* search the handler */
1204         previous = &export->event_handlers;
1205         while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1206                 previous = &handler->next;
1207
1208         /* error if found */
1209         if (handler) {
1210                 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1211                 errno = EEXIST;
1212                 return -1;
1213         }
1214
1215         /* create the event */
1216         handler = malloc(strlen(pattern) + sizeof * handler);
1217         if (!handler) {
1218                 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1219                 errno = ENOMEM;
1220                 return -1;
1221         }
1222
1223         /* init and record */
1224         handler->next = NULL;
1225         handler->callback = callback;
1226         handler->closure = closure;
1227         strcpy(handler->pattern, pattern);
1228         *previous = handler;
1229
1230         return 0;
1231 }
1232
1233 int afb_export_event_handler_del(
1234                         struct afb_export *export,
1235                         const char *pattern,
1236                         void **closure)
1237 {
1238         struct event_handler *handler, **previous;
1239
1240         /* search the handler */
1241         previous = &export->event_handlers;
1242         while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1243                 previous = &handler->next;
1244
1245         /* error if found */
1246         if (!handler) {
1247                 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1248                 errno = ENOENT;
1249                 return -1;
1250         }
1251
1252         /* remove the found event */
1253         if (closure)
1254                 *closure = handler->closure;
1255
1256         *previous = handler->next;
1257         free(handler);
1258         return 0;
1259 }
1260
1261 /******************************************************************************
1262  ******************************************************************************
1263  ******************************************************************************
1264  ******************************************************************************
1265                                            M E R G E D
1266  ******************************************************************************
1267  ******************************************************************************
1268  ******************************************************************************
1269  ******************************************************************************/
1270
1271 static struct afb_export *create(
1272                                 struct afb_apiset *declare_set,
1273                                 struct afb_apiset *call_set,
1274                                 const char *apiname,
1275                                 enum afb_api_version version)
1276 {
1277         struct afb_export *export;
1278
1279         /* session shared with other exports */
1280         if (common_session == NULL) {
1281                 common_session = afb_session_create (0);
1282                 if (common_session == NULL)
1283                         return NULL;
1284         }
1285         export = calloc(1, sizeof *export + strlen(apiname));
1286         if (!export)
1287                 errno = ENOMEM;
1288         else {
1289                 export->refcount = 1;
1290                 strcpy(export->name, apiname);
1291                 export->api.apiname = export->name;
1292                 export->version = version;
1293                 export->state = Api_State_Pre_Init;
1294                 export->session = afb_session_addref(common_session);
1295                 export->declare_set = afb_apiset_addref(declare_set);
1296                 export->call_set = afb_apiset_addref(call_set);
1297         }
1298         return export;
1299 }
1300
1301 struct afb_export *afb_export_addref(struct afb_export *export)
1302 {
1303         if (export)
1304                 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1305         return export;
1306 }
1307
1308 void afb_export_unref(struct afb_export *export)
1309 {
1310         if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1311                 afb_export_destroy(export);
1312 }
1313
1314 void afb_export_destroy(struct afb_export *export)
1315 {
1316         struct event_handler *handler;
1317
1318         if (export) {
1319                 while ((handler = export->event_handlers)) {
1320                         export->event_handlers = handler->next;
1321                         free(handler);
1322                 }
1323                 if (export->listener != NULL)
1324                         afb_evt_listener_unref(export->listener);
1325                 afb_session_unref(export->session);
1326                 afb_apiset_unref(export->declare_set);
1327                 afb_apiset_unref(export->call_set);
1328                 if (export->api.apiname != export->name)
1329                         free((void*)export->api.apiname);
1330                 json_object_put(export->settings);
1331                 free(export);
1332         }
1333 }
1334
1335 struct afb_export *afb_export_create_none_for_path(
1336                         struct afb_apiset *declare_set,
1337                         struct afb_apiset *call_set,
1338                         const char *path,
1339                         int (*creator)(void*, struct afb_api_x3*),
1340                         void *closure)
1341 {
1342         struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
1343         if (export) {
1344                 afb_export_logmask_set(export, logmask);
1345                 afb_export_update_hooks(export);
1346                 if (creator && creator(closure, to_api_x3(export)) < 0) {
1347                         afb_export_unref(export);
1348                         export = NULL;
1349                 }
1350         }
1351         return export;
1352 }
1353
1354 #if defined(WITH_LEGACY_BINDING_V1)
1355 struct afb_export *afb_export_create_v1(
1356                         struct afb_apiset *declare_set,
1357                         struct afb_apiset *call_set,
1358                         const char *apiname,
1359                         int (*init)(struct afb_service_x1),
1360                         void (*onevent)(const char*, struct json_object*))
1361 {
1362         struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
1363         if (export) {
1364                 export->init.v1 = init;
1365                 export->on_any_event_v12 = onevent;
1366                 export->export.v1.mode = AFB_MODE_LOCAL;
1367                 export->export.v1.daemon.closure = to_api_x3(export);
1368                 afb_export_logmask_set(export, logmask);
1369                 afb_export_update_hooks(export);
1370         }
1371         return export;
1372 }
1373 #endif
1374
1375 struct afb_export *afb_export_create_v2(
1376                         struct afb_apiset *declare_set,
1377                         struct afb_apiset *call_set,
1378                         const char *apiname,
1379                         const struct afb_binding_v2 *binding,
1380                         struct afb_binding_data_v2 *data,
1381                         int (*init)(),
1382                         void (*onevent)(const char*, struct json_object*))
1383 {
1384         struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
1385         if (export) {
1386                 export->init.v2 = init;
1387                 export->on_any_event_v12 = onevent;
1388                 export->desc.v2 = binding;
1389                 export->export.v2 = data;
1390                 data->daemon.closure = to_api_x3(export);
1391                 data->service.closure = to_api_x3(export);
1392                 afb_export_logmask_set(export, logmask);
1393                 afb_export_update_hooks(export);
1394         }
1395         return export;
1396 }
1397
1398 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1399                         struct afb_apiset *call_set,
1400                         const char *apiname,
1401                         struct afb_api_v3 *apiv3)
1402 {
1403         struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
1404         if (export) {
1405                 export->unsealed = 1;
1406                 export->desc.v3 = apiv3;
1407                 afb_export_logmask_set(export, logmask);
1408                 afb_export_update_hooks(export);
1409         }
1410         return export;
1411 }
1412
1413 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1414 {
1415         return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1416 }
1417
1418 int afb_export_rename(struct afb_export *export, const char *apiname)
1419 {
1420         char *name;
1421
1422         if (export->declared) {
1423                 errno = EBUSY;
1424                 return -1;
1425         }
1426
1427         /* copy the name locally */
1428         name = strdup(apiname);
1429         if (!name) {
1430                 errno = ENOMEM;
1431                 return -1;
1432         }
1433
1434         if (export->api.apiname != export->name)
1435                 free((void*)export->api.apiname);
1436         export->api.apiname = name;
1437
1438         afb_export_update_hooks(export);
1439         return 0;
1440 }
1441
1442 const char *afb_export_apiname(const struct afb_export *export)
1443 {
1444         return export->api.apiname;
1445 }
1446
1447 void afb_export_update_hooks(struct afb_export *export)
1448 {
1449         export->hookditf = afb_hook_flags_api(export->api.apiname);
1450         export->hooksvc = afb_hook_flags_api(export->api.apiname);
1451         export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1452
1453         switch (export->version) {
1454 #if defined(WITH_LEGACY_BINDING_V1)
1455         case Api_Version_1:
1456                 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1457                 break;
1458 #endif
1459         case Api_Version_2:
1460                 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1461                 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1462                 break;
1463         }
1464 }
1465
1466 int afb_export_unshare_session(struct afb_export *export)
1467 {
1468         if (export->session == common_session) {
1469                 export->session = afb_session_create (0);
1470                 if (export->session)
1471                         afb_session_unref(common_session);
1472                 else {
1473                         export->session = common_session;
1474                         return -1;
1475                 }
1476         }
1477         return 0;
1478 }
1479
1480 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1481 {
1482         /* check version */
1483         switch (export->version) {
1484 #if defined(WITH_LEGACY_BINDING_V1)
1485         case Api_Version_1:
1486 #endif
1487         case Api_Version_2:
1488                 break;
1489         default:
1490                 ERROR("invalid version 12 for API %s", export->api.apiname);
1491                 errno = EINVAL;
1492                 return -1;
1493         }
1494
1495         export->on_any_event_v12 = on_event;
1496         return ensure_listener(export);
1497 }
1498
1499 int afb_export_handle_events_v3(struct afb_export *export, void (*on_event)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1500 {
1501         /* check version */
1502         switch (export->version) {
1503         case Api_Version_3: break;
1504         default:
1505                 ERROR("invalid version Dyn for API %s", export->api.apiname);
1506                 errno = EINVAL;
1507                 return -1;
1508         }
1509
1510         export->on_any_event_v3 = on_event;
1511         return ensure_listener(export);
1512 }
1513
1514 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1515 {
1516         if (export->state != Api_State_Pre_Init) {
1517                 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1518                 errno = EINVAL;
1519                 return -1;
1520         }
1521
1522         export->init.v3  = oninit;
1523         return 0;
1524 }
1525
1526 #if defined(WITH_LEGACY_BINDING_V1)
1527 /*
1528  * Starts a new service (v1)
1529  */
1530 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1531 {
1532         return export->desc.v1 = regfun(&export->export.v1);
1533 }
1534 #endif
1535
1536 int afb_export_preinit_x3(
1537                 struct afb_export *export,
1538                 int (*preinit)(void*, struct afb_api_x3*),
1539                 void *closure)
1540 {
1541         return preinit(closure, to_api_x3(export));
1542 }
1543
1544 int afb_export_logmask_get(const struct afb_export *export)
1545 {
1546         return export->api.logmask;
1547 }
1548
1549 void afb_export_logmask_set(struct afb_export *export, int mask)
1550 {
1551         export->api.logmask = mask;
1552         switch (export->version) {
1553 #if defined(WITH_LEGACY_BINDING_V1)
1554         case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1555 #endif
1556         case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1557         }
1558 }
1559
1560 void *afb_export_userdata_get(const struct afb_export *export)
1561 {
1562         return export->api.userdata;
1563 }
1564
1565 void afb_export_userdata_set(struct afb_export *export, void *data)
1566 {
1567         export->api.userdata = data;
1568 }
1569
1570 /******************************************************************************
1571  ******************************************************************************
1572  ******************************************************************************
1573  ******************************************************************************
1574                                            N E W
1575  ******************************************************************************
1576  ******************************************************************************
1577  ******************************************************************************
1578  ******************************************************************************/
1579
1580 struct init
1581 {
1582         int return_code;
1583         struct afb_export *export;
1584 };
1585
1586 static void do_init(int sig, void *closure)
1587 {
1588         int rc = -1;
1589         struct init *init = closure;
1590         struct afb_export *export;
1591
1592         if (sig)
1593                 errno = EFAULT;
1594         else {
1595                 export = init->export;
1596                 switch (export->version) {
1597 #if defined(WITH_LEGACY_BINDING_V1)
1598                 case Api_Version_1:
1599                         rc = export->init.v1 ? export->init.v1(
1600                                 (struct afb_service_x1){
1601                                         .itf = &hooked_service_itf,
1602                                         .closure = to_api_x3(export) }) : 0;
1603                         break;
1604 #endif
1605                 case Api_Version_2:
1606                         rc = export->init.v2 ? export->init.v2() : 0;
1607                         break;
1608                 case Api_Version_3:
1609                         rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1610                         break;
1611                 default:
1612                         errno = EINVAL;
1613                         break;
1614                 }
1615         }
1616         init->return_code = rc;
1617 };
1618
1619
1620 int afb_export_start(struct afb_export *export)
1621 {
1622         struct init init;
1623         int rc;
1624
1625         /* check state */
1626         switch (export->state) {
1627         case Api_State_Run:
1628                 return 0;
1629
1630         case Api_State_Init:
1631                 /* starting in progress: it is an error */
1632                 ERROR("Service of API %s required started while starting", export->api.apiname);
1633                 return -1;
1634
1635         default:
1636                 break;
1637         }
1638
1639         /* set event handling */
1640         switch (export->version) {
1641 #if defined(WITH_LEGACY_BINDING_V1)
1642         case Api_Version_1:
1643 #endif
1644         case Api_Version_2:
1645                 if (export->on_any_event_v12) {
1646                         rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1647                         break;
1648                 }
1649                 /*@fallthrough@*/
1650         default:
1651                 rc = 0;
1652                 break;
1653         }
1654         if (rc < 0) {
1655                 ERROR("Can't set event handler for %s", export->api.apiname);
1656                 return -1;
1657         }
1658
1659         /* Starts the service */
1660         if (export->hooksvc & afb_hook_flag_api_start)
1661                 afb_hook_api_start_before(export);
1662
1663         export->state = Api_State_Init;
1664         init.export = export;
1665         sig_monitor(0, do_init, &init);
1666         rc = init.return_code;
1667         export->state = Api_State_Run;
1668
1669         if (export->hooksvc & afb_hook_flag_api_start)
1670                 afb_hook_api_start_after(export, rc);
1671
1672         if (rc < 0) {
1673                 /* initialisation error */
1674                 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1675                 return rc;
1676         }
1677
1678         return 0;
1679 }
1680
1681 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1682 {
1683         struct afb_export *export = closure;
1684
1685         xreq->request.api = to_api_x3(export);
1686
1687         switch (export->version) {
1688 #if defined(WITH_LEGACY_BINDING_V1)
1689         case Api_Version_1:
1690                 afb_api_so_v1_process_call(export->desc.v1, xreq);
1691                 break;
1692 #endif
1693         case Api_Version_2:
1694                 afb_api_so_v2_process_call(export->desc.v2, xreq);
1695                 break;
1696         case Api_Version_3:
1697                 afb_api_v3_process_call(export->desc.v3, xreq);
1698                 break;
1699         default:
1700                 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1701                 break;
1702         }
1703 }
1704
1705 static struct json_object *api_describe_cb(void *closure)
1706 {
1707         struct afb_export *export = closure;
1708         struct json_object *result;
1709
1710         switch (export->version) {
1711 #if defined(WITH_LEGACY_BINDING_V1)
1712         case Api_Version_1:
1713                 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1714                 break;
1715 #endif
1716         case Api_Version_2:
1717                 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1718                 break;
1719         case Api_Version_3:
1720                 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1721                 break;
1722         default:
1723                 result = NULL;
1724                 break;
1725         }
1726         return result;
1727 }
1728
1729 static int api_service_start_cb(void *closure)
1730 {
1731         struct afb_export *export = closure;
1732
1733         return afb_export_start(export);
1734 }
1735
1736 static void api_update_hooks_cb(void *closure)
1737 {
1738         struct afb_export *export = closure;
1739
1740         afb_export_update_hooks(export);
1741 }
1742
1743 static int api_get_logmask_cb(void *closure)
1744 {
1745         struct afb_export *export = closure;
1746
1747         return afb_export_logmask_get(export);
1748 }
1749
1750 static void api_set_logmask_cb(void *closure, int level)
1751 {
1752         struct afb_export *export = closure;
1753
1754         afb_export_logmask_set(export, level);
1755 }
1756
1757 static void api_unref_cb(void *closure)
1758 {
1759         struct afb_export *export = closure;
1760
1761         afb_export_unref(export);
1762 }
1763
1764 static struct afb_api_itf export_api_itf =
1765 {
1766         .call = api_call_cb,
1767         .service_start = api_service_start_cb,
1768         .update_hooks = api_update_hooks_cb,
1769         .get_logmask = api_get_logmask_cb,
1770         .set_logmask = api_set_logmask_cb,
1771         .describe = api_describe_cb,
1772         .unref = api_unref_cb
1773 };
1774
1775 int afb_export_declare(struct afb_export *export,
1776                         int noconcurrency)
1777 {
1778         int rc;
1779         struct afb_api_item afb_api;
1780
1781         if (export->declared)
1782                 rc = 0;
1783         else {
1784                 /* init the record structure */
1785                 afb_api.closure = afb_export_addref(export);
1786                 afb_api.itf = &export_api_itf;
1787                 afb_api.group = noconcurrency ? export : NULL;
1788
1789                 /* records the binding */
1790                 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1791                 if (rc >= 0)
1792                         export->declared = 1;
1793                 else {
1794                         ERROR("can't declare export %s to set %s, ABORTING it!",
1795                                 export->api.apiname,
1796                                 afb_apiset_name(export->declare_set));
1797                         afb_export_addref(export);
1798                 }
1799         }
1800
1801         return rc;
1802 }
1803
1804 void afb_export_undeclare(struct afb_export *export)
1805 {
1806         if (export->declared) {
1807                 export->declared = 0;
1808                 afb_apiset_del(export->declare_set, export->api.apiname);
1809         }
1810 }
1811
1812 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1813 {
1814         return afb_evt_event_x2_add_watch(export->listener, event);
1815 }
1816
1817 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1818 {
1819         return afb_evt_event_x2_remove_watch(export->listener, event);
1820 }
1821
1822 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1823 {
1824         afb_xreq_process(xreq, export->call_set);
1825 }
1826
1827 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1828 {
1829         afb_context_init(context, export->session, NULL);
1830         context->validated = 1;
1831 }
1832