Update copyright dates
[src/app-framework-binder.git] / src / afb-export.c
index e9d5d9a..800ee77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
+ * Copyright (C) 2015-2020 "IoT.bzh"
  * Author: José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
 
 #include "afb-api.h"
 #include "afb-apiset.h"
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
 #include "afb-api-so-v1.h"
 #endif
+#if WITH_LEGACY_BINDING_V2
 #include "afb-api-so-v2.h"
+#endif
 #include "afb-api-v3.h"
 #include "afb-common.h"
-#include "afb-systemd.h"
-#include "afb-cred.h"
 #include "afb-evt.h"
 #include "afb-export.h"
 #include "afb-hook.h"
 #include "afb-session.h"
 #include "afb-xreq.h"
 #include "afb-calls.h"
+#include "afb-error-text.h"
+
+#include "systemd.h"
 #include "jobs.h"
 #include "verbose.h"
+#include "globset.h"
 #include "sig-monitor.h"
+#include "wrap-json.h"
 
 /*************************************************************************
  * internal types
  ************************************************************************/
 
-/*
- * structure for handling events
- */
-struct event_handler
-{
-       /* link to the next event handler of the list */
-       struct event_handler *next;
-
-       /* function to call on the case of the event */
-       void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
-
-       /* closure for the callback */
-       void *closure;
-
-       /* the handled pattern */
-       char pattern[1];
-};
-
 /*
  * Actually supported versions
  */
 enum afb_api_version
 {
        Api_Version_None = 0,
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        Api_Version_1 = 1,
 #endif
+#if WITH_LEGACY_BINDING_V2
        Api_Version_2 = 2,
+#endif
        Api_Version_3 = 3
 };
 
@@ -120,9 +109,11 @@ struct afb_export
        /* unsealed */
        unsigned unsealed: 1;
 
+#if WITH_AFB_HOOK
        /* hooking flags */
        int hookditf;
        int hooksvc;
+#endif
 
        /* session for service */
        struct afb_session *session;
@@ -137,11 +128,20 @@ struct afb_export
        struct afb_evt_listener *listener;
 
        /* event handler list */
-       struct event_handler *event_handlers;
+       struct globset *event_handlers;
+
+       /* creator if any */
+       struct afb_export *creator;
+
+       /* path indication if any */
+       const char *path;
+
+       /* settings */
+       struct json_object *settings;
 
        /* internal descriptors */
        union {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
                struct afb_binding_v1 *v1;
 #endif
                const struct afb_binding_v2 *v2;
@@ -150,7 +150,7 @@ struct afb_export
 
        /* start function */
        union {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
                int (*v1)(struct afb_service_x1);
 #endif
                int (*v2)();
@@ -163,14 +163,14 @@ struct afb_export
 
        /* exported data */
        union {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
                struct afb_binding_interface_v1 v1;
 #endif
                struct afb_binding_data_v2 *v2;
        } export;
 
        /* initial name */
-       char name[1];
+       char name[];
 };
 
 /*****************************************************************************/
@@ -195,6 +195,54 @@ struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
        return to_api_x3(export);
 }
 
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+       SETTINGS
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
+
+static struct json_object *configuration;
+
+void afb_export_set_config(struct json_object *config)
+{
+       struct json_object *save = configuration;
+       configuration = json_object_get(config);
+       json_object_put(save);
+}
+
+static struct json_object *make_settings(struct afb_export *export)
+{
+       struct json_object *result;
+       struct json_object *obj;
+       struct afb_export *iter;
+       char *path;
+
+       /* clone the globals */
+       if (json_object_object_get_ex(configuration, "*", &obj))
+               result = wrap_json_clone(obj);
+       else
+               result = json_object_new_object();
+
+       /* add locals */
+       if (json_object_object_get_ex(configuration, export->name, &obj))
+               wrap_json_object_add(result, obj);
+
+       /* add library path */
+       for (iter = export ; iter && !iter->path ; iter = iter->creator);
+       if (iter) {
+               path = realpath(iter->path, NULL);
+               json_object_object_add(result, "binding-path", json_object_new_string(path));
+               free(path);
+       }
+
+       export->settings = result;
+       return result;
+}
+
 /******************************************************************************
  ******************************************************************************
  ******************************************************************************
@@ -216,16 +264,11 @@ static void vverbose_cb(struct afb_api_x3 *closure, int level, const char *file,
        if (!fmt || vasprintf(&p, fmt, args) < 0)
                vverbose(level, file, line, function, fmt, args);
        else {
-               verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
+               verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
                free(p);
        }
 }
 
-static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
-{
-       vverbose_cb(closure, level, file, line, NULL, fmt, args);
-}
-
 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
 {
        struct afb_export *export = from_api_x3(closure);
@@ -241,12 +284,6 @@ static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const c
        return afb_evt_event_x2_create2(export->api.apiname, name);
 }
 
-static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
-{
-       struct afb_event_x2 *event = event_x2_make_cb(closure, name);
-       return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
-}
-
 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
 {
        size_t plen, nlen;
@@ -273,6 +310,24 @@ static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, stru
        return afb_evt_broadcast(event, object);
 }
 
+static struct sd_event *get_event_loop(struct afb_api_x3 *closure)
+{
+       jobs_acquire_event_manager();
+       return systemd_get_event_loop();
+}
+
+static struct sd_bus *get_user_bus(struct afb_api_x3 *closure)
+{
+       jobs_acquire_event_manager();
+       return systemd_get_user_bus();
+}
+
+static struct sd_bus *get_system_bus(struct afb_api_x3 *closure)
+{
+       jobs_acquire_event_manager();
+       return systemd_get_system_bus();
+}
+
 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
 {
        return afb_common_rootdir_open_locale(filename, flags, locale);
@@ -283,17 +338,19 @@ static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum,
        return jobs_queue(group, timeout, callback, argument);
 }
 
-static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
-{
-       return afb_xreq_unstore(sreq);
-}
-
 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
 {
        struct afb_export *export = from_api_x3(closure);
        int rc, rc2;
        char *iter, *end, save;
 
+       /* emit a warning about unexpected require in preinit */
+       if (export->state == Api_State_Pre_Init && initialized) {
+               ERROR("[API %s] requiring initialized apis in pre-init is forbiden", export->api.apiname);
+               errno = EINVAL;
+               return -1;
+       }
+
        /* scan the names in a local copy */
        rc = 0;
        iter = strdupa(name);
@@ -312,10 +369,20 @@ static int require_api_cb(struct afb_api_x3 *closure, const char *name, int init
                *end = 0;
 
                /* check the required api */
-               if (export->state == Api_State_Pre_Init)
-                       rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
-               else
+               if (export->state == Api_State_Pre_Init) {
+                       rc2 = afb_apiset_require(export->declare_set, export->api.apiname, iter);
+                       if (rc2 < 0) {
+                               if (rc == 0)
+                                       WARNING("[API %s] requiring apis pre-init may lead to unexpected result", export->api.apiname);
+                               ERROR("[API %s] requiring api %s in pre-init failed", export->api.apiname, iter);
+                       }
+               } else {
                        rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
+                       if (rc2 < 0) {
+                               ERROR("[API %s] requiring api %s%s failed", export->api.apiname,
+                                        iter, initialized ? " initialized" : "");
+                       }
+               }
                if (rc2 < 0)
                        rc = rc2;
 
@@ -346,13 +413,51 @@ static struct afb_api_x3 *api_new_api_cb(
                void *preinit_closure)
 {
        struct afb_export *export = from_api_x3(closure);
-       struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
+       struct afb_api_v3 *apiv3 = afb_api_v3_create(
+                                       export->declare_set, export->call_set,
+                                       api, info, noconcurrency,
+                                       preinit, preinit_closure, 1,
+                                       export, NULL);
        return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
 }
 
-/**********************************************
-* hooked flow
-**********************************************/
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
+
+static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
+{
+       vverbose_cb(closure, level, file, line, NULL, fmt, args);
+}
+
+static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
+{
+       struct afb_event_x2 *event = event_x2_make_cb(closure, name);
+       return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
+}
+
+static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
+{
+       return afb_xreq_unstore(sreq);
+}
+
+static const struct afb_daemon_itf_x1 daemon_itf = {
+       .vverbose_v1 = legacy_vverbose_v1_cb,
+       .vverbose_v2 = vverbose_cb,
+       .event_make = legacy_event_x1_make_cb,
+       .event_broadcast = event_broadcast_cb,
+       .get_event_loop = get_event_loop,
+       .get_user_bus = get_user_bus,
+       .get_system_bus = get_system_bus,
+       .rootdir_get_fd = afb_common_rootdir_get_fd,
+       .rootdir_open_locale = rootdir_open_locale_cb,
+       .queue_job = queue_job_cb,
+       .unstore_req = legacy_unstore_req_cb,
+       .require_api = require_api_cb,
+       .add_alias = add_alias_cb,
+       .new_api = api_new_api_cb,
+};
+#endif
+
+#if WITH_AFB_HOOK
 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)
 {
        struct afb_export *export = from_api_x3(closure);
@@ -363,11 +468,6 @@ static void hooked_vverbose_cb(struct afb_api_x3 *closure, int level, const char
        va_end(ap);
 }
 
-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)
-{
-       hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
-}
-
 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
 {
        struct afb_export *export = from_api_x3(closure);
@@ -376,15 +476,6 @@ static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure,
        return r;
 }
 
-static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
-{
-       struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
-       struct afb_event_x1 e;
-       e.closure = event;
-       e.itf = event ? event->itf : NULL;
-       return e;
-}
-
 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
 {
        int r;
@@ -400,21 +491,30 @@ static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *nam
 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
 {
        struct afb_export *export = from_api_x3(closure);
-       struct sd_event *r = afb_systemd_get_event_loop();
+       struct sd_event *r;
+
+       jobs_acquire_event_manager();
+       r = get_event_loop(closure);
        return afb_hook_api_get_event_loop(export, r);
 }
 
 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
 {
        struct afb_export *export = from_api_x3(closure);
-       struct sd_bus *r = afb_systemd_get_user_bus();
+       struct sd_bus *r;
+
+       jobs_acquire_event_manager();
+       r = get_user_bus(closure);
        return afb_hook_api_get_user_bus(export, r);
 }
 
 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
 {
        struct afb_export *export = from_api_x3(closure);
-       struct sd_bus *r = afb_systemd_get_system_bus();
+       struct sd_bus *r;
+
+       jobs_acquire_event_manager();
+       r = get_system_bus(closure);
        return afb_hook_api_get_system_bus(export, r);
 }
 
@@ -439,13 +539,6 @@ static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int
        return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
 }
 
-static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
-{
-       struct afb_export *export = from_api_x3(closure);
-       afb_hook_api_legacy_unstore_req(export, sreq);
-       return legacy_unstore_req_cb(closure, sreq);
-}
-
 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
 {
        int result;
@@ -478,25 +571,28 @@ static struct afb_api_x3 *hooked_api_new_api_cb(
        return result;
 }
 
-/**********************************************
-* vectors
-**********************************************/
-static const struct afb_daemon_itf_x1 daemon_itf = {
-       .vverbose_v1 = legacy_vverbose_v1_cb,
-       .vverbose_v2 = vverbose_cb,
-       .event_make = legacy_event_x1_make_cb,
-       .event_broadcast = event_broadcast_cb,
-       .get_event_loop = afb_systemd_get_event_loop,
-       .get_user_bus = afb_systemd_get_user_bus,
-       .get_system_bus = afb_systemd_get_system_bus,
-       .rootdir_get_fd = afb_common_rootdir_get_fd,
-       .rootdir_open_locale = rootdir_open_locale_cb,
-       .queue_job = queue_job_cb,
-       .unstore_req = legacy_unstore_req_cb,
-       .require_api = require_api_cb,
-       .add_alias = add_alias_cb,
-       .new_api = api_new_api_cb,
-};
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
+
+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)
+{
+       hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
+}
+
+static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
+{
+       struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
+       struct afb_event_x1 e;
+       e.closure = event;
+       e.itf = event ? event->itf : NULL;
+       return e;
+}
+
+static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
+{
+       struct afb_export *export = from_api_x3(closure);
+       afb_hook_api_legacy_unstore_req(export, sreq);
+       return legacy_unstore_req_cb(closure, sreq);
+}
 
 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
        .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
@@ -514,6 +610,9 @@ static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
        .add_alias = hooked_add_alias_cb,
        .new_api = hooked_api_new_api_cb,
 };
+#endif
+
+#endif
 
 /******************************************************************************
  ******************************************************************************
@@ -563,41 +662,51 @@ static int call_sync_x3(
        return afb_calls_call_sync(export, api, verb, args, object, error, info);
 }
 
-static void legacy_call_v12(
+static void legacy_call_x3(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               void (*callback)(void*, int, struct json_object*),
+               void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
                void *closure)
 {
        struct afb_export *export = from_api_x3(apix3);
-       afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
+       afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
 }
 
-static void legacy_call_x3(
+static int legacy_call_sync(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
-               void *closure)
+               struct json_object **result)
 {
        struct afb_export *export = from_api_x3(apix3);
-       afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
+       return afb_calls_legacy_call_sync(export, api, verb, args, result);
 }
 
-static int legacy_call_sync(
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
+
+static void legacy_call_v12(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               struct json_object **result)
+               void (*callback)(void*, int, struct json_object*),
+               void *closure)
 {
        struct afb_export *export = from_api_x3(apix3);
-       return afb_calls_legacy_call_sync(export, api, verb, args, result);
+       afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
 }
 
+/* the interface for services */
+static const struct afb_service_itf_x1 service_itf = {
+       .call = legacy_call_v12,
+       .call_sync = legacy_call_sync
+};
+#endif
+
+#if WITH_AFB_HOOK
 static void hooked_call_x3(
                struct afb_api_x3 *apix3,
                const char *api,
@@ -623,52 +732,51 @@ static int hooked_call_sync_x3(
        return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
 }
 
-static void legacy_hooked_call_v12(
+static void legacy_hooked_call_x3(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               void (*callback)(void*, int, struct json_object*),
+               void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
                void *closure)
 {
        struct afb_export *export = from_api_x3(apix3);
-       afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
+       afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
 }
 
-static void legacy_hooked_call_x3(
+static int legacy_hooked_call_sync(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
-               void *closure)
+               struct json_object **result)
 {
        struct afb_export *export = from_api_x3(apix3);
-       afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
+       return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
 }
 
-static int legacy_hooked_call_sync(
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
+
+static void legacy_hooked_call_v12(
                struct afb_api_x3 *apix3,
                const char *api,
                const char *verb,
                struct json_object *args,
-               struct json_object **result)
+               void (*callback)(void*, int, struct json_object*),
+               void *closure)
 {
        struct afb_export *export = from_api_x3(apix3);
-       return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
+       afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
 }
 
-/* the interface for services */
-static const struct afb_service_itf_x1 service_itf = {
-       .call = legacy_call_v12,
-       .call_sync = legacy_call_sync
-};
-
 /* the interface for services */
 static const struct afb_service_itf_x1 hooked_service_itf = {
        .call = legacy_hooked_call_v12,
        .call_sync = legacy_hooked_call_sync
 };
+#endif
+
+#endif
 
 /******************************************************************************
  ******************************************************************************
@@ -684,6 +792,7 @@ static int api_set_verbs_v2_cb(
                struct afb_api_x3 *api,
                const struct afb_verb_v2 *verbs)
 {
+#if WITH_LEGACY_BINDING_V2
        struct afb_export *export = from_api_x3(api);
 
        if (export->unsealed) {
@@ -692,6 +801,9 @@ static int api_set_verbs_v2_cb(
        }
 
        errno = EPERM;
+#else
+       errno = ECANCELED;
+#endif
        return -1;
 }
 
@@ -867,6 +979,57 @@ static int delete_api_cb(struct afb_api_x3 *api)
        return 0;
 }
 
+static struct json_object *settings_cb(struct afb_api_x3 *api)
+{
+       struct afb_export *export = from_api_x3(api);
+       struct json_object *result = export->settings;
+       if (!result)
+               result = make_settings(export);
+       return result;
+}
+
+static const struct afb_api_x3_itf api_x3_itf = {
+
+       .vverbose = (void*)vverbose_cb,
+
+       .get_event_loop = get_event_loop,
+       .get_user_bus = get_user_bus,
+       .get_system_bus = get_system_bus,
+       .rootdir_get_fd = afb_common_rootdir_get_fd,
+       .rootdir_open_locale = rootdir_open_locale_cb,
+       .queue_job = queue_job_cb,
+
+       .require_api = require_api_cb,
+       .add_alias = add_alias_cb,
+
+       .event_broadcast = event_broadcast_cb,
+       .event_make = event_x2_make_cb,
+
+       .legacy_call = legacy_call_x3,
+       .legacy_call_sync = legacy_call_sync,
+
+       .api_new_api = api_new_api_cb,
+       .api_set_verbs_v2 = api_set_verbs_v2_cb,
+       .api_add_verb = api_add_verb_cb,
+       .api_del_verb = api_del_verb_cb,
+       .api_set_on_event = api_set_on_event_cb,
+       .api_set_on_init = api_set_on_init_cb,
+       .api_seal = api_seal_cb,
+       .api_set_verbs_v3 = api_set_verbs_v3_cb,
+       .event_handler_add = event_handler_add_cb,
+       .event_handler_del = event_handler_del_cb,
+
+       .call = call_x3,
+       .call_sync = call_sync_x3,
+
+       .class_provide = class_provide_cb,
+       .class_require = class_require_cb,
+
+       .delete_api = delete_api_cb,
+       .settings = settings_cb,
+};
+
+#if WITH_AFB_HOOK
 static int hooked_api_set_verbs_v2_cb(
                struct afb_api_x3 *api,
                const struct afb_verb_v2 *verbs)
@@ -980,45 +1143,13 @@ static int hooked_delete_api_cb(struct afb_api_x3 *api)
        return result;
 }
 
-static const struct afb_api_x3_itf api_x3_itf = {
-
-       .vverbose = (void*)vverbose_cb,
-
-       .get_event_loop = afb_systemd_get_event_loop,
-       .get_user_bus = afb_systemd_get_user_bus,
-       .get_system_bus = afb_systemd_get_system_bus,
-       .rootdir_get_fd = afb_common_rootdir_get_fd,
-       .rootdir_open_locale = rootdir_open_locale_cb,
-       .queue_job = queue_job_cb,
-
-       .require_api = require_api_cb,
-       .add_alias = add_alias_cb,
-
-       .event_broadcast = event_broadcast_cb,
-       .event_make = event_x2_make_cb,
-
-       .legacy_call = legacy_call_x3,
-       .legacy_call_sync = legacy_call_sync,
-
-       .api_new_api = api_new_api_cb,
-       .api_set_verbs_v2 = api_set_verbs_v2_cb,
-       .api_add_verb = api_add_verb_cb,
-       .api_del_verb = api_del_verb_cb,
-       .api_set_on_event = api_set_on_event_cb,
-       .api_set_on_init = api_set_on_init_cb,
-       .api_seal = api_seal_cb,
-       .api_set_verbs_v3 = api_set_verbs_v3_cb,
-       .event_handler_add = event_handler_add_cb,
-       .event_handler_del = event_handler_del_cb,
-
-       .call = call_x3,
-       .call_sync = call_sync_x3,
-
-       .class_provide = class_provide_cb,
-       .class_require = class_require_cb,
-
-       .delete_api = delete_api_cb,
-};
+static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
+{
+       struct afb_export *export = from_api_x3(api);
+       struct json_object *result = settings_cb(api);
+       result = afb_hook_api_settings(export, result);
+       return result;
+}
 
 static const struct afb_api_x3_itf hooked_api_x3_itf = {
 
@@ -1058,7 +1189,9 @@ static const struct afb_api_x3_itf hooked_api_x3_itf = {
        .class_require = hooked_class_require_cb,
 
        .delete_api = hooked_delete_api_cb,
+       .settings = hooked_settings_cb,
 };
+#endif
 
 /******************************************************************************
  ******************************************************************************
@@ -1073,47 +1206,64 @@ static const struct afb_api_x3_itf hooked_api_x3_itf = {
 /*
  * Propagates the event to the service
  */
-static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
+static void listener_of_events(void *closure, const char *event, uint16_t eventid, struct json_object *object)
 {
-       struct event_handler *handler;
+       const struct globset_handler *handler;
+       void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
        struct afb_export *export = from_api_x3(closure);
 
+#if WITH_AFB_HOOK
        /* hook the event before */
        if (export->hooksvc & afb_hook_flag_api_on_event)
                afb_hook_api_on_event_before(export, event, eventid, object);
+#endif
 
        /* transmit to specific handlers */
        /* search the handler */
-       handler = export->event_handlers;
-       while (handler) {
-               if (fnmatch(handler->pattern, event, 0)) {
-                       if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
-                               handler->callback(handler->closure, event, object, to_api_x3(export));
-                       else {
-                               afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
-                               handler->callback(handler->closure, event, object, to_api_x3(export));
-                               afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
-                       }
+       handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
+       if (handler) {
+               callback = handler->callback;
+#if WITH_AFB_HOOK
+               if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
+#endif
+                       callback(handler->closure, event, object, to_api_x3(export));
+#if WITH_AFB_HOOK
+               else {
+                       afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
+                       callback(handler->closure, event, object, to_api_x3(export));
+                       afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
                }
-               handler = handler->next;
+#endif
+       } else {
+               /* transmit to default handler */
+               if (export->on_any_event_v3)
+                       export->on_any_event_v3(to_api_x3(export), event, object);
+               else if (export->on_any_event_v12)
+                       export->on_any_event_v12(event, object);
        }
 
-       /* transmit to default handler */
-       if (export->on_any_event_v3)
-               export->on_any_event_v3(to_api_x3(export), event, object);
-       else if (export->on_any_event_v12)
-               export->on_any_event_v12(event, object);
-
+#if WITH_AFB_HOOK
        /* hook the event after */
        if (export->hooksvc & afb_hook_flag_api_on_event)
                afb_hook_api_on_event_after(export, event, eventid, object);
+#endif
        json_object_put(object);
 }
 
+static void listener_of_pushed_events(void *closure, const char *event, uint16_t eventid, struct json_object *object)
+{
+       listener_of_events(closure, event, eventid, object);
+}
+
+static void listener_of_broadcasted_events(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop)
+{
+       listener_of_events(closure, event, 0, object);
+}
+
 /* the interface for events */
 static const struct afb_evt_itf evt_itf = {
-       .broadcast = listener_of_events,
-       .push = listener_of_events
+       .broadcast = listener_of_broadcasted_events,
+       .push = listener_of_pushed_events
 };
 
 /* ensure an existing listener */
@@ -1134,40 +1284,32 @@ int afb_export_event_handler_add(
                        void *closure)
 {
        int rc;
-       struct event_handler *handler, **previous;
 
+       /* ensure the listener */
        rc = ensure_listener(export);
        if (rc < 0)
                return rc;
 
-       /* search the handler */
-       previous = &export->event_handlers;
-       while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
-               previous = &handler->next;
-
-       /* error if found */
-       if (handler) {
-               ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
-               errno = EEXIST;
-               return -1;
+       /* ensure the globset for event handling */
+       if (!export->event_handlers) {
+               export->event_handlers = globset_create();
+               if (!export->event_handlers)
+                       goto oom_error;
        }
 
-       /* create the event */
-       handler = malloc(strlen(pattern) + sizeof * handler);
-       if (!handler) {
-               ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
-               errno = ENOMEM;
+       /* add the handler */
+       rc = globset_add(export->event_handlers, pattern, callback, closure);
+       if (rc == 0)
+               return 0;
+
+       if (errno == EEXIST) {
+               ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
                return -1;
        }
 
-       /* init and record */
-       handler->next = NULL;
-       handler->callback = callback;
-       handler->closure = closure;
-       strcpy(handler->pattern, pattern);
-       *previous = handler;
-
-       return 0;
+oom_error:
+       ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
+       return -1;
 }
 
 int afb_export_event_handler_del(
@@ -1175,27 +1317,13 @@ int afb_export_event_handler_del(
                        const char *pattern,
                        void **closure)
 {
-       struct event_handler *handler, **previous;
-
-       /* search the handler */
-       previous = &export->event_handlers;
-       while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
-               previous = &handler->next;
-
-       /* error if found */
-       if (!handler) {
-               ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
-               errno = ENOENT;
-               return -1;
-       }
-
-       /* remove the found event */
-       if (closure)
-               *closure = handler->closure;
+       if (export->event_handlers
+       && !globset_del(export->event_handlers, pattern, closure))
+               return 0;
 
-       *previous = handler->next;
-       free(handler);
-       return 0;
+       ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
+       errno = ENOENT;
+       return -1;
 }
 
 /******************************************************************************
@@ -1208,13 +1336,56 @@ int afb_export_event_handler_del(
  ******************************************************************************
  ******************************************************************************/
 
+static void set_interfaces(struct afb_export *export)
+{
+#if WITH_AFB_HOOK
+       export->hookditf = afb_hook_flags_api(export->api.apiname);
+       export->hooksvc = afb_hook_flags_api(export->api.apiname);
+       export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
+
+       switch (export->version) {
+#if WITH_LEGACY_BINDING_V1
+       case Api_Version_1:
+               export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
+               break;
+#endif
+#if WITH_LEGACY_BINDING_V2
+       case Api_Version_2:
+               export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
+               export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
+               break;
+#endif
+       }
+#else
+
+       export->api.itf = &api_x3_itf;
+
+       switch (export->version) {
+#if WITH_LEGACY_BINDING_V1
+       case Api_Version_1:
+               export->export.v1.daemon.itf = &daemon_itf;
+               break;
+#endif
+#if WITH_LEGACY_BINDING_V2
+       case Api_Version_2:
+               export->export.v2->daemon.itf = &daemon_itf;
+               export->export.v2->service.itf = &service_itf;
+               break;
+#endif
+       }
+
+#endif
+}
+
 static struct afb_export *create(
                                struct afb_apiset *declare_set,
                                struct afb_apiset *call_set,
                                const char *apiname,
+                               const char *path,
                                enum afb_api_version version)
 {
        struct afb_export *export;
+       size_t lenapi;
 
        /* session shared with other exports */
        if (common_session == NULL) {
@@ -1222,13 +1393,18 @@ static struct afb_export *create(
                if (common_session == NULL)
                        return NULL;
        }
-       export = calloc(1, sizeof *export + strlen(apiname));
+       lenapi = strlen(apiname);
+       export = calloc(1, sizeof *export + 1 + lenapi + (path == apiname || !path ? 0 : 1 + strlen(path)));
        if (!export)
                errno = ENOMEM;
        else {
                export->refcount = 1;
                strcpy(export->name, apiname);
                export->api.apiname = export->name;
+               if (path == apiname)
+                       export->path = export->name;
+               else if (path)
+                       export->path = strcpy(&export->name[lenapi + 1], path);
                export->version = version;
                export->state = Api_State_Pre_Init;
                export->session = afb_session_addref(common_session);
@@ -1253,18 +1429,16 @@ void afb_export_unref(struct afb_export *export)
 
 void afb_export_destroy(struct afb_export *export)
 {
-       struct event_handler *handler;
-
        if (export) {
-               while ((handler = export->event_handlers)) {
-                       export->event_handlers = handler->next;
-                       free(handler);
-               }
+               if (export->event_handlers)
+                       globset_destroy(export->event_handlers);
                if (export->listener != NULL)
                        afb_evt_listener_unref(export->listener);
                afb_session_unref(export->session);
                afb_apiset_unref(export->declare_set);
                afb_apiset_unref(export->call_set);
+               json_object_put(export->settings);
+               afb_export_unref(export->creator);
                if (export->api.apiname != export->name)
                        free((void*)export->api.apiname);
                free(export);
@@ -1278,10 +1452,10 @@ struct afb_export *afb_export_create_none_for_path(
                        int (*creator)(void*, struct afb_api_x3*),
                        void *closure)
 {
-       struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
+       struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
        if (export) {
                afb_export_logmask_set(export, logmask);
-               afb_export_update_hooks(export);
+               set_interfaces(export);
                if (creator && creator(closure, to_api_x3(export)) < 0) {
                        afb_export_unref(export);
                        export = NULL;
@@ -1290,37 +1464,38 @@ struct afb_export *afb_export_create_none_for_path(
        return export;
 }
 
-#if defined(WITH_LEGACY_BINDING_V1)
-struct afb_export *afb_export_create_v1(
-                       struct afb_apiset *declare_set,
+#if WITH_LEGACY_BINDING_V1
+struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
                        int (*init)(struct afb_service_x1),
-                       void (*onevent)(const char*, struct json_object*))
+                       void (*onevent)(const char*, struct json_object*),
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
        if (export) {
                export->init.v1 = init;
                export->on_any_event_v12 = onevent;
                export->export.v1.mode = AFB_MODE_LOCAL;
                export->export.v1.daemon.closure = to_api_x3(export);
                afb_export_logmask_set(export, logmask);
-               afb_export_update_hooks(export);
+               set_interfaces(export);
        }
        return export;
 }
 #endif
 
-struct afb_export *afb_export_create_v2(
-                       struct afb_apiset *declare_set,
+#if WITH_LEGACY_BINDING_V2
+struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
                        const struct afb_binding_v2 *binding,
                        struct afb_binding_data_v2 *data,
                        int (*init)(),
-                       void (*onevent)(const char*, struct json_object*))
+                       void (*onevent)(const char*, struct json_object*),
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
        if (export) {
                export->init.v2 = init;
                export->on_any_event_v12 = onevent;
@@ -1329,22 +1504,26 @@ struct afb_export *afb_export_create_v2(
                data->daemon.closure = to_api_x3(export);
                data->service.closure = to_api_x3(export);
                afb_export_logmask_set(export, logmask);
-               afb_export_update_hooks(export);
+               set_interfaces(export);
        }
        return export;
 }
+#endif
 
 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
-                       struct afb_api_v3 *apiv3)
+                       struct afb_api_v3 *apiv3,
+                       struct afb_export* creator,
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
        if (export) {
                export->unsealed = 1;
                export->desc.v3 = apiv3;
+               export->creator = afb_export_addref(creator);
                afb_export_logmask_set(export, logmask);
-               afb_export_update_hooks(export);
+               set_interfaces(export);
        }
        return export;
 }
@@ -1374,7 +1553,7 @@ int afb_export_rename(struct afb_export *export, const char *apiname)
                free((void*)export->api.apiname);
        export->api.apiname = name;
 
-       afb_export_update_hooks(export);
+       set_interfaces(export);
        return 0;
 }
 
@@ -1383,25 +1562,6 @@ const char *afb_export_apiname(const struct afb_export *export)
        return export->api.apiname;
 }
 
-void afb_export_update_hooks(struct afb_export *export)
-{
-       export->hookditf = afb_hook_flags_api(export->api.apiname);
-       export->hooksvc = afb_hook_flags_api(export->api.apiname);
-       export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
-
-       switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
-       case Api_Version_1:
-               export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
-               break;
-#endif
-       case Api_Version_2:
-               export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
-               export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
-               break;
-       }
-}
-
 int afb_export_unshare_session(struct afb_export *export)
 {
        if (export->session == common_session) {
@@ -1416,15 +1576,18 @@ int afb_export_unshare_session(struct afb_export *export)
        return 0;
 }
 
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
 {
        /* check version */
        switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        case Api_Version_1:
 #endif
+#if WITH_LEGACY_BINDING_V2
        case Api_Version_2:
                break;
+#endif
        default:
                ERROR("invalid version 12 for API %s", export->api.apiname);
                errno = EINVAL;
@@ -1434,6 +1597,7 @@ int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(con
        export->on_any_event_v12 = on_event;
        return ensure_listener(export);
 }
+#endif
 
 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))
 {
@@ -1462,7 +1626,7 @@ int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct af
        return 0;
 }
 
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
 /*
  * Starts a new service (v1)
  */
@@ -1489,10 +1653,12 @@ void afb_export_logmask_set(struct afb_export *export, int mask)
 {
        export->api.logmask = mask;
        switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
 #endif
+#if WITH_LEGACY_BINDING_V2
        case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
+#endif
        }
 }
 
@@ -1533,17 +1699,23 @@ static void do_init(int sig, void *closure)
        else {
                export = init->export;
                switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
                case Api_Version_1:
                        rc = export->init.v1 ? export->init.v1(
                                (struct afb_service_x1){
+#if WITH_AFB_HOOK
                                        .itf = &hooked_service_itf,
+#else
+                                       .itf = &service_itf,
+#endif
                                        .closure = to_api_x3(export) }) : 0;
                        break;
 #endif
+#if WITH_LEGACY_BINDING_V2
                case Api_Version_2:
                        rc = export->init.v2 ? export->init.v2() : 0;
                        break;
+#endif
                case Api_Version_3:
                        rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
                        break;
@@ -1576,11 +1748,14 @@ int afb_export_start(struct afb_export *export)
        }
 
        /* set event handling */
+#if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
        switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        case Api_Version_1:
 #endif
+#if WITH_LEGACY_BINDING_V2
        case Api_Version_2:
+#endif
                if (export->on_any_event_v12) {
                        rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
                        break;
@@ -1594,10 +1769,13 @@ int afb_export_start(struct afb_export *export)
                ERROR("Can't set event handler for %s", export->api.apiname);
                return -1;
        }
+#endif
 
+#if WITH_AFB_HOOK
        /* Starts the service */
        if (export->hooksvc & afb_hook_flag_api_start)
                afb_hook_api_start_before(export);
+#endif
 
        export->state = Api_State_Init;
        init.export = export;
@@ -1605,8 +1783,10 @@ int afb_export_start(struct afb_export *export)
        rc = init.return_code;
        export->state = Api_State_Run;
 
+#if WITH_AFB_HOOK
        if (export->hooksvc & afb_hook_flag_api_start)
                afb_hook_api_start_after(export, rc);
+#endif
 
        if (rc < 0) {
                /* initialisation error */
@@ -1624,37 +1804,41 @@ static void api_call_cb(void *closure, struct afb_xreq *xreq)
        xreq->request.api = to_api_x3(export);
 
        switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        case Api_Version_1:
                afb_api_so_v1_process_call(export->desc.v1, xreq);
                break;
 #endif
+#if WITH_LEGACY_BINDING_V2
        case Api_Version_2:
                afb_api_so_v2_process_call(export->desc.v2, xreq);
                break;
+#endif
        case Api_Version_3:
                afb_api_v3_process_call(export->desc.v3, xreq);
                break;
        default:
-               afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
+               afb_xreq_reply(xreq, NULL, afb_error_text_internal_error, NULL);
                break;
        }
 }
 
-static struct json_object *api_describe_cb(void *closure)
+static void api_describe_cb(void *closure, void (*describecb)(void *, struct json_object *), void *clocb)
 {
        struct afb_export *export = closure;
        struct json_object *result;
 
        switch (export->version) {
-#if defined(WITH_LEGACY_BINDING_V1)
+#if WITH_LEGACY_BINDING_V1
        case Api_Version_1:
                result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
                break;
 #endif
+#if WITH_LEGACY_BINDING_V2
        case Api_Version_2:
                result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
                break;
+#endif
        case Api_Version_3:
                result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
                break;
@@ -1662,7 +1846,7 @@ static struct json_object *api_describe_cb(void *closure)
                result = NULL;
                break;
        }
-       return result;
+       describecb(clocb, result);
 }
 
 static int api_service_start_cb(void *closure)
@@ -1672,12 +1856,13 @@ static int api_service_start_cb(void *closure)
        return afb_export_start(export);
 }
 
+#if WITH_AFB_HOOK
 static void api_update_hooks_cb(void *closure)
-{
-       struct afb_export *export = closure;
+       __attribute__((alias("set_interfaces")));
 
-       afb_export_update_hooks(export);
-}
+void afb_export_update_hooks(struct afb_export *export)
+       __attribute__((alias("set_interfaces")));
+#endif
 
 static int api_get_logmask_cb(void *closure)
 {
@@ -1704,7 +1889,9 @@ static struct afb_api_itf export_api_itf =
 {
        .call = api_call_cb,
        .service_start = api_service_start_cb,
+#if WITH_AFB_HOOK
        .update_hooks = api_update_hooks_cb,
+#endif
        .get_logmask = api_get_logmask_cb,
        .set_logmask = api_set_logmask_cb,
        .describe = api_describe_cb,
@@ -1733,7 +1920,7 @@ int afb_export_declare(struct afb_export *export,
                        ERROR("can't declare export %s to set %s, ABORTING it!",
                                export->api.apiname,
                                afb_apiset_name(export->declare_set));
-                       afb_export_addref(export);
+                       afb_export_unref(export);
                }
        }
 
@@ -1750,12 +1937,12 @@ void afb_export_undeclare(struct afb_export *export)
 
 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
 {
-       return afb_evt_event_x2_add_watch(export->listener, event);
+       return afb_evt_listener_watch_x2(export->listener, event);
 }
 
 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
 {
-       return afb_evt_event_x2_remove_watch(export->listener, event);
+       return afb_evt_listener_unwatch_x2(export->listener, event);
 }
 
 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
@@ -1765,7 +1952,6 @@ void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
 
 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
 {
-       afb_context_init(context, export->session, NULL);
-       context->validated = 1;
+       afb_context_init_validated(context, export->session, NULL, NULL);
 }