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