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