2 * Copyright (C) 2016-2019 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
35 #include "afb-apiset.h"
36 #if WITH_LEGACY_BINDING_V1
37 #include "afb-api-so-v1.h"
39 #if WITH_LEGACY_BINDING_V2
40 #include "afb-api-so-v2.h"
42 #include "afb-api-v3.h"
43 #include "afb-common.h"
46 #include "afb-export.h"
48 #include "afb-msg-json.h"
49 #include "afb-session.h"
51 #include "afb-calls.h"
57 #include "sig-monitor.h"
58 #include "wrap-json.h"
60 /*************************************************************************
62 ************************************************************************/
65 * Actually supported versions
70 #if WITH_LEGACY_BINDING_V1
73 #if WITH_LEGACY_BINDING_V2
80 * The states of exported APIs
90 * structure of the exported API
95 struct afb_api_x3 api;
100 /* version of the api */
107 unsigned declared: 1;
110 unsigned unsealed: 1;
118 /* session for service */
119 struct afb_session *session;
121 /* apiset the API is declared in */
122 struct afb_apiset *declare_set;
124 /* apiset for calls */
125 struct afb_apiset *call_set;
127 /* event listener for service or NULL */
128 struct afb_evt_listener *listener;
130 /* event handler list */
131 struct globset *event_handlers;
134 struct afb_export *creator;
136 /* path indication if any */
140 struct json_object *settings;
142 /* internal descriptors */
144 #if WITH_LEGACY_BINDING_V1
145 struct afb_binding_v1 *v1;
147 const struct afb_binding_v2 *v2;
148 struct afb_api_v3 *v3;
153 #if WITH_LEGACY_BINDING_V1
154 int (*v1)(struct afb_service_x1);
157 int (*v3)(struct afb_api_x3 *api);
161 void (*on_any_event_v12)(const char *event, struct json_object *object);
162 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
166 #if WITH_LEGACY_BINDING_V1
167 struct afb_binding_interface_v1 v1;
169 struct afb_binding_data_v2 *v2;
176 /*****************************************************************************/
178 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
180 return (struct afb_api_x3*)export;
183 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
185 return (struct afb_export*)api;
188 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
190 return from_api_x3(api);
193 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
195 return to_api_x3(export);
198 /******************************************************************************
199 ******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
203 ******************************************************************************
204 ******************************************************************************
205 ******************************************************************************
206 ******************************************************************************/
208 static struct json_object *configuration;
210 void afb_export_set_config(struct json_object *config)
212 struct json_object *save = configuration;
213 configuration = json_object_get(config);
214 json_object_put(save);
217 static struct json_object *make_settings(struct afb_export *export)
219 struct json_object *result;
220 struct json_object *obj;
221 struct afb_export *iter;
224 /* clone the globals */
225 if (json_object_object_get_ex(configuration, "*", &obj))
226 result = wrap_json_clone(obj);
228 result = json_object_new_object();
231 if (json_object_object_get_ex(configuration, export->name, &obj))
232 wrap_json_object_add(result, obj);
234 /* add library path */
235 for (iter = export ; iter && !iter->path ; iter = iter->creator);
237 path = realpath(iter->path, NULL);
238 json_object_object_add(result, "binding-path", json_object_new_string(path));
242 export->settings = result;
246 /******************************************************************************
247 ******************************************************************************
248 ******************************************************************************
249 ******************************************************************************
251 ******************************************************************************
252 ******************************************************************************
253 ******************************************************************************
254 ******************************************************************************/
256 /**********************************************
258 **********************************************/
259 static void vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
262 struct afb_export *export = from_api_x3(closure);
264 if (!fmt || vasprintf(&p, fmt, args) < 0)
265 vverbose(level, file, line, function, fmt, args);
267 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
272 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
274 struct afb_export *export = from_api_x3(closure);
276 /* check daemon state */
277 if (export->state == Api_State_Pre_Init) {
278 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
283 /* create the event */
284 return afb_evt_event_x2_create2(export->api.apiname, name);
287 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
291 struct afb_export *export = from_api_x3(closure);
293 /* check daemon state */
294 if (export->state == Api_State_Pre_Init) {
295 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
296 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
301 /* makes the event name */
302 plen = strlen(export->api.apiname);
304 event = alloca(nlen + plen + 2);
305 memcpy(event, export->api.apiname, plen);
307 memcpy(event + plen + 1, name, nlen + 1);
309 /* broadcast the event */
310 return afb_evt_broadcast(event, object);
313 static struct sd_event *get_event_loop(struct afb_api_x3 *closure)
315 jobs_acquire_event_manager();
316 return systemd_get_event_loop();
319 static struct sd_bus *get_user_bus(struct afb_api_x3 *closure)
321 jobs_acquire_event_manager();
322 return systemd_get_user_bus();
325 static struct sd_bus *get_system_bus(struct afb_api_x3 *closure)
327 jobs_acquire_event_manager();
328 return systemd_get_system_bus();
331 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
333 return afb_common_rootdir_open_locale(filename, flags, locale);
336 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
338 return jobs_queue(group, timeout, callback, argument);
341 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
343 struct afb_export *export = from_api_x3(closure);
345 char *iter, *end, save;
347 /* emit a warning about unexpected require in preinit */
348 if (export->state == Api_State_Pre_Init && initialized) {
349 ERROR("[API %s] requiring initialized apis in pre-init is forbiden", export->api.apiname);
354 /* scan the names in a local copy */
356 iter = strdupa(name);
362 if (!save) /* at end? */
365 /* search for the end */
367 while (save && !isspace(save))
371 /* check the required api */
372 if (export->state == Api_State_Pre_Init) {
373 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, iter);
376 WARNING("[API %s] requiring apis pre-init may lead to unexpected result", export->api.apiname);
377 ERROR("[API %s] requiring api %s in pre-init failed", export->api.apiname, iter);
380 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
382 ERROR("[API %s] requiring api %s%s failed", export->api.apiname,
383 iter, initialized ? " initialized" : "");
394 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
396 struct afb_export *export = from_api_x3(closure);
397 if (!afb_api_is_valid_name(aliasname)) {
398 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
402 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
403 afb_export_add_alias(export, apiname, aliasname);
407 static struct afb_api_x3 *api_new_api_cb(
408 struct afb_api_x3 *closure,
412 int (*preinit)(void*, struct afb_api_x3 *),
413 void *preinit_closure)
415 struct afb_export *export = from_api_x3(closure);
416 struct afb_api_v3 *apiv3 = afb_api_v3_create(
417 export->declare_set, export->call_set,
418 api, info, noconcurrency,
419 preinit, preinit_closure, 1,
421 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
424 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
426 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
428 vverbose_cb(closure, level, file, line, NULL, fmt, args);
431 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
433 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
434 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
437 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
439 return afb_xreq_unstore(sreq);
442 static const struct afb_daemon_itf_x1 daemon_itf = {
443 .vverbose_v1 = legacy_vverbose_v1_cb,
444 .vverbose_v2 = vverbose_cb,
445 .event_make = legacy_event_x1_make_cb,
446 .event_broadcast = event_broadcast_cb,
447 .get_event_loop = get_event_loop,
448 .get_user_bus = get_user_bus,
449 .get_system_bus = get_system_bus,
450 .rootdir_get_fd = afb_common_rootdir_get_fd,
451 .rootdir_open_locale = rootdir_open_locale_cb,
452 .queue_job = queue_job_cb,
453 .unstore_req = legacy_unstore_req_cb,
454 .require_api = require_api_cb,
455 .add_alias = add_alias_cb,
456 .new_api = api_new_api_cb,
461 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)
463 struct afb_export *export = from_api_x3(closure);
466 vverbose_cb(closure, level, file, line, function, fmt, args);
467 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
471 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
473 struct afb_export *export = from_api_x3(closure);
474 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
475 afb_hook_api_event_make(export, name, r);
479 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
482 struct afb_export *export = from_api_x3(closure);
483 json_object_get(object);
484 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
485 r = event_broadcast_cb(closure, name, object);
486 afb_hook_api_event_broadcast_after(export, name, object, r);
487 json_object_put(object);
491 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
493 struct afb_export *export = from_api_x3(closure);
496 jobs_acquire_event_manager();
497 r = get_event_loop(closure);
498 return afb_hook_api_get_event_loop(export, r);
501 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
503 struct afb_export *export = from_api_x3(closure);
506 jobs_acquire_event_manager();
507 r = get_user_bus(closure);
508 return afb_hook_api_get_user_bus(export, r);
511 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
513 struct afb_export *export = from_api_x3(closure);
516 jobs_acquire_event_manager();
517 r = get_system_bus(closure);
518 return afb_hook_api_get_system_bus(export, r);
521 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
523 struct afb_export *export = from_api_x3(closure);
524 int r = afb_common_rootdir_get_fd();
525 return afb_hook_api_rootdir_get_fd(export, r);
528 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
530 struct afb_export *export = from_api_x3(closure);
531 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
532 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
535 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
537 struct afb_export *export = from_api_x3(closure);
538 int r = queue_job_cb(closure, callback, argument, group, timeout);
539 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
542 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
545 struct afb_export *export = from_api_x3(closure);
546 afb_hook_api_require_api(export, name, initialized);
547 result = require_api_cb(closure, name, initialized);
548 return afb_hook_api_require_api_result(export, name, initialized, result);
551 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
553 struct afb_export *export = from_api_x3(closure);
554 int result = add_alias_cb(closure, apiname, aliasname);
555 return afb_hook_api_add_alias(export, apiname, aliasname, result);
558 static struct afb_api_x3 *hooked_api_new_api_cb(
559 struct afb_api_x3 *closure,
563 int (*preinit)(void*, struct afb_api_x3 *),
564 void *preinit_closure)
566 struct afb_api_x3 *result;
567 struct afb_export *export = from_api_x3(closure);
568 afb_hook_api_new_api_before(export, api, info, noconcurrency);
569 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
570 afb_hook_api_new_api_after(export, -!result, api);
574 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
576 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)
578 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
581 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
583 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
584 struct afb_event_x1 e;
586 e.itf = event ? event->itf : NULL;
590 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
592 struct afb_export *export = from_api_x3(closure);
593 afb_hook_api_legacy_unstore_req(export, sreq);
594 return legacy_unstore_req_cb(closure, sreq);
597 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
598 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
599 .vverbose_v2 = hooked_vverbose_cb,
600 .event_make = legacy_hooked_event_x1_make_cb,
601 .event_broadcast = hooked_event_broadcast_cb,
602 .get_event_loop = hooked_get_event_loop,
603 .get_user_bus = hooked_get_user_bus,
604 .get_system_bus = hooked_get_system_bus,
605 .rootdir_get_fd = hooked_rootdir_get_fd,
606 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
607 .queue_job = hooked_queue_job_cb,
608 .unstore_req = legacy_hooked_unstore_req_cb,
609 .require_api = hooked_require_api_cb,
610 .add_alias = hooked_add_alias_cb,
611 .new_api = hooked_api_new_api_cb,
617 /******************************************************************************
618 ******************************************************************************
619 ******************************************************************************
620 ******************************************************************************
622 ******************************************************************************
623 ******************************************************************************
624 ******************************************************************************
625 ******************************************************************************/
627 /* the common session for services sharing their session */
628 static struct afb_session *common_session;
630 /******************************************************************************
631 ******************************************************************************
632 ******************************************************************************
633 ******************************************************************************
635 ******************************************************************************
636 ******************************************************************************
637 ******************************************************************************
638 ******************************************************************************/
641 struct afb_api_x3 *apix3,
644 struct json_object *args,
645 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
648 struct afb_export *export = from_api_x3(apix3);
649 return afb_calls_call(export, api, verb, args, callback, closure);
652 static int call_sync_x3(
653 struct afb_api_x3 *apix3,
656 struct json_object *args,
657 struct json_object **object,
661 struct afb_export *export = from_api_x3(apix3);
662 return afb_calls_call_sync(export, api, verb, args, object, error, info);
665 static void legacy_call_x3(
666 struct afb_api_x3 *apix3,
669 struct json_object *args,
670 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
673 struct afb_export *export = from_api_x3(apix3);
674 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
677 static int legacy_call_sync(
678 struct afb_api_x3 *apix3,
681 struct json_object *args,
682 struct json_object **result)
684 struct afb_export *export = from_api_x3(apix3);
685 return afb_calls_legacy_call_sync(export, api, verb, args, result);
688 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
690 static void legacy_call_v12(
691 struct afb_api_x3 *apix3,
694 struct json_object *args,
695 void (*callback)(void*, int, struct json_object*),
698 struct afb_export *export = from_api_x3(apix3);
699 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
702 /* the interface for services */
703 static const struct afb_service_itf_x1 service_itf = {
704 .call = legacy_call_v12,
705 .call_sync = legacy_call_sync
710 static void hooked_call_x3(
711 struct afb_api_x3 *apix3,
714 struct json_object *args,
715 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
718 struct afb_export *export = from_api_x3(apix3);
719 afb_calls_hooked_call(export, api, verb, args, callback, closure);
722 static int hooked_call_sync_x3(
723 struct afb_api_x3 *apix3,
726 struct json_object *args,
727 struct json_object **object,
731 struct afb_export *export = from_api_x3(apix3);
732 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
735 static void legacy_hooked_call_x3(
736 struct afb_api_x3 *apix3,
739 struct json_object *args,
740 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
743 struct afb_export *export = from_api_x3(apix3);
744 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
747 static int legacy_hooked_call_sync(
748 struct afb_api_x3 *apix3,
751 struct json_object *args,
752 struct json_object **result)
754 struct afb_export *export = from_api_x3(apix3);
755 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
758 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
760 static void legacy_hooked_call_v12(
761 struct afb_api_x3 *apix3,
764 struct json_object *args,
765 void (*callback)(void*, int, struct json_object*),
768 struct afb_export *export = from_api_x3(apix3);
769 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
772 /* the interface for services */
773 static const struct afb_service_itf_x1 hooked_service_itf = {
774 .call = legacy_hooked_call_v12,
775 .call_sync = legacy_hooked_call_sync
781 /******************************************************************************
782 ******************************************************************************
783 ******************************************************************************
784 ******************************************************************************
786 ******************************************************************************
787 ******************************************************************************
788 ******************************************************************************
789 ******************************************************************************/
791 static int api_set_verbs_v2_cb(
792 struct afb_api_x3 *api,
793 const struct afb_verb_v2 *verbs)
795 #if WITH_LEGACY_BINDING_V2
796 struct afb_export *export = from_api_x3(api);
798 if (export->unsealed) {
799 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
810 static int api_set_verbs_v3_cb(
811 struct afb_api_x3 *api,
812 const struct afb_verb_v3 *verbs)
814 struct afb_export *export = from_api_x3(api);
816 if (!export->unsealed) {
821 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
825 static int api_add_verb_cb(
826 struct afb_api_x3 *api,
829 void (*callback)(struct afb_req_x2 *req),
831 const struct afb_auth *auth,
835 struct afb_export *export = from_api_x3(api);
837 if (!export->unsealed) {
842 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
845 static int api_del_verb_cb(
846 struct afb_api_x3 *api,
850 struct afb_export *export = from_api_x3(api);
852 if (!export->unsealed) {
857 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
860 static int api_set_on_event_cb(
861 struct afb_api_x3 *api,
862 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
864 struct afb_export *export = from_api_x3(api);
865 return afb_export_handle_events_v3(export, onevent);
868 static int api_set_on_init_cb(
869 struct afb_api_x3 *api,
870 int (*oninit)(struct afb_api_x3 *api))
872 struct afb_export *export = from_api_x3(api);
874 return afb_export_handle_init_v3(export, oninit);
877 static void api_seal_cb(
878 struct afb_api_x3 *api)
880 struct afb_export *export = from_api_x3(api);
882 export->unsealed = 0;
885 static int event_handler_add_cb(
886 struct afb_api_x3 *api,
888 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
891 struct afb_export *export = from_api_x3(api);
893 return afb_export_event_handler_add(export, pattern, callback, closure);
896 static int event_handler_del_cb(
897 struct afb_api_x3 *api,
901 struct afb_export *export = from_api_x3(api);
903 return afb_export_event_handler_del(export, pattern, closure);
906 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
908 struct afb_export *export = from_api_x3(api);
911 char *iter, *end, save;
913 iter = strdupa(name);
919 if (!save) /* at end? */
922 /* search for the end */
924 while (save && !isspace(save))
928 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
937 static int class_require_cb(struct afb_api_x3 *api, const char *name)
939 struct afb_export *export = from_api_x3(api);
942 char *iter, *end, save;
944 iter = strdupa(name);
950 if (!save) /* at end? */
953 /* search for the end */
955 while (save && !isspace(save))
959 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
968 static int delete_api_cb(struct afb_api_x3 *api)
970 struct afb_export *export = from_api_x3(api);
972 if (!export->unsealed) {
977 afb_export_undeclare(export);
978 afb_export_unref(export);
982 static struct json_object *settings_cb(struct afb_api_x3 *api)
984 struct afb_export *export = from_api_x3(api);
985 struct json_object *result = export->settings;
987 result = make_settings(export);
991 static const struct afb_api_x3_itf api_x3_itf = {
993 .vverbose = (void*)vverbose_cb,
995 .get_event_loop = get_event_loop,
996 .get_user_bus = get_user_bus,
997 .get_system_bus = get_system_bus,
998 .rootdir_get_fd = afb_common_rootdir_get_fd,
999 .rootdir_open_locale = rootdir_open_locale_cb,
1000 .queue_job = queue_job_cb,
1002 .require_api = require_api_cb,
1003 .add_alias = add_alias_cb,
1005 .event_broadcast = event_broadcast_cb,
1006 .event_make = event_x2_make_cb,
1008 .legacy_call = legacy_call_x3,
1009 .legacy_call_sync = legacy_call_sync,
1011 .api_new_api = api_new_api_cb,
1012 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1013 .api_add_verb = api_add_verb_cb,
1014 .api_del_verb = api_del_verb_cb,
1015 .api_set_on_event = api_set_on_event_cb,
1016 .api_set_on_init = api_set_on_init_cb,
1017 .api_seal = api_seal_cb,
1018 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1019 .event_handler_add = event_handler_add_cb,
1020 .event_handler_del = event_handler_del_cb,
1023 .call_sync = call_sync_x3,
1025 .class_provide = class_provide_cb,
1026 .class_require = class_require_cb,
1028 .delete_api = delete_api_cb,
1029 .settings = settings_cb,
1033 static int hooked_api_set_verbs_v2_cb(
1034 struct afb_api_x3 *api,
1035 const struct afb_verb_v2 *verbs)
1037 struct afb_export *export = from_api_x3(api);
1038 int result = api_set_verbs_v2_cb(api, verbs);
1039 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
1042 static int hooked_api_set_verbs_v3_cb(
1043 struct afb_api_x3 *api,
1044 const struct afb_verb_v3 *verbs)
1046 struct afb_export *export = from_api_x3(api);
1047 int result = api_set_verbs_v3_cb(api, verbs);
1048 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
1051 static int hooked_api_add_verb_cb(
1052 struct afb_api_x3 *api,
1055 void (*callback)(struct afb_req_x2 *req),
1057 const struct afb_auth *auth,
1061 struct afb_export *export = from_api_x3(api);
1062 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
1063 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
1066 static int hooked_api_del_verb_cb(
1067 struct afb_api_x3 *api,
1071 struct afb_export *export = from_api_x3(api);
1072 int result = api_del_verb_cb(api, verb, vcbdata);
1073 return afb_hook_api_api_del_verb(export, result, verb);
1076 static int hooked_api_set_on_event_cb(
1077 struct afb_api_x3 *api,
1078 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1080 struct afb_export *export = from_api_x3(api);
1081 int result = api_set_on_event_cb(api, onevent);
1082 return afb_hook_api_api_set_on_event(export, result);
1085 static int hooked_api_set_on_init_cb(
1086 struct afb_api_x3 *api,
1087 int (*oninit)(struct afb_api_x3 *api))
1089 struct afb_export *export = from_api_x3(api);
1090 int result = api_set_on_init_cb(api, oninit);
1091 return afb_hook_api_api_set_on_init(export, result);
1094 static void hooked_api_seal_cb(
1095 struct afb_api_x3 *api)
1097 struct afb_export *export = from_api_x3(api);
1098 afb_hook_api_api_seal(export);
1102 static int hooked_event_handler_add_cb(
1103 struct afb_api_x3 *api,
1104 const char *pattern,
1105 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1108 struct afb_export *export = from_api_x3(api);
1109 int result = event_handler_add_cb(api, pattern, callback, closure);
1110 return afb_hook_api_event_handler_add(export, result, pattern);
1113 static int hooked_event_handler_del_cb(
1114 struct afb_api_x3 *api,
1115 const char *pattern,
1118 struct afb_export *export = from_api_x3(api);
1119 int result = event_handler_del_cb(api, pattern, closure);
1120 return afb_hook_api_event_handler_del(export, result, pattern);
1123 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1125 struct afb_export *export = from_api_x3(api);
1126 int result = class_provide_cb(api, name);
1127 return afb_hook_api_class_provide(export, result, name);
1130 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1132 struct afb_export *export = from_api_x3(api);
1133 int result = class_require_cb(api, name);
1134 return afb_hook_api_class_require(export, result, name);
1137 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1139 struct afb_export *export = afb_export_addref(from_api_x3(api));
1140 int result = delete_api_cb(api);
1141 result = afb_hook_api_delete_api(export, result);
1142 afb_export_unref(export);
1146 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1148 struct afb_export *export = from_api_x3(api);
1149 struct json_object *result = settings_cb(api);
1150 result = afb_hook_api_settings(export, result);
1154 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1156 .vverbose = hooked_vverbose_cb,
1158 .get_event_loop = hooked_get_event_loop,
1159 .get_user_bus = hooked_get_user_bus,
1160 .get_system_bus = hooked_get_system_bus,
1161 .rootdir_get_fd = hooked_rootdir_get_fd,
1162 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1163 .queue_job = hooked_queue_job_cb,
1165 .require_api = hooked_require_api_cb,
1166 .add_alias = hooked_add_alias_cb,
1168 .event_broadcast = hooked_event_broadcast_cb,
1169 .event_make = hooked_event_x2_make_cb,
1171 .legacy_call = legacy_hooked_call_x3,
1172 .legacy_call_sync = legacy_hooked_call_sync,
1174 .api_new_api = hooked_api_new_api_cb,
1175 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1176 .api_add_verb = hooked_api_add_verb_cb,
1177 .api_del_verb = hooked_api_del_verb_cb,
1178 .api_set_on_event = hooked_api_set_on_event_cb,
1179 .api_set_on_init = hooked_api_set_on_init_cb,
1180 .api_seal = hooked_api_seal_cb,
1181 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1182 .event_handler_add = hooked_event_handler_add_cb,
1183 .event_handler_del = hooked_event_handler_del_cb,
1185 .call = hooked_call_x3,
1186 .call_sync = hooked_call_sync_x3,
1188 .class_provide = hooked_class_provide_cb,
1189 .class_require = hooked_class_require_cb,
1191 .delete_api = hooked_delete_api_cb,
1192 .settings = hooked_settings_cb,
1196 /******************************************************************************
1197 ******************************************************************************
1198 ******************************************************************************
1199 ******************************************************************************
1201 ******************************************************************************
1202 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************/
1207 * Propagates the event to the service
1209 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1211 const struct globset_handler *handler;
1212 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1213 struct afb_export *export = from_api_x3(closure);
1216 /* hook the event before */
1217 if (export->hooksvc & afb_hook_flag_api_on_event)
1218 afb_hook_api_on_event_before(export, event, eventid, object);
1221 /* transmit to specific handlers */
1222 /* search the handler */
1223 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1225 callback = handler->callback;
1227 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1229 callback(handler->closure, event, object, to_api_x3(export));
1232 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1233 callback(handler->closure, event, object, to_api_x3(export));
1234 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1238 /* transmit to default handler */
1239 if (export->on_any_event_v3)
1240 export->on_any_event_v3(to_api_x3(export), event, object);
1241 else if (export->on_any_event_v12)
1242 export->on_any_event_v12(event, object);
1246 /* hook the event after */
1247 if (export->hooksvc & afb_hook_flag_api_on_event)
1248 afb_hook_api_on_event_after(export, event, eventid, object);
1250 json_object_put(object);
1253 static void listener_of_pushed_events(void *closure, const char *event, int eventid, struct json_object *object)
1255 listener_of_events(closure, event, eventid, object);
1258 static void listener_of_broadcasted_events(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop)
1260 listener_of_events(closure, event, 0, object);
1263 /* the interface for events */
1264 static const struct afb_evt_itf evt_itf = {
1265 .broadcast = listener_of_broadcasted_events,
1266 .push = listener_of_pushed_events
1269 /* ensure an existing listener */
1270 static int ensure_listener(struct afb_export *export)
1272 if (!export->listener) {
1273 export->listener = afb_evt_listener_create(&evt_itf, export);
1274 if (export->listener == NULL)
1280 int afb_export_event_handler_add(
1281 struct afb_export *export,
1282 const char *pattern,
1283 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1288 /* ensure the listener */
1289 rc = ensure_listener(export);
1293 /* ensure the globset for event handling */
1294 if (!export->event_handlers) {
1295 export->event_handlers = globset_create();
1296 if (!export->event_handlers)
1300 /* add the handler */
1301 rc = globset_add(export->event_handlers, pattern, callback, closure);
1305 if (errno == EEXIST) {
1306 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1311 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1315 int afb_export_event_handler_del(
1316 struct afb_export *export,
1317 const char *pattern,
1320 if (export->event_handlers
1321 && !globset_del(export->event_handlers, pattern, closure))
1324 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1329 /******************************************************************************
1330 ******************************************************************************
1331 ******************************************************************************
1332 ******************************************************************************
1334 ******************************************************************************
1335 ******************************************************************************
1336 ******************************************************************************
1337 ******************************************************************************/
1339 static void set_interfaces(struct afb_export *export)
1342 export->hookditf = afb_hook_flags_api(export->api.apiname);
1343 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1344 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1346 switch (export->version) {
1347 #if WITH_LEGACY_BINDING_V1
1349 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1352 #if WITH_LEGACY_BINDING_V2
1354 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1355 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1361 export->api.itf = &api_x3_itf;
1363 switch (export->version) {
1364 #if WITH_LEGACY_BINDING_V1
1366 export->export.v1.daemon.itf = &daemon_itf;
1369 #if WITH_LEGACY_BINDING_V2
1371 export->export.v2->daemon.itf = &daemon_itf;
1372 export->export.v2->service.itf = &service_itf;
1380 static struct afb_export *create(
1381 struct afb_apiset *declare_set,
1382 struct afb_apiset *call_set,
1383 const char *apiname,
1385 enum afb_api_version version)
1387 struct afb_export *export;
1390 /* session shared with other exports */
1391 if (common_session == NULL) {
1392 common_session = afb_session_create (0);
1393 if (common_session == NULL)
1396 lenapi = strlen(apiname);
1397 export = calloc(1, sizeof *export + 1 + lenapi + (path == apiname || !path ? 0 : 1 + strlen(path)));
1401 export->refcount = 1;
1402 strcpy(export->name, apiname);
1403 export->api.apiname = export->name;
1404 if (path == apiname)
1405 export->path = export->name;
1407 export->path = strcpy(&export->name[lenapi + 1], path);
1408 export->version = version;
1409 export->state = Api_State_Pre_Init;
1410 export->session = afb_session_addref(common_session);
1411 export->declare_set = afb_apiset_addref(declare_set);
1412 export->call_set = afb_apiset_addref(call_set);
1417 struct afb_export *afb_export_addref(struct afb_export *export)
1420 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1424 void afb_export_unref(struct afb_export *export)
1426 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1427 afb_export_destroy(export);
1430 void afb_export_destroy(struct afb_export *export)
1433 if (export->event_handlers)
1434 globset_destroy(export->event_handlers);
1435 if (export->listener != NULL)
1436 afb_evt_listener_unref(export->listener);
1437 afb_session_unref(export->session);
1438 afb_apiset_unref(export->declare_set);
1439 afb_apiset_unref(export->call_set);
1440 json_object_put(export->settings);
1441 afb_export_unref(export->creator);
1442 if (export->api.apiname != export->name)
1443 free((void*)export->api.apiname);
1448 struct afb_export *afb_export_create_none_for_path(
1449 struct afb_apiset *declare_set,
1450 struct afb_apiset *call_set,
1452 int (*creator)(void*, struct afb_api_x3*),
1455 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1457 afb_export_logmask_set(export, logmask);
1458 set_interfaces(export);
1459 if (creator && creator(closure, to_api_x3(export)) < 0) {
1460 afb_export_unref(export);
1467 #if WITH_LEGACY_BINDING_V1
1468 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1469 struct afb_apiset *call_set,
1470 const char *apiname,
1471 int (*init)(struct afb_service_x1),
1472 void (*onevent)(const char*, struct json_object*),
1475 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1477 export->init.v1 = init;
1478 export->on_any_event_v12 = onevent;
1479 export->export.v1.mode = AFB_MODE_LOCAL;
1480 export->export.v1.daemon.closure = to_api_x3(export);
1481 afb_export_logmask_set(export, logmask);
1482 set_interfaces(export);
1488 #if WITH_LEGACY_BINDING_V2
1489 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1490 struct afb_apiset *call_set,
1491 const char *apiname,
1492 const struct afb_binding_v2 *binding,
1493 struct afb_binding_data_v2 *data,
1495 void (*onevent)(const char*, struct json_object*),
1498 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1500 export->init.v2 = init;
1501 export->on_any_event_v12 = onevent;
1502 export->desc.v2 = binding;
1503 export->export.v2 = data;
1504 data->daemon.closure = to_api_x3(export);
1505 data->service.closure = to_api_x3(export);
1506 afb_export_logmask_set(export, logmask);
1507 set_interfaces(export);
1513 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1514 struct afb_apiset *call_set,
1515 const char *apiname,
1516 struct afb_api_v3 *apiv3,
1517 struct afb_export* creator,
1520 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1522 export->unsealed = 1;
1523 export->desc.v3 = apiv3;
1524 export->creator = afb_export_addref(creator);
1525 afb_export_logmask_set(export, logmask);
1526 set_interfaces(export);
1531 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1533 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1536 int afb_export_rename(struct afb_export *export, const char *apiname)
1540 if (export->declared) {
1545 /* copy the name locally */
1546 name = strdup(apiname);
1552 if (export->api.apiname != export->name)
1553 free((void*)export->api.apiname);
1554 export->api.apiname = name;
1556 set_interfaces(export);
1560 const char *afb_export_apiname(const struct afb_export *export)
1562 return export->api.apiname;
1565 int afb_export_unshare_session(struct afb_export *export)
1567 if (export->session == common_session) {
1568 export->session = afb_session_create (0);
1569 if (export->session)
1570 afb_session_unref(common_session);
1572 export->session = common_session;
1579 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1580 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1583 switch (export->version) {
1584 #if WITH_LEGACY_BINDING_V1
1587 #if WITH_LEGACY_BINDING_V2
1592 ERROR("invalid version 12 for API %s", export->api.apiname);
1597 export->on_any_event_v12 = on_event;
1598 return ensure_listener(export);
1602 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))
1605 switch (export->version) {
1606 case Api_Version_3: break;
1608 ERROR("invalid version Dyn for API %s", export->api.apiname);
1613 export->on_any_event_v3 = on_event;
1614 return ensure_listener(export);
1617 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1619 if (export->state != Api_State_Pre_Init) {
1620 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1625 export->init.v3 = oninit;
1629 #if WITH_LEGACY_BINDING_V1
1631 * Starts a new service (v1)
1633 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1635 return export->desc.v1 = regfun(&export->export.v1);
1639 int afb_export_preinit_x3(
1640 struct afb_export *export,
1641 int (*preinit)(void*, struct afb_api_x3*),
1644 return preinit(closure, to_api_x3(export));
1647 int afb_export_logmask_get(const struct afb_export *export)
1649 return export->api.logmask;
1652 void afb_export_logmask_set(struct afb_export *export, int mask)
1654 export->api.logmask = mask;
1655 switch (export->version) {
1656 #if WITH_LEGACY_BINDING_V1
1657 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1659 #if WITH_LEGACY_BINDING_V2
1660 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1665 void *afb_export_userdata_get(const struct afb_export *export)
1667 return export->api.userdata;
1670 void afb_export_userdata_set(struct afb_export *export, void *data)
1672 export->api.userdata = data;
1675 /******************************************************************************
1676 ******************************************************************************
1677 ******************************************************************************
1678 ******************************************************************************
1680 ******************************************************************************
1681 ******************************************************************************
1682 ******************************************************************************
1683 ******************************************************************************/
1688 struct afb_export *export;
1691 static void do_init(int sig, void *closure)
1694 struct init *init = closure;
1695 struct afb_export *export;
1700 export = init->export;
1701 switch (export->version) {
1702 #if WITH_LEGACY_BINDING_V1
1704 rc = export->init.v1 ? export->init.v1(
1705 (struct afb_service_x1){
1707 .itf = &hooked_service_itf,
1709 .itf = &service_itf,
1711 .closure = to_api_x3(export) }) : 0;
1714 #if WITH_LEGACY_BINDING_V2
1716 rc = export->init.v2 ? export->init.v2() : 0;
1720 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1727 init->return_code = rc;
1731 int afb_export_start(struct afb_export *export)
1737 switch (export->state) {
1741 case Api_State_Init:
1742 /* starting in progress: it is an error */
1743 ERROR("Service of API %s required started while starting", export->api.apiname);
1750 /* set event handling */
1751 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1752 switch (export->version) {
1753 #if WITH_LEGACY_BINDING_V1
1756 #if WITH_LEGACY_BINDING_V2
1759 if (export->on_any_event_v12) {
1760 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1769 ERROR("Can't set event handler for %s", export->api.apiname);
1775 /* Starts the service */
1776 if (export->hooksvc & afb_hook_flag_api_start)
1777 afb_hook_api_start_before(export);
1780 export->state = Api_State_Init;
1781 init.export = export;
1782 sig_monitor(0, do_init, &init);
1783 rc = init.return_code;
1784 export->state = Api_State_Run;
1787 if (export->hooksvc & afb_hook_flag_api_start)
1788 afb_hook_api_start_after(export, rc);
1792 /* initialisation error */
1793 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1800 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1802 struct afb_export *export = closure;
1804 xreq->request.api = to_api_x3(export);
1806 switch (export->version) {
1807 #if WITH_LEGACY_BINDING_V1
1809 afb_api_so_v1_process_call(export->desc.v1, xreq);
1812 #if WITH_LEGACY_BINDING_V2
1814 afb_api_so_v2_process_call(export->desc.v2, xreq);
1818 afb_api_v3_process_call(export->desc.v3, xreq);
1821 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1826 static struct json_object *api_describe_cb(void *closure)
1828 struct afb_export *export = closure;
1829 struct json_object *result;
1831 switch (export->version) {
1832 #if WITH_LEGACY_BINDING_V1
1834 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1837 #if WITH_LEGACY_BINDING_V2
1839 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1843 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1852 static int api_service_start_cb(void *closure)
1854 struct afb_export *export = closure;
1856 return afb_export_start(export);
1860 static void api_update_hooks_cb(void *closure)
1861 __attribute__((alias("set_interfaces")));
1863 void afb_export_update_hooks(struct afb_export *export)
1864 __attribute__((alias("set_interfaces")));
1867 static int api_get_logmask_cb(void *closure)
1869 struct afb_export *export = closure;
1871 return afb_export_logmask_get(export);
1874 static void api_set_logmask_cb(void *closure, int level)
1876 struct afb_export *export = closure;
1878 afb_export_logmask_set(export, level);
1881 static void api_unref_cb(void *closure)
1883 struct afb_export *export = closure;
1885 afb_export_unref(export);
1888 static struct afb_api_itf export_api_itf =
1890 .call = api_call_cb,
1891 .service_start = api_service_start_cb,
1893 .update_hooks = api_update_hooks_cb,
1895 .get_logmask = api_get_logmask_cb,
1896 .set_logmask = api_set_logmask_cb,
1897 .describe = api_describe_cb,
1898 .unref = api_unref_cb
1901 int afb_export_declare(struct afb_export *export,
1905 struct afb_api_item afb_api;
1907 if (export->declared)
1910 /* init the record structure */
1911 afb_api.closure = afb_export_addref(export);
1912 afb_api.itf = &export_api_itf;
1913 afb_api.group = noconcurrency ? export : NULL;
1915 /* records the binding */
1916 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1918 export->declared = 1;
1920 ERROR("can't declare export %s to set %s, ABORTING it!",
1921 export->api.apiname,
1922 afb_apiset_name(export->declare_set));
1923 afb_export_unref(export);
1930 void afb_export_undeclare(struct afb_export *export)
1932 if (export->declared) {
1933 export->declared = 0;
1934 afb_apiset_del(export->declare_set, export->api.apiname);
1938 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1940 return afb_evt_event_x2_add_watch(export->listener, event);
1943 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1945 return afb_evt_event_x2_remove_watch(export->listener, event);
1948 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1950 afb_xreq_process(xreq, export->call_set);
1953 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1955 afb_context_init(context, export->session, NULL);
1956 context->validated = 1;