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"
52 #include "afb-error-text.h"
58 #include "sig-monitor.h"
59 #include "wrap-json.h"
61 /*************************************************************************
63 ************************************************************************/
66 * Actually supported versions
71 #if WITH_LEGACY_BINDING_V1
74 #if WITH_LEGACY_BINDING_V2
81 * The states of exported APIs
91 * structure of the exported API
96 struct afb_api_x3 api;
101 /* version of the api */
108 unsigned declared: 1;
111 unsigned unsealed: 1;
119 /* session for service */
120 struct afb_session *session;
122 /* apiset the API is declared in */
123 struct afb_apiset *declare_set;
125 /* apiset for calls */
126 struct afb_apiset *call_set;
128 /* event listener for service or NULL */
129 struct afb_evt_listener *listener;
131 /* event handler list */
132 struct globset *event_handlers;
135 struct afb_export *creator;
137 /* path indication if any */
141 struct json_object *settings;
143 /* internal descriptors */
145 #if WITH_LEGACY_BINDING_V1
146 struct afb_binding_v1 *v1;
148 const struct afb_binding_v2 *v2;
149 struct afb_api_v3 *v3;
154 #if WITH_LEGACY_BINDING_V1
155 int (*v1)(struct afb_service_x1);
158 int (*v3)(struct afb_api_x3 *api);
162 void (*on_any_event_v12)(const char *event, struct json_object *object);
163 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
167 #if WITH_LEGACY_BINDING_V1
168 struct afb_binding_interface_v1 v1;
170 struct afb_binding_data_v2 *v2;
177 /*****************************************************************************/
179 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
181 return (struct afb_api_x3*)export;
184 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
186 return (struct afb_export*)api;
189 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
191 return from_api_x3(api);
194 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
196 return to_api_x3(export);
199 /******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
202 ******************************************************************************
204 ******************************************************************************
205 ******************************************************************************
206 ******************************************************************************
207 ******************************************************************************/
209 static struct json_object *configuration;
211 void afb_export_set_config(struct json_object *config)
213 struct json_object *save = configuration;
214 configuration = json_object_get(config);
215 json_object_put(save);
218 static struct json_object *make_settings(struct afb_export *export)
220 struct json_object *result;
221 struct json_object *obj;
222 struct afb_export *iter;
225 /* clone the globals */
226 if (json_object_object_get_ex(configuration, "*", &obj))
227 result = wrap_json_clone(obj);
229 result = json_object_new_object();
232 if (json_object_object_get_ex(configuration, export->name, &obj))
233 wrap_json_object_add(result, obj);
235 /* add library path */
236 for (iter = export ; iter && !iter->path ; iter = iter->creator);
238 path = realpath(iter->path, NULL);
239 json_object_object_add(result, "binding-path", json_object_new_string(path));
243 export->settings = result;
247 /******************************************************************************
248 ******************************************************************************
249 ******************************************************************************
250 ******************************************************************************
252 ******************************************************************************
253 ******************************************************************************
254 ******************************************************************************
255 ******************************************************************************/
257 /**********************************************
259 **********************************************/
260 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)
263 struct afb_export *export = from_api_x3(closure);
265 if (!fmt || vasprintf(&p, fmt, args) < 0)
266 vverbose(level, file, line, function, fmt, args);
268 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
273 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
275 struct afb_export *export = from_api_x3(closure);
277 /* check daemon state */
278 if (export->state == Api_State_Pre_Init) {
279 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
284 /* create the event */
285 return afb_evt_event_x2_create2(export->api.apiname, name);
288 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
292 struct afb_export *export = from_api_x3(closure);
294 /* check daemon state */
295 if (export->state == Api_State_Pre_Init) {
296 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
297 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
302 /* makes the event name */
303 plen = strlen(export->api.apiname);
305 event = alloca(nlen + plen + 2);
306 memcpy(event, export->api.apiname, plen);
308 memcpy(event + plen + 1, name, nlen + 1);
310 /* broadcast the event */
311 return afb_evt_broadcast(event, object);
314 static struct sd_event *get_event_loop(struct afb_api_x3 *closure)
316 jobs_acquire_event_manager();
317 return systemd_get_event_loop();
320 static struct sd_bus *get_user_bus(struct afb_api_x3 *closure)
322 jobs_acquire_event_manager();
323 return systemd_get_user_bus();
326 static struct sd_bus *get_system_bus(struct afb_api_x3 *closure)
328 jobs_acquire_event_manager();
329 return systemd_get_system_bus();
332 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
334 return afb_common_rootdir_open_locale(filename, flags, locale);
337 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
339 return jobs_queue(group, timeout, callback, argument);
342 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
344 struct afb_export *export = from_api_x3(closure);
346 char *iter, *end, save;
348 /* emit a warning about unexpected require in preinit */
349 if (export->state == Api_State_Pre_Init && initialized) {
350 ERROR("[API %s] requiring initialized apis in pre-init is forbiden", export->api.apiname);
355 /* scan the names in a local copy */
357 iter = strdupa(name);
363 if (!save) /* at end? */
366 /* search for the end */
368 while (save && !isspace(save))
372 /* check the required api */
373 if (export->state == Api_State_Pre_Init) {
374 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, iter);
377 WARNING("[API %s] requiring apis pre-init may lead to unexpected result", export->api.apiname);
378 ERROR("[API %s] requiring api %s in pre-init failed", export->api.apiname, iter);
381 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
383 ERROR("[API %s] requiring api %s%s failed", export->api.apiname,
384 iter, initialized ? " initialized" : "");
395 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
397 struct afb_export *export = from_api_x3(closure);
398 if (!afb_api_is_valid_name(aliasname)) {
399 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
403 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
404 afb_export_add_alias(export, apiname, aliasname);
408 static struct afb_api_x3 *api_new_api_cb(
409 struct afb_api_x3 *closure,
413 int (*preinit)(void*, struct afb_api_x3 *),
414 void *preinit_closure)
416 struct afb_export *export = from_api_x3(closure);
417 struct afb_api_v3 *apiv3 = afb_api_v3_create(
418 export->declare_set, export->call_set,
419 api, info, noconcurrency,
420 preinit, preinit_closure, 1,
422 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
425 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
427 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
429 vverbose_cb(closure, level, file, line, NULL, fmt, args);
432 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
434 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
435 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
438 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
440 return afb_xreq_unstore(sreq);
443 static const struct afb_daemon_itf_x1 daemon_itf = {
444 .vverbose_v1 = legacy_vverbose_v1_cb,
445 .vverbose_v2 = vverbose_cb,
446 .event_make = legacy_event_x1_make_cb,
447 .event_broadcast = event_broadcast_cb,
448 .get_event_loop = get_event_loop,
449 .get_user_bus = get_user_bus,
450 .get_system_bus = get_system_bus,
451 .rootdir_get_fd = afb_common_rootdir_get_fd,
452 .rootdir_open_locale = rootdir_open_locale_cb,
453 .queue_job = queue_job_cb,
454 .unstore_req = legacy_unstore_req_cb,
455 .require_api = require_api_cb,
456 .add_alias = add_alias_cb,
457 .new_api = api_new_api_cb,
462 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)
464 struct afb_export *export = from_api_x3(closure);
467 vverbose_cb(closure, level, file, line, function, fmt, args);
468 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
472 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
474 struct afb_export *export = from_api_x3(closure);
475 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
476 afb_hook_api_event_make(export, name, r);
480 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
483 struct afb_export *export = from_api_x3(closure);
484 json_object_get(object);
485 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
486 r = event_broadcast_cb(closure, name, object);
487 afb_hook_api_event_broadcast_after(export, name, object, r);
488 json_object_put(object);
492 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
494 struct afb_export *export = from_api_x3(closure);
497 jobs_acquire_event_manager();
498 r = get_event_loop(closure);
499 return afb_hook_api_get_event_loop(export, r);
502 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
504 struct afb_export *export = from_api_x3(closure);
507 jobs_acquire_event_manager();
508 r = get_user_bus(closure);
509 return afb_hook_api_get_user_bus(export, r);
512 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
514 struct afb_export *export = from_api_x3(closure);
517 jobs_acquire_event_manager();
518 r = get_system_bus(closure);
519 return afb_hook_api_get_system_bus(export, r);
522 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
524 struct afb_export *export = from_api_x3(closure);
525 int r = afb_common_rootdir_get_fd();
526 return afb_hook_api_rootdir_get_fd(export, r);
529 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
531 struct afb_export *export = from_api_x3(closure);
532 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
533 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
536 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
538 struct afb_export *export = from_api_x3(closure);
539 int r = queue_job_cb(closure, callback, argument, group, timeout);
540 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
543 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
546 struct afb_export *export = from_api_x3(closure);
547 afb_hook_api_require_api(export, name, initialized);
548 result = require_api_cb(closure, name, initialized);
549 return afb_hook_api_require_api_result(export, name, initialized, result);
552 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
554 struct afb_export *export = from_api_x3(closure);
555 int result = add_alias_cb(closure, apiname, aliasname);
556 return afb_hook_api_add_alias(export, apiname, aliasname, result);
559 static struct afb_api_x3 *hooked_api_new_api_cb(
560 struct afb_api_x3 *closure,
564 int (*preinit)(void*, struct afb_api_x3 *),
565 void *preinit_closure)
567 struct afb_api_x3 *result;
568 struct afb_export *export = from_api_x3(closure);
569 afb_hook_api_new_api_before(export, api, info, noconcurrency);
570 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
571 afb_hook_api_new_api_after(export, -!result, api);
575 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
577 static void legacy_hooked_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
579 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
582 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
584 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
585 struct afb_event_x1 e;
587 e.itf = event ? event->itf : NULL;
591 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
593 struct afb_export *export = from_api_x3(closure);
594 afb_hook_api_legacy_unstore_req(export, sreq);
595 return legacy_unstore_req_cb(closure, sreq);
598 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
599 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
600 .vverbose_v2 = hooked_vverbose_cb,
601 .event_make = legacy_hooked_event_x1_make_cb,
602 .event_broadcast = hooked_event_broadcast_cb,
603 .get_event_loop = hooked_get_event_loop,
604 .get_user_bus = hooked_get_user_bus,
605 .get_system_bus = hooked_get_system_bus,
606 .rootdir_get_fd = hooked_rootdir_get_fd,
607 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
608 .queue_job = hooked_queue_job_cb,
609 .unstore_req = legacy_hooked_unstore_req_cb,
610 .require_api = hooked_require_api_cb,
611 .add_alias = hooked_add_alias_cb,
612 .new_api = hooked_api_new_api_cb,
618 /******************************************************************************
619 ******************************************************************************
620 ******************************************************************************
621 ******************************************************************************
623 ******************************************************************************
624 ******************************************************************************
625 ******************************************************************************
626 ******************************************************************************/
628 /* the common session for services sharing their session */
629 static struct afb_session *common_session;
631 /******************************************************************************
632 ******************************************************************************
633 ******************************************************************************
634 ******************************************************************************
636 ******************************************************************************
637 ******************************************************************************
638 ******************************************************************************
639 ******************************************************************************/
642 struct afb_api_x3 *apix3,
645 struct json_object *args,
646 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
649 struct afb_export *export = from_api_x3(apix3);
650 return afb_calls_call(export, api, verb, args, callback, closure);
653 static int call_sync_x3(
654 struct afb_api_x3 *apix3,
657 struct json_object *args,
658 struct json_object **object,
662 struct afb_export *export = from_api_x3(apix3);
663 return afb_calls_call_sync(export, api, verb, args, object, error, info);
666 static void legacy_call_x3(
667 struct afb_api_x3 *apix3,
670 struct json_object *args,
671 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
674 struct afb_export *export = from_api_x3(apix3);
675 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
678 static int legacy_call_sync(
679 struct afb_api_x3 *apix3,
682 struct json_object *args,
683 struct json_object **result)
685 struct afb_export *export = from_api_x3(apix3);
686 return afb_calls_legacy_call_sync(export, api, verb, args, result);
689 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
691 static void legacy_call_v12(
692 struct afb_api_x3 *apix3,
695 struct json_object *args,
696 void (*callback)(void*, int, struct json_object*),
699 struct afb_export *export = from_api_x3(apix3);
700 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
703 /* the interface for services */
704 static const struct afb_service_itf_x1 service_itf = {
705 .call = legacy_call_v12,
706 .call_sync = legacy_call_sync
711 static void hooked_call_x3(
712 struct afb_api_x3 *apix3,
715 struct json_object *args,
716 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
719 struct afb_export *export = from_api_x3(apix3);
720 afb_calls_hooked_call(export, api, verb, args, callback, closure);
723 static int hooked_call_sync_x3(
724 struct afb_api_x3 *apix3,
727 struct json_object *args,
728 struct json_object **object,
732 struct afb_export *export = from_api_x3(apix3);
733 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
736 static void legacy_hooked_call_x3(
737 struct afb_api_x3 *apix3,
740 struct json_object *args,
741 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
744 struct afb_export *export = from_api_x3(apix3);
745 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
748 static int legacy_hooked_call_sync(
749 struct afb_api_x3 *apix3,
752 struct json_object *args,
753 struct json_object **result)
755 struct afb_export *export = from_api_x3(apix3);
756 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
759 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
761 static void legacy_hooked_call_v12(
762 struct afb_api_x3 *apix3,
765 struct json_object *args,
766 void (*callback)(void*, int, struct json_object*),
769 struct afb_export *export = from_api_x3(apix3);
770 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
773 /* the interface for services */
774 static const struct afb_service_itf_x1 hooked_service_itf = {
775 .call = legacy_hooked_call_v12,
776 .call_sync = legacy_hooked_call_sync
782 /******************************************************************************
783 ******************************************************************************
784 ******************************************************************************
785 ******************************************************************************
787 ******************************************************************************
788 ******************************************************************************
789 ******************************************************************************
790 ******************************************************************************/
792 static int api_set_verbs_v2_cb(
793 struct afb_api_x3 *api,
794 const struct afb_verb_v2 *verbs)
796 #if WITH_LEGACY_BINDING_V2
797 struct afb_export *export = from_api_x3(api);
799 if (export->unsealed) {
800 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
811 static int api_set_verbs_v3_cb(
812 struct afb_api_x3 *api,
813 const struct afb_verb_v3 *verbs)
815 struct afb_export *export = from_api_x3(api);
817 if (!export->unsealed) {
822 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
826 static int api_add_verb_cb(
827 struct afb_api_x3 *api,
830 void (*callback)(struct afb_req_x2 *req),
832 const struct afb_auth *auth,
836 struct afb_export *export = from_api_x3(api);
838 if (!export->unsealed) {
843 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
846 static int api_del_verb_cb(
847 struct afb_api_x3 *api,
851 struct afb_export *export = from_api_x3(api);
853 if (!export->unsealed) {
858 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
861 static int api_set_on_event_cb(
862 struct afb_api_x3 *api,
863 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
865 struct afb_export *export = from_api_x3(api);
866 return afb_export_handle_events_v3(export, onevent);
869 static int api_set_on_init_cb(
870 struct afb_api_x3 *api,
871 int (*oninit)(struct afb_api_x3 *api))
873 struct afb_export *export = from_api_x3(api);
875 return afb_export_handle_init_v3(export, oninit);
878 static void api_seal_cb(
879 struct afb_api_x3 *api)
881 struct afb_export *export = from_api_x3(api);
883 export->unsealed = 0;
886 static int event_handler_add_cb(
887 struct afb_api_x3 *api,
889 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
892 struct afb_export *export = from_api_x3(api);
894 return afb_export_event_handler_add(export, pattern, callback, closure);
897 static int event_handler_del_cb(
898 struct afb_api_x3 *api,
902 struct afb_export *export = from_api_x3(api);
904 return afb_export_event_handler_del(export, pattern, closure);
907 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
909 struct afb_export *export = from_api_x3(api);
912 char *iter, *end, save;
914 iter = strdupa(name);
920 if (!save) /* at end? */
923 /* search for the end */
925 while (save && !isspace(save))
929 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
938 static int class_require_cb(struct afb_api_x3 *api, const char *name)
940 struct afb_export *export = from_api_x3(api);
943 char *iter, *end, save;
945 iter = strdupa(name);
951 if (!save) /* at end? */
954 /* search for the end */
956 while (save && !isspace(save))
960 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
969 static int delete_api_cb(struct afb_api_x3 *api)
971 struct afb_export *export = from_api_x3(api);
973 if (!export->unsealed) {
978 afb_export_undeclare(export);
979 afb_export_unref(export);
983 static struct json_object *settings_cb(struct afb_api_x3 *api)
985 struct afb_export *export = from_api_x3(api);
986 struct json_object *result = export->settings;
988 result = make_settings(export);
992 static const struct afb_api_x3_itf api_x3_itf = {
994 .vverbose = (void*)vverbose_cb,
996 .get_event_loop = get_event_loop,
997 .get_user_bus = get_user_bus,
998 .get_system_bus = get_system_bus,
999 .rootdir_get_fd = afb_common_rootdir_get_fd,
1000 .rootdir_open_locale = rootdir_open_locale_cb,
1001 .queue_job = queue_job_cb,
1003 .require_api = require_api_cb,
1004 .add_alias = add_alias_cb,
1006 .event_broadcast = event_broadcast_cb,
1007 .event_make = event_x2_make_cb,
1009 .legacy_call = legacy_call_x3,
1010 .legacy_call_sync = legacy_call_sync,
1012 .api_new_api = api_new_api_cb,
1013 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1014 .api_add_verb = api_add_verb_cb,
1015 .api_del_verb = api_del_verb_cb,
1016 .api_set_on_event = api_set_on_event_cb,
1017 .api_set_on_init = api_set_on_init_cb,
1018 .api_seal = api_seal_cb,
1019 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1020 .event_handler_add = event_handler_add_cb,
1021 .event_handler_del = event_handler_del_cb,
1024 .call_sync = call_sync_x3,
1026 .class_provide = class_provide_cb,
1027 .class_require = class_require_cb,
1029 .delete_api = delete_api_cb,
1030 .settings = settings_cb,
1034 static int hooked_api_set_verbs_v2_cb(
1035 struct afb_api_x3 *api,
1036 const struct afb_verb_v2 *verbs)
1038 struct afb_export *export = from_api_x3(api);
1039 int result = api_set_verbs_v2_cb(api, verbs);
1040 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
1043 static int hooked_api_set_verbs_v3_cb(
1044 struct afb_api_x3 *api,
1045 const struct afb_verb_v3 *verbs)
1047 struct afb_export *export = from_api_x3(api);
1048 int result = api_set_verbs_v3_cb(api, verbs);
1049 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
1052 static int hooked_api_add_verb_cb(
1053 struct afb_api_x3 *api,
1056 void (*callback)(struct afb_req_x2 *req),
1058 const struct afb_auth *auth,
1062 struct afb_export *export = from_api_x3(api);
1063 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
1064 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
1067 static int hooked_api_del_verb_cb(
1068 struct afb_api_x3 *api,
1072 struct afb_export *export = from_api_x3(api);
1073 int result = api_del_verb_cb(api, verb, vcbdata);
1074 return afb_hook_api_api_del_verb(export, result, verb);
1077 static int hooked_api_set_on_event_cb(
1078 struct afb_api_x3 *api,
1079 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1081 struct afb_export *export = from_api_x3(api);
1082 int result = api_set_on_event_cb(api, onevent);
1083 return afb_hook_api_api_set_on_event(export, result);
1086 static int hooked_api_set_on_init_cb(
1087 struct afb_api_x3 *api,
1088 int (*oninit)(struct afb_api_x3 *api))
1090 struct afb_export *export = from_api_x3(api);
1091 int result = api_set_on_init_cb(api, oninit);
1092 return afb_hook_api_api_set_on_init(export, result);
1095 static void hooked_api_seal_cb(
1096 struct afb_api_x3 *api)
1098 struct afb_export *export = from_api_x3(api);
1099 afb_hook_api_api_seal(export);
1103 static int hooked_event_handler_add_cb(
1104 struct afb_api_x3 *api,
1105 const char *pattern,
1106 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1109 struct afb_export *export = from_api_x3(api);
1110 int result = event_handler_add_cb(api, pattern, callback, closure);
1111 return afb_hook_api_event_handler_add(export, result, pattern);
1114 static int hooked_event_handler_del_cb(
1115 struct afb_api_x3 *api,
1116 const char *pattern,
1119 struct afb_export *export = from_api_x3(api);
1120 int result = event_handler_del_cb(api, pattern, closure);
1121 return afb_hook_api_event_handler_del(export, result, pattern);
1124 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1126 struct afb_export *export = from_api_x3(api);
1127 int result = class_provide_cb(api, name);
1128 return afb_hook_api_class_provide(export, result, name);
1131 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1133 struct afb_export *export = from_api_x3(api);
1134 int result = class_require_cb(api, name);
1135 return afb_hook_api_class_require(export, result, name);
1138 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1140 struct afb_export *export = afb_export_addref(from_api_x3(api));
1141 int result = delete_api_cb(api);
1142 result = afb_hook_api_delete_api(export, result);
1143 afb_export_unref(export);
1147 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1149 struct afb_export *export = from_api_x3(api);
1150 struct json_object *result = settings_cb(api);
1151 result = afb_hook_api_settings(export, result);
1155 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1157 .vverbose = hooked_vverbose_cb,
1159 .get_event_loop = hooked_get_event_loop,
1160 .get_user_bus = hooked_get_user_bus,
1161 .get_system_bus = hooked_get_system_bus,
1162 .rootdir_get_fd = hooked_rootdir_get_fd,
1163 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1164 .queue_job = hooked_queue_job_cb,
1166 .require_api = hooked_require_api_cb,
1167 .add_alias = hooked_add_alias_cb,
1169 .event_broadcast = hooked_event_broadcast_cb,
1170 .event_make = hooked_event_x2_make_cb,
1172 .legacy_call = legacy_hooked_call_x3,
1173 .legacy_call_sync = legacy_hooked_call_sync,
1175 .api_new_api = hooked_api_new_api_cb,
1176 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1177 .api_add_verb = hooked_api_add_verb_cb,
1178 .api_del_verb = hooked_api_del_verb_cb,
1179 .api_set_on_event = hooked_api_set_on_event_cb,
1180 .api_set_on_init = hooked_api_set_on_init_cb,
1181 .api_seal = hooked_api_seal_cb,
1182 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1183 .event_handler_add = hooked_event_handler_add_cb,
1184 .event_handler_del = hooked_event_handler_del_cb,
1186 .call = hooked_call_x3,
1187 .call_sync = hooked_call_sync_x3,
1189 .class_provide = hooked_class_provide_cb,
1190 .class_require = hooked_class_require_cb,
1192 .delete_api = hooked_delete_api_cb,
1193 .settings = hooked_settings_cb,
1197 /******************************************************************************
1198 ******************************************************************************
1199 ******************************************************************************
1200 ******************************************************************************
1202 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************
1205 ******************************************************************************/
1208 * Propagates the event to the service
1210 static void listener_of_events(void *closure, const char *event, uint16_t eventid, struct json_object *object)
1212 const struct globset_handler *handler;
1213 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1214 struct afb_export *export = from_api_x3(closure);
1217 /* hook the event before */
1218 if (export->hooksvc & afb_hook_flag_api_on_event)
1219 afb_hook_api_on_event_before(export, event, eventid, object);
1222 /* transmit to specific handlers */
1223 /* search the handler */
1224 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1226 callback = handler->callback;
1228 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1230 callback(handler->closure, event, object, to_api_x3(export));
1233 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1234 callback(handler->closure, event, object, to_api_x3(export));
1235 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1239 /* transmit to default handler */
1240 if (export->on_any_event_v3)
1241 export->on_any_event_v3(to_api_x3(export), event, object);
1242 else if (export->on_any_event_v12)
1243 export->on_any_event_v12(event, object);
1247 /* hook the event after */
1248 if (export->hooksvc & afb_hook_flag_api_on_event)
1249 afb_hook_api_on_event_after(export, event, eventid, object);
1251 json_object_put(object);
1254 static void listener_of_pushed_events(void *closure, const char *event, uint16_t eventid, struct json_object *object)
1256 listener_of_events(closure, event, eventid, object);
1259 static void listener_of_broadcasted_events(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop)
1261 listener_of_events(closure, event, 0, object);
1264 /* the interface for events */
1265 static const struct afb_evt_itf evt_itf = {
1266 .broadcast = listener_of_broadcasted_events,
1267 .push = listener_of_pushed_events
1270 /* ensure an existing listener */
1271 static int ensure_listener(struct afb_export *export)
1273 if (!export->listener) {
1274 export->listener = afb_evt_listener_create(&evt_itf, export);
1275 if (export->listener == NULL)
1281 int afb_export_event_handler_add(
1282 struct afb_export *export,
1283 const char *pattern,
1284 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1289 /* ensure the listener */
1290 rc = ensure_listener(export);
1294 /* ensure the globset for event handling */
1295 if (!export->event_handlers) {
1296 export->event_handlers = globset_create();
1297 if (!export->event_handlers)
1301 /* add the handler */
1302 rc = globset_add(export->event_handlers, pattern, callback, closure);
1306 if (errno == EEXIST) {
1307 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1312 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1316 int afb_export_event_handler_del(
1317 struct afb_export *export,
1318 const char *pattern,
1321 if (export->event_handlers
1322 && !globset_del(export->event_handlers, pattern, closure))
1325 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1330 /******************************************************************************
1331 ******************************************************************************
1332 ******************************************************************************
1333 ******************************************************************************
1335 ******************************************************************************
1336 ******************************************************************************
1337 ******************************************************************************
1338 ******************************************************************************/
1340 static void set_interfaces(struct afb_export *export)
1343 export->hookditf = afb_hook_flags_api(export->api.apiname);
1344 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1345 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1347 switch (export->version) {
1348 #if WITH_LEGACY_BINDING_V1
1350 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1353 #if WITH_LEGACY_BINDING_V2
1355 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1356 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1362 export->api.itf = &api_x3_itf;
1364 switch (export->version) {
1365 #if WITH_LEGACY_BINDING_V1
1367 export->export.v1.daemon.itf = &daemon_itf;
1370 #if WITH_LEGACY_BINDING_V2
1372 export->export.v2->daemon.itf = &daemon_itf;
1373 export->export.v2->service.itf = &service_itf;
1381 static struct afb_export *create(
1382 struct afb_apiset *declare_set,
1383 struct afb_apiset *call_set,
1384 const char *apiname,
1386 enum afb_api_version version)
1388 struct afb_export *export;
1391 /* session shared with other exports */
1392 if (common_session == NULL) {
1393 common_session = afb_session_create (0);
1394 if (common_session == NULL)
1397 lenapi = strlen(apiname);
1398 export = calloc(1, sizeof *export + 1 + lenapi + (path == apiname || !path ? 0 : 1 + strlen(path)));
1402 export->refcount = 1;
1403 strcpy(export->name, apiname);
1404 export->api.apiname = export->name;
1405 if (path == apiname)
1406 export->path = export->name;
1408 export->path = strcpy(&export->name[lenapi + 1], path);
1409 export->version = version;
1410 export->state = Api_State_Pre_Init;
1411 export->session = afb_session_addref(common_session);
1412 export->declare_set = afb_apiset_addref(declare_set);
1413 export->call_set = afb_apiset_addref(call_set);
1418 struct afb_export *afb_export_addref(struct afb_export *export)
1421 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1425 void afb_export_unref(struct afb_export *export)
1427 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1428 afb_export_destroy(export);
1431 void afb_export_destroy(struct afb_export *export)
1434 if (export->event_handlers)
1435 globset_destroy(export->event_handlers);
1436 if (export->listener != NULL)
1437 afb_evt_listener_unref(export->listener);
1438 afb_session_unref(export->session);
1439 afb_apiset_unref(export->declare_set);
1440 afb_apiset_unref(export->call_set);
1441 json_object_put(export->settings);
1442 afb_export_unref(export->creator);
1443 if (export->api.apiname != export->name)
1444 free((void*)export->api.apiname);
1449 struct afb_export *afb_export_create_none_for_path(
1450 struct afb_apiset *declare_set,
1451 struct afb_apiset *call_set,
1453 int (*creator)(void*, struct afb_api_x3*),
1456 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1458 afb_export_logmask_set(export, logmask);
1459 set_interfaces(export);
1460 if (creator && creator(closure, to_api_x3(export)) < 0) {
1461 afb_export_unref(export);
1468 #if WITH_LEGACY_BINDING_V1
1469 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1470 struct afb_apiset *call_set,
1471 const char *apiname,
1472 int (*init)(struct afb_service_x1),
1473 void (*onevent)(const char*, struct json_object*),
1476 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1478 export->init.v1 = init;
1479 export->on_any_event_v12 = onevent;
1480 export->export.v1.mode = AFB_MODE_LOCAL;
1481 export->export.v1.daemon.closure = to_api_x3(export);
1482 afb_export_logmask_set(export, logmask);
1483 set_interfaces(export);
1489 #if WITH_LEGACY_BINDING_V2
1490 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1491 struct afb_apiset *call_set,
1492 const char *apiname,
1493 const struct afb_binding_v2 *binding,
1494 struct afb_binding_data_v2 *data,
1496 void (*onevent)(const char*, struct json_object*),
1499 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1501 export->init.v2 = init;
1502 export->on_any_event_v12 = onevent;
1503 export->desc.v2 = binding;
1504 export->export.v2 = data;
1505 data->daemon.closure = to_api_x3(export);
1506 data->service.closure = to_api_x3(export);
1507 afb_export_logmask_set(export, logmask);
1508 set_interfaces(export);
1514 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1515 struct afb_apiset *call_set,
1516 const char *apiname,
1517 struct afb_api_v3 *apiv3,
1518 struct afb_export* creator,
1521 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1523 export->unsealed = 1;
1524 export->desc.v3 = apiv3;
1525 export->creator = afb_export_addref(creator);
1526 afb_export_logmask_set(export, logmask);
1527 set_interfaces(export);
1532 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1534 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1537 int afb_export_rename(struct afb_export *export, const char *apiname)
1541 if (export->declared) {
1546 /* copy the name locally */
1547 name = strdup(apiname);
1553 if (export->api.apiname != export->name)
1554 free((void*)export->api.apiname);
1555 export->api.apiname = name;
1557 set_interfaces(export);
1561 const char *afb_export_apiname(const struct afb_export *export)
1563 return export->api.apiname;
1566 int afb_export_unshare_session(struct afb_export *export)
1568 if (export->session == common_session) {
1569 export->session = afb_session_create (0);
1570 if (export->session)
1571 afb_session_unref(common_session);
1573 export->session = common_session;
1580 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1581 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1584 switch (export->version) {
1585 #if WITH_LEGACY_BINDING_V1
1588 #if WITH_LEGACY_BINDING_V2
1593 ERROR("invalid version 12 for API %s", export->api.apiname);
1598 export->on_any_event_v12 = on_event;
1599 return ensure_listener(export);
1603 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))
1606 switch (export->version) {
1607 case Api_Version_3: break;
1609 ERROR("invalid version Dyn for API %s", export->api.apiname);
1614 export->on_any_event_v3 = on_event;
1615 return ensure_listener(export);
1618 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1620 if (export->state != Api_State_Pre_Init) {
1621 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1626 export->init.v3 = oninit;
1630 #if WITH_LEGACY_BINDING_V1
1632 * Starts a new service (v1)
1634 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1636 return export->desc.v1 = regfun(&export->export.v1);
1640 int afb_export_preinit_x3(
1641 struct afb_export *export,
1642 int (*preinit)(void*, struct afb_api_x3*),
1645 return preinit(closure, to_api_x3(export));
1648 int afb_export_logmask_get(const struct afb_export *export)
1650 return export->api.logmask;
1653 void afb_export_logmask_set(struct afb_export *export, int mask)
1655 export->api.logmask = mask;
1656 switch (export->version) {
1657 #if WITH_LEGACY_BINDING_V1
1658 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1660 #if WITH_LEGACY_BINDING_V2
1661 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1666 void *afb_export_userdata_get(const struct afb_export *export)
1668 return export->api.userdata;
1671 void afb_export_userdata_set(struct afb_export *export, void *data)
1673 export->api.userdata = data;
1676 /******************************************************************************
1677 ******************************************************************************
1678 ******************************************************************************
1679 ******************************************************************************
1681 ******************************************************************************
1682 ******************************************************************************
1683 ******************************************************************************
1684 ******************************************************************************/
1689 struct afb_export *export;
1692 static void do_init(int sig, void *closure)
1695 struct init *init = closure;
1696 struct afb_export *export;
1701 export = init->export;
1702 switch (export->version) {
1703 #if WITH_LEGACY_BINDING_V1
1705 rc = export->init.v1 ? export->init.v1(
1706 (struct afb_service_x1){
1708 .itf = &hooked_service_itf,
1710 .itf = &service_itf,
1712 .closure = to_api_x3(export) }) : 0;
1715 #if WITH_LEGACY_BINDING_V2
1717 rc = export->init.v2 ? export->init.v2() : 0;
1721 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1728 init->return_code = rc;
1732 int afb_export_start(struct afb_export *export)
1738 switch (export->state) {
1742 case Api_State_Init:
1743 /* starting in progress: it is an error */
1744 ERROR("Service of API %s required started while starting", export->api.apiname);
1751 /* set event handling */
1752 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1753 switch (export->version) {
1754 #if WITH_LEGACY_BINDING_V1
1757 #if WITH_LEGACY_BINDING_V2
1760 if (export->on_any_event_v12) {
1761 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1770 ERROR("Can't set event handler for %s", export->api.apiname);
1776 /* Starts the service */
1777 if (export->hooksvc & afb_hook_flag_api_start)
1778 afb_hook_api_start_before(export);
1781 export->state = Api_State_Init;
1782 init.export = export;
1783 sig_monitor(0, do_init, &init);
1784 rc = init.return_code;
1785 export->state = Api_State_Run;
1788 if (export->hooksvc & afb_hook_flag_api_start)
1789 afb_hook_api_start_after(export, rc);
1793 /* initialisation error */
1794 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1801 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1803 struct afb_export *export = closure;
1805 xreq->request.api = to_api_x3(export);
1807 switch (export->version) {
1808 #if WITH_LEGACY_BINDING_V1
1810 afb_api_so_v1_process_call(export->desc.v1, xreq);
1813 #if WITH_LEGACY_BINDING_V2
1815 afb_api_so_v2_process_call(export->desc.v2, xreq);
1819 afb_api_v3_process_call(export->desc.v3, xreq);
1822 afb_xreq_reply(xreq, NULL, afb_error_text_internal_error, NULL);
1827 static void api_describe_cb(void *closure, void (*describecb)(void *, struct json_object *), void *clocb)
1829 struct afb_export *export = closure;
1830 struct json_object *result;
1832 switch (export->version) {
1833 #if WITH_LEGACY_BINDING_V1
1835 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1838 #if WITH_LEGACY_BINDING_V2
1840 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1844 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1850 describecb(clocb, result);
1853 static int api_service_start_cb(void *closure)
1855 struct afb_export *export = closure;
1857 return afb_export_start(export);
1861 static void api_update_hooks_cb(void *closure)
1862 __attribute__((alias("set_interfaces")));
1864 void afb_export_update_hooks(struct afb_export *export)
1865 __attribute__((alias("set_interfaces")));
1868 static int api_get_logmask_cb(void *closure)
1870 struct afb_export *export = closure;
1872 return afb_export_logmask_get(export);
1875 static void api_set_logmask_cb(void *closure, int level)
1877 struct afb_export *export = closure;
1879 afb_export_logmask_set(export, level);
1882 static void api_unref_cb(void *closure)
1884 struct afb_export *export = closure;
1886 afb_export_unref(export);
1889 static struct afb_api_itf export_api_itf =
1891 .call = api_call_cb,
1892 .service_start = api_service_start_cb,
1894 .update_hooks = api_update_hooks_cb,
1896 .get_logmask = api_get_logmask_cb,
1897 .set_logmask = api_set_logmask_cb,
1898 .describe = api_describe_cb,
1899 .unref = api_unref_cb
1902 int afb_export_declare(struct afb_export *export,
1906 struct afb_api_item afb_api;
1908 if (export->declared)
1911 /* init the record structure */
1912 afb_api.closure = afb_export_addref(export);
1913 afb_api.itf = &export_api_itf;
1914 afb_api.group = noconcurrency ? export : NULL;
1916 /* records the binding */
1917 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1919 export->declared = 1;
1921 ERROR("can't declare export %s to set %s, ABORTING it!",
1922 export->api.apiname,
1923 afb_apiset_name(export->declare_set));
1924 afb_export_unref(export);
1931 void afb_export_undeclare(struct afb_export *export)
1933 if (export->declared) {
1934 export->declared = 0;
1935 afb_apiset_del(export->declare_set, export->api.apiname);
1939 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1941 return afb_evt_event_x2_add_watch(export->listener, event);
1944 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1946 return afb_evt_event_x2_remove_watch(export->listener, event);
1949 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1951 afb_xreq_process(xreq, export->call_set);
1954 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1956 afb_context_init_validated(context, export->session);