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