Allow renaming of API
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 4 Sep 2017 16:17:55 +0000 (18:17 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Thu, 7 Sep 2017 07:43:14 +0000 (09:43 +0200)
The function afb_daemon_rename_api allows to rename
an API during the preinit phase.

Change-Id: I35477ba99d35b1dc51a7cacf8e55c3f02d86d7b4
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
docs/afb-binding-references.md
include/afb/afb-binding.h
include/afb/afb-daemon-common.h
include/afb/afb-daemon-v1.h
include/afb/afb-daemon-v2.h
src/afb-api-so-v1.c
src/afb-api-so-v2.c
src/afb-ditf.c
src/afb-hook.c
src/afb-hook.h

index c266c2e..f5ab66d 100644 (file)
@@ -238,6 +238,18 @@ bindings at its initialization.
 int afb_daemon_require_api(const char *name, int initialized)
 ```
 
+This function allows to give a different name to the binding.
+It can be called during pre-init.
+
+```C
+/*
+ * Set the name of the API to 'name'.
+ * Calling this function is only allowed within preinit.
+ * Returns 0 in case of success or -1 in case of error.
+ */
+int afb_daemon_rename_api(const char *name);
+```
+
 ## Functions of class afb_service
 
 The following functions allow services to call verbs of other
index 1c4ec3f..f8e38c4 100644 (file)
@@ -161,6 +161,7 @@ typedef struct afb_service_itf          afb_service_itf;
 #define afb_daemon_rootdir_open_locale afb_daemon_rootdir_open_locale_v1
 #define afb_daemon_queue_job           afb_daemon_queue_job_v1
 #define afb_daemon_require_api         afb_daemon_require_api_v1
+#define afb_daemon_rename_api          afb_daemon_rename_api_v1
 
 #define afb_service_call               afb_service_call_v1
 #define afb_service_call_sync          afb_service_call_sync_v1
@@ -216,6 +217,7 @@ typedef struct afb_service_itf          afb_service_itf;
 #define afb_daemon_queue_job           afb_daemon_queue_job_v2
 #define afb_daemon_unstore_req         afb_daemon_unstore_req_v2
 #define afb_daemon_require_api         afb_daemon_require_api_v2
+#define afb_daemon_rename_api          afb_daemon_rename_api_v2
 
 #define afb_service_call               afb_service_call_v2
 #define afb_service_call_sync          afb_service_call_sync_v2
index 1d576b9..5faf575 100644 (file)
@@ -42,6 +42,7 @@ struct afb_daemon_itf
        void (*vverbose_v2)(void*closure, int level, const char *file, int line, const char * func, const char *fmt, va_list args);
        struct afb_req (*unstore_req)(void*closure, struct afb_stored_req *sreq);
        int (*require_api)(void*closure, const char *name, int initialized);
+       int (*rename_api)(void*closure, const char *name);
 };
 
 /*
index 81cdb12..7fc2c23 100644 (file)
@@ -180,3 +180,14 @@ static inline int afb_daemon_require_api_v1(struct afb_daemon daemon, const char
 {
        return daemon.itf->require_api(daemon.closure, name, initialized);
 }
+
+/*
+ * Set the name of the API to 'name'.
+ * Calling this function is only allowed within preinit.
+ * Returns 0 in case of success or -1 in case of error.
+ */
+static inline int afb_daemon_rename_api_v1(struct afb_daemon daemon, const char *name)
+{
+       return daemon.itf->rename_api(daemon.closure, name);
+}
+
index 7ef085b..1451a09 100644 (file)
@@ -157,3 +157,14 @@ static inline int afb_daemon_require_api_v2(const char *name, int initialized)
 {
        return afb_get_daemon_v2().itf->require_api(afb_get_daemon_v2().closure, name, initialized);
 }
+
+/*
+ * Set the name of the API to 'name'.
+ * Calling this function is only allowed within preinit.
+ * Returns 0 in case of success or -1 in case of error.
+ */
+static inline int afb_daemon_rename_api_v2(const char *name)
+{
+       return afb_get_daemon_v2().itf->rename_api(afb_get_daemon_v2().closure, name);
+}
+
index ad7a0cd..84b870d 100644 (file)
@@ -90,7 +90,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
                        goto done;
 
                /* already started: it is an error */
-               ERROR("Service %s already started", desc->binding->v1.prefix);
+               ERROR("Service %s already started", desc->ditf.api);
                return -1;
        }
 
@@ -103,14 +103,14 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
                        goto done;
 
                /* no initialisation method */
-               ERROR("Binding %s is not a service", desc->binding->v1.prefix);
+               ERROR("Binding %s is not a service", desc->ditf.api);
                return -1;
        }
 
        /* get the event handler if any */
-       desc->service = afb_svc_create(desc->binding->v1.prefix, apiset, share_session, onevent, NULL);
+       desc->service = afb_svc_create(desc->ditf.api, apiset, share_session, onevent, NULL);
        if (desc->service == NULL) {
-               ERROR("Creation of service %s failed", desc->binding->v1.prefix);
+               ERROR("Creation of service %s failed", desc->ditf.api);
                return -1;
        }
 
@@ -119,7 +119,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
        rc = afb_svc_start_v1(desc->service, init);
        if (rc < 0) {
                /* initialisation error */
-               ERROR("Initialisation of service %s failed (%d): %m", desc->binding->v1.prefix, rc);
+               ERROR("Initialisation of service %s failed (%d): %m", desc->ditf.api, rc);
                afb_svc_destroy(desc->service, NULL);
                desc->service = NULL;
                return rc;
@@ -195,9 +195,9 @@ static struct json_object *make_description_openAPIv3(struct api_so_v1 *desc)
 
        i = json_object_new_object();
        json_object_object_add(r, "info", i);
-       json_object_object_add(i, "title", json_object_new_string(desc->binding->v1.prefix));
+       json_object_object_add(i, "title", json_object_new_string(desc->ditf.api));
        json_object_object_add(i, "version", json_object_new_string("0.0.0"));
-       json_object_object_add(i, "description", json_object_new_string(desc->binding->v1.info ?: desc->binding->v1.prefix));
+       json_object_object_add(i, "description", json_object_new_string(desc->binding->v1.info ?: desc->ditf.api));
 
        p = json_object_new_object();
        json_object_object_add(r, "paths", p);
@@ -303,15 +303,16 @@ int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset)
        }
 
        /* records the binding */
-       afb_ditf_rename(&desc->ditf, desc->binding->v1.prefix);
+       if (desc->ditf.api == path)
+               afb_ditf_rename(&desc->ditf, desc->binding->v1.prefix);
        afb_api.closure = desc;
        afb_api.itf = &so_v1_api_itf;
        afb_api.noconcurrency = 0;
-       if (afb_apiset_add(apiset, desc->binding->v1.prefix, afb_api) < 0) {
+       if (afb_apiset_add(apiset, desc->ditf.api, afb_api) < 0) {
                ERROR("binding [%s] can't be registered...", path);
                goto error2;
        }
-       INFO("binding %s loaded with API prefix %s", path, desc->binding->v1.prefix);
+       INFO("binding %s loaded with API prefix %s", path, desc->ditf.api);
        return 1;
 
 error2:
index d8941a4..8403366 100644 (file)
@@ -90,7 +90,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
                        goto done;
 
                /* already started: it is an error */
-               ERROR("Service %s already started", desc->binding->api);
+               ERROR("Service %s already started", desc->ditf.api);
                return -1;
        }
 
@@ -103,15 +103,15 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
                        goto done;
 
                /* no initialisation method */
-               ERROR("Binding %s is not a service", desc->binding->api);
+               ERROR("Binding %s is not a service", desc->ditf.api);
                return -1;
        }
 
        /* get the event handler if any */
-       desc->service = afb_svc_create(desc->binding->api, apiset, share_session, onevent, &desc->data->service);
+       desc->service = afb_svc_create(desc->ditf.api, apiset, share_session, onevent, &desc->data->service);
        if (desc->service == NULL) {
                /* starting error */
-               ERROR("Starting service %s failed", desc->binding->api);
+               ERROR("Starting service %s failed", desc->ditf.api);
                return -1;
        }
 
@@ -120,7 +120,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct
        rc = afb_svc_start_v2(desc->service, start);
        if (rc < 0) {
                /* initialisation error */
-               ERROR("Initialisation of service %s failed (%d): %m", desc->binding->api, rc);
+               ERROR("Initialisation of service %s failed (%d): %m", desc->ditf.api, rc);
                afb_svc_destroy(desc->service, &desc->data->service);
                desc->service = NULL;
                return rc;
@@ -196,9 +196,9 @@ static struct json_object *make_description_openAPIv3(struct api_so_v2 *desc)
 
        i = json_object_new_object();
        json_object_object_add(r, "info", i);
-       json_object_object_add(i, "title", json_object_new_string(desc->binding->api));
+       json_object_object_add(i, "title", json_object_new_string(desc->ditf.api));
        json_object_object_add(i, "version", json_object_new_string("0.0.0"));
-       json_object_object_add(i, "description", json_object_new_string(desc->binding->info ?: desc->binding->api));
+       json_object_object_add(i, "description", json_object_new_string(desc->binding->info ?: desc->ditf.api));
 
        p = json_object_new_object();
        json_object_object_add(r, "paths", p);
@@ -288,7 +288,7 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle
                INFO("binding %s calling preinit function", binding->api);
                rc = binding->preinit();
                if (rc < 0) {
-                       ERROR("binding %s preinit function failed...", binding->api);
+                       ERROR("binding %s preinit function failed...", desc->ditf.api);
                        goto error2;
                }
        }
@@ -297,11 +297,11 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle
        afb_api.closure = desc;
        afb_api.itf = &so_v2_api_itf;
        afb_api.noconcurrency = binding->noconcurrency;
-       if (afb_apiset_add(apiset, binding->api, afb_api) < 0) {
-               ERROR("binding %s can't be registered to set %s...", binding->api, afb_apiset_name(apiset));
+       if (afb_apiset_add(apiset, desc->ditf.api, afb_api) < 0) {
+               ERROR("binding %s can't be registered to set %s...", desc->ditf.api, afb_apiset_name(apiset));
                goto error2;
        }
-       INFO("binding %s added to set %s", binding->api, afb_apiset_name(apiset));
+       INFO("binding %s added to set %s", desc->ditf.api, afb_apiset_name(apiset));
        return 1;
 
 error2:
index 63268a8..d3db9bb 100644 (file)
@@ -137,6 +137,24 @@ static int require_api_cb(void *closure, const char *name, int initialized)
        return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(main_apiset, name, 1);
 }
 
+static int rename_api_cb(void *closure, const char *name)
+{
+       struct afb_ditf *ditf = closure;
+       if (ditf->state != Daemon_Pre_Init) {
+               ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", ditf->api, name);
+               errno = EINVAL;
+               return -1;
+       }
+       if (!afb_api_is_valid_name(name)) {
+               ERROR("[API %s] Can't rename to %s: bad API name", ditf->api, name);
+               errno = EINVAL;
+               return -1;
+       }
+       NOTICE("[API %s] renamed to [API %s]", ditf->api, name);
+       afb_ditf_rename(ditf, name);
+       return 0;
+}
+
 /**********************************************
 * hooked flow
 **********************************************/
@@ -232,6 +250,14 @@ static int hooked_require_api_cb(void *closure, const char *name, int initialize
        return afb_hook_ditf_require_api_result(ditf, name, initialized, result);
 }
 
+static int hooked_rename_api_cb(void *closure, const char *name)
+{
+       struct afb_ditf *ditf = closure;
+       const char *oldname = ditf->api;
+       int result = rename_api_cb(closure, name);
+       return afb_hook_ditf_rename_api(ditf, oldname, name, result);
+}
+
 /**********************************************
 * vectors
 **********************************************/
@@ -247,7 +273,8 @@ static const struct afb_daemon_itf daemon_itf = {
        .rootdir_open_locale = rootdir_open_locale_cb,
        .queue_job = queue_job_cb,
        .unstore_req = unstore_req_cb,
-       .require_api = require_api_cb
+       .require_api = require_api_cb,
+       .rename_api = rename_api_cb
 };
 
 static const struct afb_daemon_itf hooked_daemon_itf = {
@@ -262,7 +289,8 @@ static const struct afb_daemon_itf hooked_daemon_itf = {
        .rootdir_open_locale = hooked_rootdir_open_locale_cb,
        .queue_job = hooked_queue_job_cb,
        .unstore_req = hooked_unstore_req_cb,
-       .require_api = hooked_require_api_cb
+       .require_api = hooked_require_api_cb,
+       .rename_api = hooked_rename_api_cb
 };
 
 void afb_ditf_init_v2(struct afb_ditf *ditf, const char *api, struct afb_binding_data_v2 *data)
index 7dd81cb..a1ecea6 100644 (file)
@@ -752,6 +752,11 @@ static void hook_ditf_require_api_result_cb(void *closure, const struct afb_hook
        _hook_ditf_(ditf, "...require_api(%s, %d) -> %d", name, initialized, result);
 }
 
+static void hook_ditf_rename_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *oldname, const char *newname, int result)
+{
+       _hook_ditf_(ditf, "rename_api(%s -> %s) -> %d", oldname, newname, result);
+}
+
 static struct afb_hook_ditf_itf hook_ditf_default_itf = {
        .hook_ditf_event_broadcast_before = hook_ditf_event_broadcast_before_cb,
        .hook_ditf_event_broadcast_after = hook_ditf_event_broadcast_after_cb,
@@ -765,7 +770,8 @@ static struct afb_hook_ditf_itf hook_ditf_default_itf = {
        .hook_ditf_queue_job = hook_ditf_queue_job_cb,
        .hook_ditf_unstore_req = hook_ditf_unstore_req_cb,
        .hook_ditf_require_api = hook_ditf_require_api_cb,
-       .hook_ditf_require_api_result = hook_ditf_require_api_result_cb
+       .hook_ditf_require_api_result = hook_ditf_require_api_result_cb,
+       .hook_ditf_rename_api = hook_ditf_rename_api_cb
 };
 
 /******************************************************************************
@@ -862,6 +868,12 @@ int afb_hook_ditf_require_api_result(const struct afb_ditf *ditf, const char *na
        return result;
 }
 
+int afb_hook_ditf_rename_api(const struct afb_ditf *ditf, const char *oldname, const char *newname, int result)
+{
+       _HOOK_DITF_(rename_api, ditf, oldname, newname, result);
+       return result;
+}
+
 /******************************************************************************
  * section: hooking ditf
  *****************************************************************************/
index 235e19d..6f54f70 100644 (file)
@@ -176,11 +176,13 @@ extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char
 #define afb_hook_flag_ditf_unstore_req                 0x000400
 #define afb_hook_flag_ditf_require_api                 0x000800
 #define afb_hook_flag_ditf_require_api_result          0x001000
+#define afb_hook_flag_ditf_rename_api                  0x002000
 
 #define afb_hook_flags_ditf_common     (afb_hook_flag_ditf_vverbose\
                                        |afb_hook_flag_ditf_event_make\
                                        |afb_hook_flag_ditf_event_broadcast_before\
-                                       |afb_hook_flag_ditf_event_broadcast_after)
+                                       |afb_hook_flag_ditf_event_broadcast_after\
+                                       |afb_hook_flag_ditf_rename_api)
 #define afb_hook_flags_ditf_extra      (afb_hook_flag_ditf_get_event_loop\
                                        |afb_hook_flag_ditf_get_user_bus\
                                        |afb_hook_flag_ditf_get_system_bus\
@@ -207,6 +209,7 @@ struct afb_hook_ditf_itf {
        void (*hook_ditf_unstore_req)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct afb_stored_req *sreq);
        void (*hook_ditf_require_api)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, int initialized);
        void (*hook_ditf_require_api_result)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, int initialized, int result);
+       void (*hook_ditf_rename_api)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *oldname, const char *newname, int result);
 };
 
 extern void afb_hook_ditf_event_broadcast_before(const struct afb_ditf *ditf, const char *name, struct json_object *object);
@@ -222,6 +225,7 @@ extern int afb_hook_ditf_queue_job(const struct afb_ditf *ditf, void (*callback)
 extern void afb_hook_ditf_unstore_req(const struct afb_ditf *ditf, struct afb_stored_req *sreq);
 extern void afb_hook_ditf_require_api(const struct afb_ditf *ditf, const char *name, int initialized);
 extern int afb_hook_ditf_require_api_result(const struct afb_ditf *ditf, const char *name, int initialized, int result);
+extern int afb_hook_ditf_rename_api(const struct afb_ditf *ditf, const char *oldname, const char *newname, int result);
 
 extern int afb_hook_flags_ditf(const char *api);
 extern struct afb_hook_ditf *afb_hook_create_ditf(const char *api, int flags, struct afb_hook_ditf_itf *itf, void *closure);