From 550b36945f2e9eae1fc4b822ea9a00a2a866eb83 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Mon, 4 Sep 2017 18:17:55 +0200 Subject: [PATCH] Allow renaming of API MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The function afb_daemon_rename_api allows to rename an API during the preinit phase. Change-Id: I35477ba99d35b1dc51a7cacf8e55c3f02d86d7b4 Signed-off-by: José Bollo --- docs/afb-binding-references.md | 12 ++++++++++++ include/afb/afb-binding.h | 2 ++ include/afb/afb-daemon-common.h | 1 + include/afb/afb-daemon-v1.h | 11 +++++++++++ include/afb/afb-daemon-v2.h | 11 +++++++++++ src/afb-api-so-v1.c | 21 +++++++++++---------- src/afb-api-so-v2.c | 22 +++++++++++----------- src/afb-ditf.c | 32 ++++++++++++++++++++++++++++++-- src/afb-hook.c | 14 +++++++++++++- src/afb-hook.h | 6 +++++- 10 files changed, 107 insertions(+), 25 deletions(-) diff --git a/docs/afb-binding-references.md b/docs/afb-binding-references.md index c266c2ef..f5ab66d1 100644 --- a/docs/afb-binding-references.md +++ b/docs/afb-binding-references.md @@ -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 diff --git a/include/afb/afb-binding.h b/include/afb/afb-binding.h index 1c4ec3f2..f8e38c49 100644 --- a/include/afb/afb-binding.h +++ b/include/afb/afb-binding.h @@ -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 diff --git a/include/afb/afb-daemon-common.h b/include/afb/afb-daemon-common.h index 1d576b9a..5faf5758 100644 --- a/include/afb/afb-daemon-common.h +++ b/include/afb/afb-daemon-common.h @@ -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); }; /* diff --git a/include/afb/afb-daemon-v1.h b/include/afb/afb-daemon-v1.h index 81cdb124..7fc2c235 100644 --- a/include/afb/afb-daemon-v1.h +++ b/include/afb/afb-daemon-v1.h @@ -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); +} + diff --git a/include/afb/afb-daemon-v2.h b/include/afb/afb-daemon-v2.h index 7ef085b0..1451a097 100644 --- a/include/afb/afb-daemon-v2.h +++ b/include/afb/afb-daemon-v2.h @@ -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); +} + diff --git a/src/afb-api-so-v1.c b/src/afb-api-so-v1.c index ad7a0cdd..84b870d7 100644 --- a/src/afb-api-so-v1.c +++ b/src/afb-api-so-v1.c @@ -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: diff --git a/src/afb-api-so-v2.c b/src/afb-api-so-v2.c index d8941a42..8403366b 100644 --- a/src/afb-api-so-v2.c +++ b/src/afb-api-so-v2.c @@ -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: diff --git a/src/afb-ditf.c b/src/afb-ditf.c index 63268a85..d3db9bb0 100644 --- a/src/afb-ditf.c +++ b/src/afb-ditf.c @@ -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) diff --git a/src/afb-hook.c b/src/afb-hook.c index 7dd81cba..a1ecea6d 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -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 *****************************************************************************/ diff --git a/src/afb-hook.h b/src/afb-hook.h index 235e19d9..6f54f703 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -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); -- 2.16.6