diff options
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/afb-api-so-v1.c | 92 | ||||
-rw-r--r-- | src/afb-api-so-v2.c | 82 | ||||
-rw-r--r-- | src/afb-ditf.c | 333 | ||||
-rw-r--r-- | src/afb-ditf.h | 45 | ||||
-rw-r--r-- | src/afb-export.c | 882 | ||||
-rw-r--r-- | src/afb-export.h | 47 | ||||
-rw-r--r-- | src/afb-hook.c | 217 | ||||
-rw-r--r-- | src/afb-hook.h | 95 | ||||
-rw-r--r-- | src/afb-monitor.c | 1 | ||||
-rw-r--r-- | src/afb-svc.c | 381 | ||||
-rw-r--r-- | src/afb-svc.h | 66 | ||||
-rw-r--r-- | src/afb-trace.c | 103 |
13 files changed, 1214 insertions, 1133 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74702ad3..39b7fe1a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,8 +43,8 @@ ADD_LIBRARY(afb-lib STATIC afb-context.c afb-cred.c afb-debug.c - afb-ditf.c afb-evt.c + afb-export.c afb-hook.c afb-hreq.c afb-hsrv.c @@ -55,7 +55,6 @@ ADD_LIBRARY(afb-lib STATIC afb-proto-ws.c afb-session.c afb-stub-ws.c - afb-svc.c afb-trace.c afb-websock.c afb-ws-client.c diff --git a/src/afb-api-so-v1.c b/src/afb-api-so-v1.c index 84b870d7..dd2db5bf 100644 --- a/src/afb-api-so-v1.c +++ b/src/afb-api-so-v1.c @@ -29,13 +29,12 @@ #include "afb-api.h" #include "afb-api-so-v1.h" #include "afb-apiset.h" -#include "afb-svc.h" -#include "afb-evt.h" +#include "afb-export.h" +//#include "afb-evt.h" #include "afb-common.h" #include "afb-context.h" #include "afb-api-so.h" #include "afb-xreq.h" -#include "afb-ditf.h" #include "verbose.h" /* @@ -51,9 +50,7 @@ static const char afb_api_so_v1_service_event[] = "afbBindingV1ServiceEvent"; struct api_so_v1 { struct afb_binding_v1 *binding; /* descriptor */ void *handle; /* context of dlopen */ - struct afb_svc *service; /* handler for service started */ - struct afb_binding_interface_v1 interface; - struct afb_ditf ditf; /* daemon interface */ + struct afb_export *export; /* export */ }; static const struct afb_verb_desc_v1 *search(struct api_so_v1 *desc, const char *name) @@ -84,70 +81,64 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct struct api_so_v1 *desc = closure; /* check state */ - if (desc->service != NULL) { + if (afb_export_is_started(desc->export)) { /* not an error when onneed */ if (onneed != 0) goto done; /* already started: it is an error */ - ERROR("Service %s already started", desc->ditf.api); + ERROR("Service %s already started", afb_export_apiname(desc->export)); return -1; } /* get the initialisation */ init = dlsym(desc->handle, afb_api_so_v1_service_init); onevent = dlsym(desc->handle, afb_api_so_v1_service_event); - if (init == NULL && onevent == NULL) { - /* not an error when onneed */ - if (onneed != 0) - goto done; - /* no initialisation method */ - ERROR("Binding %s is not a service", desc->ditf.api); - return -1; + /* unshare the session if asked */ + if (!share_session) { + rc = afb_export_unshare_session(desc->export); + if (rc < 0) { + ERROR("Can't unshare the session for %s", afb_export_apiname(desc->export)); + return -1; + } } - /* get the event handler if any */ - desc->service = afb_svc_create(desc->ditf.api, apiset, share_session, onevent, NULL); - if (desc->service == NULL) { - ERROR("Creation of service %s failed", desc->ditf.api); + /* set event handling */ + rc = afb_export_handle_events(desc->export, onevent); + if (rc < 0) { + ERROR("Can't set event handler for %s", afb_export_apiname(desc->export)); return -1; } /* Starts the service */ - desc->ditf.state = Daemon_Init; - rc = afb_svc_start_v1(desc->service, init); + rc = afb_export_start_v1(desc->export, init); if (rc < 0) { /* initialisation error */ - ERROR("Initialisation of service %s failed (%d): %m", desc->ditf.api, rc); - afb_svc_destroy(desc->service, NULL); - desc->service = NULL; + ERROR("Initialisation of service %s failed (%d): %m", afb_export_apiname(desc->export), rc); return rc; } done: - desc->ditf.state = Daemon_Run; return 0; } static void update_hooks_cb(void *closure) { struct api_so_v1 *desc = closure; - afb_ditf_update_hook(&desc->ditf); - if (desc->service) - afb_svc_update_hook(desc->service); + afb_export_update_hook(desc->export); } static int get_verbosity_cb(void *closure) { struct api_so_v1 *desc = closure; - return desc->interface.verbosity; + return afb_export_verbosity_get(desc->export); } static void set_verbosity_cb(void *closure, int level) { struct api_so_v1 *desc = closure; - desc->interface.verbosity = level; + afb_export_verbosity_set(desc->export, level); } static struct json_object *addperm(struct json_object *o, struct json_object *x) @@ -195,9 +186,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->ditf.api)); + json_object_object_add(i, "title", json_object_new_string(afb_export_apiname(desc->export))); 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->ditf.api)); + json_object_object_add(i, "description", json_object_new_string(desc->binding->v1.info ?: afb_export_apiname(desc->export))); p = json_object_new_object(); json_object_object_add(r, "paths", p); @@ -254,6 +245,7 @@ int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset) struct api_so_v1 *desc; struct afb_binding_v1 *(*register_function) (const struct afb_binding_interface_v1 *interface); struct afb_api afb_api; + struct afb_export *export; /* retrieves the register function */ register_function = dlsym(handle, afb_api_so_v1_register); @@ -262,62 +254,62 @@ int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset) INFO("binding [%s] is a valid AFB binding V1", path); /* allocates the description */ + export = afb_export_create_v1(path); desc = calloc(1, sizeof *desc); - if (desc == NULL) { + if (desc == NULL || export == NULL) { ERROR("out of memory"); goto error; } + desc->export = export; desc->handle = handle; - /* init the interface */ - afb_ditf_init_v1(&desc->ditf, path, &desc->interface); - /* init the binding */ INFO("binding [%s] calling registering function %s", path, afb_api_so_v1_register); - desc->binding = register_function(&desc->interface); + desc->binding = afb_export_register_v1(desc->export, register_function); if (desc->binding == NULL) { ERROR("binding [%s] register function failed. continuing...", path); - goto error2; + goto error; } /* check the returned structure */ if (desc->binding->type != AFB_BINDING_VERSION_1) { ERROR("binding [%s] invalid type %d...", path, desc->binding->type); - goto error2; + goto error; } if (desc->binding->v1.prefix == NULL || *desc->binding->v1.prefix == 0) { ERROR("binding [%s] bad prefix...", path); - goto error2; + goto error; } if (!afb_api_is_valid_name(desc->binding->v1.prefix)) { ERROR("binding [%s] invalid prefix...", path); - goto error2; + goto error; } if (desc->binding->v1.info == NULL || *desc->binding->v1.info == 0) { ERROR("binding [%s] bad description...", path); - goto error2; + goto error; } if (desc->binding->v1.verbs == NULL) { ERROR("binding [%s] no APIs...", path); - goto error2; + goto error; } /* records the binding */ - if (desc->ditf.api == path) - afb_ditf_rename(&desc->ditf, desc->binding->v1.prefix); + if (!strcmp(path, afb_export_apiname(desc->export))) + afb_export_rename(desc->export, 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->ditf.api, afb_api) < 0) { + if (afb_apiset_add(apiset, afb_export_apiname(desc->export), afb_api) < 0) { ERROR("binding [%s] can't be registered...", path); - goto error2; + goto error; } - INFO("binding %s loaded with API prefix %s", path, desc->ditf.api); + INFO("binding %s loaded with API prefix %s", path, afb_export_apiname(desc->export)); return 1; -error2: - free(desc); error: + afb_export_destroy(export); + free(desc); + return -1; } diff --git a/src/afb-api-so-v2.c b/src/afb-api-so-v2.c index 32812243..68fd865c 100644 --- a/src/afb-api-so-v2.c +++ b/src/afb-api-so-v2.c @@ -28,8 +28,7 @@ #include "afb-api.h" #include "afb-api-so-v2.h" #include "afb-apiset.h" -#include "afb-svc.h" -#include "afb-ditf.h" +#include "afb-export.h" #include "afb-evt.h" #include "afb-common.h" #include "afb-context.h" @@ -49,10 +48,8 @@ static const char afb_api_so_v2_data[] = "afbBindingV2data"; */ struct api_so_v2 { const struct afb_binding_v2 *binding; /* descriptor */ - struct afb_binding_data_v2 *data; /* data */ - void *handle; /* context of dlopen */ - struct afb_svc *service; /* handler for service started */ - struct afb_ditf ditf; /* daemon interface */ + void *handle; /* context of dlopen */ + struct afb_export *export; /* exportations */ }; static const struct afb_verb_v2 *search(struct api_so_v2 *desc, const char *name) @@ -84,71 +81,64 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct struct api_so_v2 *desc = closure; /* check state */ - if (desc->service != NULL) { + if (afb_export_is_started(desc->export)) { /* not an error when onneed */ if (onneed != 0) goto done; /* already started: it is an error */ - ERROR("Service %s already started", desc->ditf.api); + ERROR("Service %s already started", afb_export_apiname(desc->export)); return -1; } /* get the initialisation */ start = desc->binding->init; onevent = desc->binding->onevent; - if (start == NULL && onevent == NULL) { - /* not an error when onneed */ - if (onneed != 0) - goto done; - /* no initialisation method */ - ERROR("Binding %s is not a service", desc->ditf.api); - return -1; + /* unshare the session if asked */ + if (!share_session) { + rc = afb_export_unshare_session(desc->export); + if (rc < 0) { + ERROR("Can't unshare the session for %s", afb_export_apiname(desc->export)); + return -1; + } } - /* get the event handler if any */ - 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->ditf.api); + /* set event handling */ + rc = afb_export_handle_events(desc->export, onevent); + if (rc < 0) { + ERROR("Can't set event handler for %s", afb_export_apiname(desc->export)); return -1; } /* Starts the service */ - desc->ditf.state = Daemon_Init; - rc = afb_svc_start_v2(desc->service, start); + rc = afb_export_start_v2(desc->export, start); if (rc < 0) { /* initialisation error */ - ERROR("Initialisation of service %s failed (%d): %m", desc->ditf.api, rc); - afb_svc_destroy(desc->service, &desc->data->service); - desc->service = NULL; + ERROR("Initialisation of service %s failed (%d): %m", afb_export_apiname(desc->export), rc); return rc; } done: - desc->ditf.state = Daemon_Run; return 0; } static void update_hooks_cb(void *closure) { struct api_so_v2 *desc = closure; - afb_ditf_update_hook(&desc->ditf); - if (desc->service) - afb_svc_update_hook(desc->service); + afb_export_update_hook(desc->export); } static int get_verbosity_cb(void *closure) { struct api_so_v2 *desc = closure; - return desc->data->verbosity; + return afb_export_verbosity_get(desc->export); } static void set_verbosity_cb(void *closure, int level) { struct api_so_v2 *desc = closure; - desc->data->verbosity = level; + afb_export_verbosity_set(desc->export, level); } static struct json_object *addperm(struct json_object *o, struct json_object *x) @@ -225,9 +215,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->ditf.api)); + json_object_object_add(i, "title", json_object_new_string(afb_export_apiname(desc->export))); 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->ditf.api)); + json_object_object_add(i, "description", json_object_new_string(desc->binding->info ?: afb_export_apiname(desc->export))); p = json_object_new_object(); json_object_object_add(r, "paths", p); @@ -288,6 +278,7 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle int rc; struct api_so_v2 *desc; struct afb_api afb_api; + struct afb_export *export; /* basic checks */ assert(binding); @@ -296,27 +287,23 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle assert(data); /* allocates the description */ + export = afb_export_create_v2(binding->api, data); desc = calloc(1, sizeof *desc); if (desc == NULL) { ERROR("out of memory"); goto error; } desc->binding = binding; - desc->data = data; desc->handle = handle; - desc->service = NULL; - - /* init the interface */ - desc->data->verbosity = verbosity; - afb_ditf_init_v2(&desc->ditf, binding->api, data); + desc->export = export; /* init the binding */ if (binding->preinit) { INFO("binding %s calling preinit function", binding->api); rc = binding->preinit(); if (rc < 0) { - ERROR("binding %s preinit function failed...", desc->ditf.api); - goto error2; + ERROR("binding %s preinit function failed...", afb_export_apiname(desc->export)); + goto error; } } @@ -324,16 +311,17 @@ 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, 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; + if (afb_apiset_add(apiset, afb_export_apiname(desc->export), afb_api) < 0) { + ERROR("binding %s can't be registered to set %s...", afb_export_apiname(desc->export), afb_apiset_name(apiset)); + goto error; } - INFO("binding %s added to set %s", desc->ditf.api, afb_apiset_name(apiset)); + INFO("binding %s added to set %s", afb_export_apiname(desc->export), afb_apiset_name(apiset)); return 1; -error2: - free(desc); error: + afb_export_destroy(export); + free(desc); + return -1; } diff --git a/src/afb-ditf.c b/src/afb-ditf.c deleted file mode 100644 index a7f97ddc..00000000 --- a/src/afb-ditf.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2016, 2017 "IoT.bzh" - * Author José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <json-c/json.h> - -#include <afb/afb-binding-v1.h> -#include <afb/afb-binding-v2.h> - -#include "afb-ditf.h" -#include "afb-evt.h" -#include "afb-common.h" -#include "afb-xreq.h" -#include "afb-api.h" -#include "afb-apiset.h" -#include "afb-hook.h" -#include "jobs.h" -#include "verbose.h" - -extern struct afb_apiset *main_apiset; - -/********************************************** -* normal flow -**********************************************/ -static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args) -{ - char *p; - struct afb_ditf *ditf = closure; - - if (!fmt || vasprintf(&p, fmt, args) < 0) - vverbose(level, file, line, function, fmt, args); - else { - verbose(level, file, line, function, "[API %s] %s", ditf->api, p); - free(p); - } -} - -static void old_vverbose_cb(void *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 event_make_cb(void *closure, const char *name) -{ - size_t plen, nlen; - char *event; - struct afb_ditf *ditf = closure; - - /* check daemon state */ - if (ditf->state == Daemon_Pre_Init) { - ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", ditf->api, name); - errno = EINVAL; - return (struct afb_event){ .itf = NULL, .closure = NULL }; - } - - /* makes the event name */ - plen = strlen(ditf->api); - nlen = strlen(name); - event = alloca(nlen + plen + 2); - memcpy(event, ditf->api, plen); - event[plen] = '/'; - memcpy(event + plen + 1, name, nlen + 1); - - /* create the event */ - return afb_evt_create_event(event); -} - -static int event_broadcast_cb(void *closure, const char *name, struct json_object *object) -{ - size_t plen, nlen; - char *event; - struct afb_ditf *ditf = closure; - - /* check daemon state */ - if (ditf->state == Daemon_Pre_Init) { - ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", ditf->api, name, json_object_to_json_string(object)); - errno = EINVAL; - return 0; - } - - /* makes the event name */ - plen = strlen(ditf->api); - nlen = strlen(name); - event = alloca(nlen + plen + 2); - memcpy(event, ditf->api, plen); - event[plen] = '/'; - memcpy(event + plen + 1, name, nlen + 1); - - /* broadcast the event */ - return afb_evt_broadcast(event, object); -} - -static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale) -{ - return afb_common_rootdir_open_locale(filename, flags, locale); -} - -static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) -{ - return jobs_queue(group, timeout, callback, argument); -} - -static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq) -{ - return afb_xreq_unstore(sreq); -} - -static int require_api_cb(void *closure, const char *name, int initialized) -{ - struct afb_ditf *ditf = closure; - if (ditf->state != Daemon_Init) { - ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", ditf->api, name, initialized); - errno = EINVAL; - return -1; - } - 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 -**********************************************/ -static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args) -{ - struct afb_ditf *ditf = closure; - va_list ap; - va_copy(ap, args); - vverbose_cb(closure, level, file, line, function, fmt, args); - afb_hook_ditf_vverbose(ditf, level, file, line, function, fmt, ap); - va_end(ap); -} - -static void hooked_old_vverbose_cb(void *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 hooked_event_make_cb(void *closure, const char *name) -{ - struct afb_ditf *ditf = closure; - struct afb_event r = event_make_cb(closure, name); - return afb_hook_ditf_event_make(ditf, name, r); -} - -static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object) -{ - int r; - struct afb_ditf *ditf = closure; - json_object_get(object); - afb_hook_ditf_event_broadcast_before(ditf, name, json_object_get(object)); - r = event_broadcast_cb(closure, name, object); - afb_hook_ditf_event_broadcast_after(ditf, name, object, r); - json_object_put(object); - return r; -} - -static struct sd_event *hooked_get_event_loop(void *closure) -{ - struct afb_ditf *ditf = closure; - struct sd_event *r = afb_common_get_event_loop(); - return afb_hook_ditf_get_event_loop(ditf, r); -} - -static struct sd_bus *hooked_get_user_bus(void *closure) -{ - struct afb_ditf *ditf = closure; - struct sd_bus *r = afb_common_get_user_bus(); - return afb_hook_ditf_get_user_bus(ditf, r); -} - -static struct sd_bus *hooked_get_system_bus(void *closure) -{ - struct afb_ditf *ditf = closure; - struct sd_bus *r = afb_common_get_system_bus(); - return afb_hook_ditf_get_system_bus(ditf, r); -} - -static int hooked_rootdir_get_fd(void *closure) -{ - struct afb_ditf *ditf = closure; - int r = afb_common_rootdir_get_fd(); - return afb_hook_ditf_rootdir_get_fd(ditf, r); -} - -static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale) -{ - struct afb_ditf *ditf = closure; - int r = rootdir_open_locale_cb(closure, filename, flags, locale); - return afb_hook_ditf_rootdir_open_locale(ditf, filename, flags, locale, r); -} - -static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) -{ - struct afb_ditf *ditf = closure; - int r = queue_job_cb(closure, callback, argument, group, timeout); - return afb_hook_ditf_queue_job(ditf, callback, argument, group, timeout, r); -} - -static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq) -{ - struct afb_ditf *ditf = closure; - afb_hook_ditf_unstore_req(ditf, sreq); - return unstore_req_cb(closure, sreq); -} - -static int hooked_require_api_cb(void *closure, const char *name, int initialized) -{ - int result; - struct afb_ditf *ditf = closure; - afb_hook_ditf_require_api(ditf, name, initialized); - result = require_api_cb(closure, name, initialized); - 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 -**********************************************/ -static const struct afb_daemon_itf daemon_itf = { - .vverbose_v1 = old_vverbose_cb, - .vverbose_v2 = vverbose_cb, - .event_make = event_make_cb, - .event_broadcast = event_broadcast_cb, - .get_event_loop = afb_common_get_event_loop, - .get_user_bus = afb_common_get_user_bus, - .get_system_bus = afb_common_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 = unstore_req_cb, - .require_api = require_api_cb, - .rename_api = rename_api_cb -}; - -static const struct afb_daemon_itf hooked_daemon_itf = { - .vverbose_v1 = hooked_old_vverbose_cb, - .vverbose_v2 = hooked_vverbose_cb, - .event_make = hooked_event_make_cb, - .event_broadcast = hooked_event_broadcast_cb, - .get_event_loop = hooked_get_event_loop, - .get_user_bus = hooked_get_user_bus, - .get_system_bus = hooked_get_system_bus, - .rootdir_get_fd = hooked_rootdir_get_fd, - .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, - .rename_api = hooked_rename_api_cb -}; - -void afb_ditf_init_v2(struct afb_ditf *ditf, const char *api, struct afb_binding_data_v2 *data) -{ - ditf->version = 2; - ditf->state = Daemon_Pre_Init; - ditf->v2 = data; - data->daemon.closure = ditf; - afb_ditf_rename(ditf, api); -} - -void afb_ditf_init_v1(struct afb_ditf *ditf, const char *api, struct afb_binding_interface_v1 *itf) -{ - ditf->version = 1; - ditf->state = Daemon_Pre_Init; - ditf->v1 = itf; - itf->verbosity = verbosity; - itf->mode = AFB_MODE_LOCAL; - itf->daemon.closure = ditf; - afb_ditf_rename(ditf, api); -} - -void afb_ditf_rename(struct afb_ditf *ditf, const char *api) -{ - ditf->api = api; - afb_ditf_update_hook(ditf); -} - -void afb_ditf_update_hook(struct afb_ditf *ditf) -{ - int hooked = !!afb_hook_flags_ditf(ditf->api); - switch (ditf->version) { - case 1: - ditf->v1->daemon.itf = hooked ? &hooked_daemon_itf : &daemon_itf; - break; - default: - case 2: - ditf->v2->daemon.itf = hooked ? &hooked_daemon_itf : &daemon_itf; - break; - } -} - diff --git a/src/afb-ditf.h b/src/afb-ditf.h deleted file mode 100644 index a24eb0ae..00000000 --- a/src/afb-ditf.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016, 2017 "IoT.bzh" - * Author José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -struct afb_binding_interface_v1; -struct afb_binding_data_v2; - -enum afb_ditf_state -{ - Daemon_Pre_Init, - Daemon_Init, - Daemon_Run -}; - -struct afb_ditf -{ - int version; - enum afb_ditf_state state; - const char *api; - union { - struct afb_binding_interface_v1 *v1; - struct afb_binding_data_v2 *v2; - }; -}; - -extern void afb_ditf_init_v1(struct afb_ditf *ditf, const char *api, struct afb_binding_interface_v1 *itf); -extern void afb_ditf_init_v2(struct afb_ditf *ditf, const char *api, struct afb_binding_data_v2 *data); -extern void afb_ditf_rename(struct afb_ditf *ditf, const char *api); -extern void afb_ditf_update_hook(struct afb_ditf *ditf); - diff --git a/src/afb-export.c b/src/afb-export.c new file mode 100644 index 00000000..70a63774 --- /dev/null +++ b/src/afb-export.c @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author: José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <json-c/json.h> + +#include <afb/afb-binding-v1.h> +#include <afb/afb-binding-v2.h> + +#include "afb-api.h" +#include "afb-apiset.h" +#include "afb-common.h" +#include "afb-cred.h" +#include "afb-evt.h" +#include "afb-export.h" +#include "afb-hook.h" +#include "afb-msg-json.h" +#include "afb-session.h" +#include "afb-xreq.h" +#include "jobs.h" +#include "verbose.h" + +extern struct afb_apiset *main_apiset; + +/************************************************************************* + * internal types and structures + ************************************************************************/ + +enum afb_api_version +{ + Api_Version_None = 0, + Api_Version_1 = 1, + Api_Version_2 = 2, + Api_Version_3 = 3 +}; + +enum afb_api_state +{ + Api_State_Pre_Init, + Api_State_Init, + Api_State_Run +}; + +struct afb_export +{ + /* name of the api */ + char *apiname; + + /* version of the api */ + unsigned version: 4; + + /* current state */ + unsigned state: 4; + + /* hooking flags */ + int hookditf; + int hooksvc; + + /* session for service */ + struct afb_session *session; + + /* apiset for service */ + struct afb_apiset *apiset; + + /* event listener for service or NULL */ + struct afb_evt_listener *listener; + + /* event callback for service */ + void (*on_event)(const char *event, struct json_object *object); + + /* exported data */ + union { + struct afb_binding_interface_v1 v1; + struct afb_binding_data_v2 *v2; + } export; +}; + +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + F R O M D I T F + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +/********************************************** +* normal flow +**********************************************/ +static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +{ + char *p; + struct afb_export *export = closure; + + if (!fmt || vasprintf(&p, fmt, args) < 0) + vverbose(level, file, line, function, fmt, args); + else { + verbose(level, file, line, function, "[API %s] %s", export->apiname, p); + free(p); + } +} + +static void old_vverbose_cb(void *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 event_make_cb(void *closure, const char *name) +{ + size_t plen, nlen; + char *event; + struct afb_export *export = closure; + + /* check daemon state */ + if (export->state == Api_State_Pre_Init) { + ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name); + errno = EINVAL; + return (struct afb_event){ .itf = NULL, .closure = NULL }; + } + + /* makes the event name */ + plen = strlen(export->apiname); + nlen = strlen(name); + event = alloca(nlen + plen + 2); + memcpy(event, export->apiname, plen); + event[plen] = '/'; + memcpy(event + plen + 1, name, nlen + 1); + + /* create the event */ + return afb_evt_create_event(event); +} + +static int event_broadcast_cb(void *closure, const char *name, struct json_object *object) +{ + size_t plen, nlen; + char *event; + struct afb_export *export = closure; + + /* check daemon state */ + if (export->state == Api_State_Pre_Init) { + ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->apiname, name, json_object_to_json_string(object)); + errno = EINVAL; + return 0; + } + + /* makes the event name */ + plen = strlen(export->apiname); + nlen = strlen(name); + event = alloca(nlen + plen + 2); + memcpy(event, export->apiname, plen); + event[plen] = '/'; + memcpy(event + plen + 1, name, nlen + 1); + + /* broadcast the event */ + return afb_evt_broadcast(event, object); +} + +static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale) +{ + return afb_common_rootdir_open_locale(filename, flags, locale); +} + +static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) +{ + return jobs_queue(group, timeout, callback, argument); +} + +static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq) +{ + return afb_xreq_unstore(sreq); +} + +static int require_api_cb(void *closure, const char *name, int initialized) +{ + struct afb_export *export = closure; + if (export->state != Api_State_Init) { + ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized); + errno = EINVAL; + return -1; + } + 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_export *export = closure; + if (export->state != Api_State_Pre_Init) { + ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name); + errno = EINVAL; + return -1; + } + if (!afb_api_is_valid_name(name)) { + ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name); + errno = EINVAL; + return -1; + } + NOTICE("[API %s] renamed to [API %s]", export->apiname, name); + afb_export_rename(export, name); + return 0; +} + +/********************************************** +* hooked flow +**********************************************/ +static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +{ + struct afb_export *export = closure; + va_list ap; + va_copy(ap, args); + vverbose_cb(closure, level, file, line, function, fmt, args); + afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap); + va_end(ap); +} + +static void hooked_old_vverbose_cb(void *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 hooked_event_make_cb(void *closure, const char *name) +{ + struct afb_export *export = closure; + struct afb_event r = event_make_cb(closure, name); + return afb_hook_ditf_event_make(export, name, r); +} + +static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object) +{ + int r; + struct afb_export *export = closure; + json_object_get(object); + afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object)); + r = event_broadcast_cb(closure, name, object); + afb_hook_ditf_event_broadcast_after(export, name, object, r); + json_object_put(object); + return r; +} + +static struct sd_event *hooked_get_event_loop(void *closure) +{ + struct afb_export *export = closure; + struct sd_event *r = afb_common_get_event_loop(); + return afb_hook_ditf_get_event_loop(export, r); +} + +static struct sd_bus *hooked_get_user_bus(void *closure) +{ + struct afb_export *export = closure; + struct sd_bus *r = afb_common_get_user_bus(); + return afb_hook_ditf_get_user_bus(export, r); +} + +static struct sd_bus *hooked_get_system_bus(void *closure) +{ + struct afb_export *export = closure; + struct sd_bus *r = afb_common_get_system_bus(); + return afb_hook_ditf_get_system_bus(export, r); +} + +static int hooked_rootdir_get_fd(void *closure) +{ + struct afb_export *export = closure; + int r = afb_common_rootdir_get_fd(); + return afb_hook_ditf_rootdir_get_fd(export, r); +} + +static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale) +{ + struct afb_export *export = closure; + int r = rootdir_open_locale_cb(closure, filename, flags, locale); + return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r); +} + +static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) +{ + struct afb_export *export = closure; + int r = queue_job_cb(closure, callback, argument, group, timeout); + return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r); +} + +static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq) +{ + struct afb_export *export = closure; + afb_hook_ditf_unstore_req(export, sreq); + return unstore_req_cb(closure, sreq); +} + +static int hooked_require_api_cb(void *closure, const char *name, int initialized) +{ + int result; + struct afb_export *export = closure; + afb_hook_ditf_require_api(export, name, initialized); + result = require_api_cb(closure, name, initialized); + return afb_hook_ditf_require_api_result(export, name, initialized, result); +} + +static int hooked_rename_api_cb(void *closure, const char *name) +{ + struct afb_export *export = closure; + const char *oldname = export->apiname; + int result = rename_api_cb(closure, name); + return afb_hook_ditf_rename_api(export, oldname, name, result); +} + +/********************************************** +* vectors +**********************************************/ +static const struct afb_daemon_itf daemon_itf = { + .vverbose_v1 = old_vverbose_cb, + .vverbose_v2 = vverbose_cb, + .event_make = event_make_cb, + .event_broadcast = event_broadcast_cb, + .get_event_loop = afb_common_get_event_loop, + .get_user_bus = afb_common_get_user_bus, + .get_system_bus = afb_common_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 = unstore_req_cb, + .require_api = require_api_cb, + .rename_api = rename_api_cb +}; + +static const struct afb_daemon_itf hooked_daemon_itf = { + .vverbose_v1 = hooked_old_vverbose_cb, + .vverbose_v2 = hooked_vverbose_cb, + .event_make = hooked_event_make_cb, + .event_broadcast = hooked_event_broadcast_cb, + .get_event_loop = hooked_get_event_loop, + .get_user_bus = hooked_get_user_bus, + .get_system_bus = hooked_get_system_bus, + .rootdir_get_fd = hooked_rootdir_get_fd, + .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, + .rename_api = hooked_rename_api_cb +}; + + +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + F R O M S V C + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +/* the common session for services sharing their session */ +static struct afb_session *common_session; + +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + F R O M S V C + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +/* + * Structure for requests initiated by the service + */ +struct call_req +{ + struct afb_xreq xreq; + + struct afb_export *export; + + /* the args */ + void (*callback)(void*, int, struct json_object*); + void *closure; + + /* sync */ + struct jobloop *jobloop; + struct json_object *result; + int status; + int async; +}; + +/* + * destroys the call_req + */ +static void callreq_destroy(struct afb_xreq *xreq) +{ + struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq); + + afb_context_disconnect(&callreq->xreq.context); + json_object_put(callreq->xreq.json); + afb_cred_unref(callreq->xreq.cred); + free(callreq); +} + +static void callreq_reply(struct afb_xreq *xreq, int status, json_object *obj) +{ + struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq); + if (callreq->callback) + callreq->callback(callreq->closure, status, obj); + json_object_put(obj); +} + +static void callreq_sync_leave(struct call_req *callreq) +{ + struct jobloop *jobloop = callreq->jobloop; + + if (jobloop) { + callreq->jobloop = NULL; + jobs_leave(jobloop); + } +} + +static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj) +{ + struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq); + callreq->status = status; + callreq->result = obj; + callreq_sync_leave(callreq); +} + +static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop) +{ + struct call_req *callreq = closure; + + if (!signum) { + callreq->jobloop = jobloop; + afb_xreq_process(&callreq->xreq, callreq->export->apiset); + } else { + callreq->result = afb_msg_json_internal_error(); + callreq->status = -1; + callreq_sync_leave(callreq); + } +} + +/* interface for requests of services */ +const struct afb_xreq_query_itf afb_export_xreq_itf = { + .unref = callreq_destroy, + .reply = callreq_reply +}; + +/* interface for requests of services */ +const struct afb_xreq_query_itf afb_export_xreq_sync_itf = { + .unref = callreq_destroy, + .reply = callreq_reply_sync +}; + +/* + * create an call_req + */ +static struct call_req *callreq_create(struct afb_export *export, const char *api, const char *verb, struct json_object *args, const struct afb_xreq_query_itf *itf) +{ + struct call_req *callreq; + size_t lenapi, lenverb; + char *copy; + + /* allocates the request */ + lenapi = 1 + strlen(api); + lenverb = 1 + strlen(verb); + callreq = malloc(lenapi + lenverb + sizeof *callreq); + if (callreq != NULL) { + /* initialises the request */ + afb_xreq_init(&callreq->xreq, itf); + afb_context_init(&callreq->xreq.context, export->session, NULL); + callreq->xreq.context.validated = 1; + copy = (char*)&callreq[1]; + memcpy(copy, api, lenapi); + callreq->xreq.api = copy; + copy = ©[lenapi]; + memcpy(copy, verb, lenverb); + callreq->xreq.verb = copy; + callreq->xreq.listener = export->listener; + callreq->xreq.json = args; + callreq->export = export; + } + return callreq; +} + +/* + * Initiates a call for the service + */ +static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure) +{ + struct afb_export *export = closure; + struct call_req *callreq; + struct json_object *ierr; + + /* allocates the request */ + callreq = callreq_create(export, api, verb, args, &afb_export_xreq_itf); + if (callreq == NULL) { + ERROR("out of memory"); + json_object_put(args); + ierr = afb_msg_json_internal_error(); + if (callback) + callback(cbclosure, -1, ierr); + json_object_put(ierr); + return; + } + + /* initialises the request */ + callreq->jobloop = NULL; + callreq->callback = callback; + callreq->closure = cbclosure; + callreq->async = 1; + + /* terminates and frees ressources if needed */ + afb_xreq_process(&callreq->xreq, export->apiset); +} + +static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, + struct json_object **result) +{ + struct afb_export *export = closure; + struct call_req *callreq; + struct json_object *resu; + int rc; + + /* allocates the request */ + callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf); + if (callreq == NULL) { + ERROR("out of memory"); + errno = ENOMEM; + json_object_put(args); + resu = afb_msg_json_internal_error(); + rc = -1; + } else { + /* initialises the request */ + callreq->jobloop = NULL; + callreq->callback = NULL; + callreq->result = NULL; + callreq->status = 0; + callreq->async = 0; + afb_xreq_addref(&callreq->xreq); + rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq); + if (rc >= 0) + rc = callreq->status; + resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error(); + afb_xreq_unref(&callreq->xreq); + } + if (result) + *result = resu; + else + json_object_put(resu); + return rc; +} + +struct hooked_call +{ + struct afb_export *export; + void (*callback)(void*, int, struct json_object*); + void *cbclosure; +}; + +static void svc_hooked_call_result(void *closure, int status, struct json_object *result) +{ + struct hooked_call *hc = closure; + afb_hook_svc_call_result(hc->export, status, result); + hc->callback(hc->cbclosure, status, result); + free(hc); +} + +static void svc_hooked_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure) +{ + struct afb_export *export = closure; + struct hooked_call *hc; + + if (export->hooksvc & afb_hook_flag_svc_call) + afb_hook_svc_call(export, api, verb, args); + + if (export->hooksvc & afb_hook_flag_svc_call_result) { + hc = malloc(sizeof *hc); + if (!hc) + WARNING("allocation failed"); + else { + hc->export = export; + hc->callback = callback; + hc->cbclosure = cbclosure; + callback = svc_hooked_call_result; + cbclosure = hc; + } + } + svc_call(closure, api, verb, args, callback, cbclosure); +} + +static int svc_hooked_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, + struct json_object **result) +{ + struct afb_export *export = closure; + struct json_object *resu; + int rc; + + if (export->hooksvc & afb_hook_flag_svc_callsync) + afb_hook_svc_callsync(export, api, verb, args); + + rc = svc_call_sync(closure, api, verb, args, &resu); + + if (export->hooksvc & afb_hook_flag_svc_callsync_result) + afb_hook_svc_callsync_result(export, rc, resu); + + if (result) + *result = resu; + else + json_object_put(resu); + + return rc; +} + +/* the interface for services */ +static const struct afb_service_itf service_itf = { + .call = svc_call, + .call_sync = svc_call_sync +}; + +/* the interface for services */ +static const struct afb_service_itf hooked_service_itf = { + .call = svc_hooked_call, + .call_sync = svc_hooked_call_sync +}; + +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + F R O M S V C + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +/* + * Propagates the event to the service + */ +static void export_on_event(void *closure, const char *event, int eventid, struct json_object *object) +{ + struct afb_export *export = closure; + + if (export->hooksvc & afb_hook_flag_svc_on_event_before) + afb_hook_svc_on_event_before(export, event, eventid, object); + export->on_event(event, object); + if (export->hooksvc & afb_hook_flag_svc_on_event_after) + afb_hook_svc_on_event_after(export, event, eventid, object); + json_object_put(object); +} + +/* the interface for events */ +static const struct afb_evt_itf evt_itf = { + .broadcast = export_on_event, + .push = export_on_event +}; + +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + M E R G E D + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +static struct afb_export *create(const char *apiname, enum afb_api_version version) +{ + struct afb_export *export; + + /* session shared with other exports */ + if (common_session == NULL) { + common_session = afb_session_create (NULL, 0); + if (common_session == NULL) + return NULL; + } + export = calloc(1, sizeof *export); + if (!export) + errno = ENOMEM; + else { + memset(export, 0, sizeof *export); + export->apiname = strdup(apiname); + export->version = version; + export->state = Api_State_Pre_Init; + export->session = afb_session_addref(common_session); + export->apiset = afb_apiset_addref(main_apiset); + } + return export; +} + +void afb_export_destroy(struct afb_export *export) +{ + if (export) { + if (export->listener != NULL) + afb_evt_listener_unref(export->listener); + afb_session_unref(export->session); + afb_apiset_unref(export->apiset); + free(export->apiname); + free(export); + } +} + +struct afb_export *afb_export_create_v1(const char *apiname) +{ + struct afb_export *export = create(apiname, Api_Version_1); + if (export) { + export->export.v1.verbosity = verbosity; + export->export.v1.mode = AFB_MODE_LOCAL; + export->export.v1.daemon.closure = export; + afb_export_update_hook(export); + } + return export; +} + +struct afb_export *afb_export_create_v2(const char *apiname, struct afb_binding_data_v2 *data) +{ + struct afb_export *export = create(apiname, Api_Version_2); + if (export) { + export->export.v2 = data; + data->daemon.closure = export; + data->service.closure = export; + afb_export_update_hook(export); + } + return export; +} + +void afb_export_rename(struct afb_export *export, const char *apiname) +{ + free(export->apiname); + export->apiname = strdup(apiname); + afb_export_update_hook(export); +} + +const char *afb_export_apiname(const struct afb_export *export) +{ + return export->apiname; +} + +void afb_export_update_hook(struct afb_export *export) +{ + export->hookditf = afb_hook_flags_ditf(export->apiname); + export->hooksvc = afb_hook_flags_svc(export->apiname); + switch (export->version) { + case Api_Version_1: + export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf; + break; + default: + 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; + } +} + +struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export) +{ + return export->version == Api_Version_1 ? &export->export.v1 : NULL; +} + +int afb_export_unshare_session(struct afb_export *export) +{ + if (export->session == common_session) { + export->session = afb_session_create (NULL, 0); + if (export->session) + afb_session_unref(common_session); + else { + export->session = common_session; + return -1; + } + } + return 0; +} + +void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset) +{ + struct afb_apiset *prvset = export->apiset; + export->apiset = afb_apiset_addref(apiset); + afb_apiset_unref(prvset); +} + +/* + * Creates a new service + */ +int afb_export_handle_events(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object)) +{ + if (on_event != export->on_event) { + if (!on_event) { + afb_evt_listener_unref(export->listener); + export->listener = NULL; + } else if (!export->listener) { + export->listener = afb_evt_listener_create(&evt_itf, export); + if (export->listener == NULL) + return -1; + } + export->on_event = on_event; + } + return 0; +} + + + +int afb_export_is_started(const struct afb_export *export) +{ + return export->state != Api_State_Pre_Init; +} + + +/* + * Starts a new service (v1) + */ +struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*)) +{ + return regfun(&export->export.v1); + +} + +int afb_export_start_v1(struct afb_export *export, int (*start)(struct afb_service)) +{ + int rc; + struct afb_service svc = { .itf = &hooked_service_itf, .closure = export }; + + if (export->hooksvc & afb_hook_flag_svc_start_before) + afb_hook_svc_start_before(export); + export->state = Api_State_Init; + rc = start ? start(svc) : 0; + export->state = Api_State_Run; + if (export->hooksvc & afb_hook_flag_svc_start_after) + afb_hook_svc_start_after(export, rc); + return rc; +} + +/* + * Starts a new service (v2) + */ +int afb_export_start_v2(struct afb_export *export, int (*start)()) +{ + int rc; + + if (export->hooksvc & afb_hook_flag_svc_start_before) + afb_hook_svc_start_before(export); + export->state = Api_State_Init; + rc = start ? start() : 0; + export->state = Api_State_Run; + if (export->hooksvc & afb_hook_flag_svc_start_after) + afb_hook_svc_start_after(export, rc); + if (rc >= 0) + export->state = Api_State_Run; + return rc; +} + +int afb_export_verbosity_get(const struct afb_export *export) +{ + switch (export->version) { + case Api_Version_1: return export->export.v1.verbosity; + case Api_Version_2: return export->export.v2->verbosity; + } + return verbosity; +} + +void afb_export_verbosity_set(struct afb_export *export, int level) +{ + switch (export->version) { + case Api_Version_1: export->export.v1.verbosity = level; break; + case Api_Version_2: export->export.v2->verbosity = level; break; + } +} + diff --git a/src/afb-export.h b/src/afb-export.h new file mode 100644 index 00000000..96ccb938 --- /dev/null +++ b/src/afb-export.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author: José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +struct afb_export; +struct afb_apiset; + +struct afb_service; +struct afb_binding_data_v2; +struct afb_binding_interface_v1; + +extern struct afb_export *afb_export_create_v1(const char *apiname); +extern struct afb_export *afb_export_create_v2(const char *apiname, struct afb_binding_data_v2 *data); +extern void afb_export_destroy(struct afb_export *export); + +extern const char *afb_export_apiname(const struct afb_export *export); +extern void afb_export_rename(struct afb_export *export, const char *apiname); +extern void afb_export_update_hook(struct afb_export *export); + +extern int afb_export_unshare_session(struct afb_export *export); +extern void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset); + +extern int afb_export_is_started(const struct afb_export *export); +extern struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*)); +extern int afb_export_start_v1(struct afb_export *export, int (*start)(struct afb_service)); +extern int afb_export_start_v2(struct afb_export *export, int (*start)()); + +extern int afb_export_handle_events(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object)); + +extern int afb_export_verbosity_get(const struct afb_export *export); +extern void afb_export_verbosity_set(struct afb_export *export, int level); + diff --git a/src/afb-hook.c b/src/afb-hook.c index a1ecea6d..92a4c829 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -36,8 +36,7 @@ #include "afb-session.h" #include "afb-cred.h" #include "afb-xreq.h" -#include "afb-ditf.h" -#include "afb-svc.h" +#include "afb-export.h" #include "afb-evt.h" #include "verbose.h" @@ -56,7 +55,7 @@ struct afb_hook_xreq { }; /** - * Definition of a hook for ditf + * Definition of a hook for export */ struct afb_hook_ditf { struct afb_hook_ditf *next; /**< next hook */ @@ -68,7 +67,7 @@ struct afb_hook_ditf { }; /** - * Definition of a hook for svc + * Definition of a hook for export */ struct afb_hook_svc { struct afb_hook_svc *next; /**< next hook */ @@ -108,10 +107,10 @@ static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; /* list of hooks for xreq */ static struct afb_hook_xreq *list_of_xreq_hooks = NULL; -/* list of hooks for ditf */ +/* list of hooks for export */ static struct afb_hook_ditf *list_of_ditf_hooks = NULL; -/* list of hooks for svc */ +/* list of hooks for export */ static struct afb_hook_svc *list_of_svc_hooks = NULL; /* list of hooks for evt */ @@ -650,40 +649,40 @@ void afb_hook_unref_xreq(struct afb_hook_xreq *hook) * section: default callbacks for tracing daemon interface *****************************************************************************/ -static void _hook_ditf_(const struct afb_ditf *ditf, const char *format, ...) +static void _hook_ditf_(const struct afb_export *export, const char *format, ...) { va_list ap; va_start(ap, format); - _hook_("ditf-%s", format, ap, ditf->api); + _hook_("export-%s", format, ap, afb_export_apiname(export)); va_end(ap); } -static void hook_ditf_event_broadcast_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object) +static void hook_ditf_event_broadcast_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object) { - _hook_ditf_(ditf, "event_broadcast.before(%s, %s)....", name, json_object_to_json_string(object)); + _hook_ditf_(export, "event_broadcast.before(%s, %s)....", name, json_object_to_json_string(object)); } -static void hook_ditf_event_broadcast_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object, int result) +static void hook_ditf_event_broadcast_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result) { - _hook_ditf_(ditf, "event_broadcast.after(%s, %s) -> %d", name, json_object_to_json_string(object), result); + _hook_ditf_(export, "event_broadcast.after(%s, %s) -> %d", name, json_object_to_json_string(object), result); } -static void hook_ditf_get_event_loop_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_event *result) +static void hook_ditf_get_event_loop_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result) { - _hook_ditf_(ditf, "get_event_loop() -> %p", result); + _hook_ditf_(export, "get_event_loop() -> %p", result); } -static void hook_ditf_get_user_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result) +static void hook_ditf_get_user_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result) { - _hook_ditf_(ditf, "get_user_bus() -> %p", result); + _hook_ditf_(export, "get_user_bus() -> %p", result); } -static void hook_ditf_get_system_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result) +static void hook_ditf_get_system_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result) { - _hook_ditf_(ditf, "get_system_bus() -> %p", result); + _hook_ditf_(export, "get_system_bus() -> %p", result); } -static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args) { int len; char *msg; @@ -694,67 +693,67 @@ static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid va_end(ap); if (len < 0) - _hook_ditf_(ditf, "vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, function, fmt); + _hook_ditf_(export, "vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, function, fmt); else { - _hook_ditf_(ditf, "vverbose(%d, %s, %d, %s) -> %s", level, file, line, function, msg); + _hook_ditf_(export, "vverbose(%d, %s, %d, %s) -> %s", level, file, line, function, msg); free(msg); } } -static void hook_ditf_event_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct afb_event result) +static void hook_ditf_event_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event result) { - _hook_ditf_(ditf, "event_make(%s) -> %s:%d", name, afb_evt_event_name(result), afb_evt_event_id(result)); + _hook_ditf_(export, "event_make(%s) -> %s:%d", name, afb_evt_event_name(result), afb_evt_event_id(result)); } -static void hook_ditf_rootdir_get_fd_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int result) +static void hook_ditf_rootdir_get_fd_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result) { char path[PATH_MAX]; if (result < 0) - _hook_ditf_(ditf, "rootdir_get_fd() -> %d, %m", result); + _hook_ditf_(export, "rootdir_get_fd() -> %d, %m", result); else { sprintf(path, "/proc/self/fd/%d", result); readlink(path, path, sizeof path); - _hook_ditf_(ditf, "rootdir_get_fd() -> %d = %s", result, path); + _hook_ditf_(export, "rootdir_get_fd() -> %d = %s", result, path); } } -static void hook_ditf_rootdir_open_locale_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, int result) +static void hook_ditf_rootdir_open_locale_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result) { char path[PATH_MAX]; if (!locale) locale = "(null)"; if (result < 0) - _hook_ditf_(ditf, "rootdir_open_locale(%s, %d, %s) -> %d, %m", filename, flags, locale, result); + _hook_ditf_(export, "rootdir_open_locale(%s, %d, %s) -> %d, %m", filename, flags, locale, result); else { sprintf(path, "/proc/self/fd/%d", result); readlink(path, path, sizeof path); - _hook_ditf_(ditf, "rootdir_open_locale(%s, %d, %s) -> %d = %s", filename, flags, locale, result, path); + _hook_ditf_(export, "rootdir_open_locale(%s, %d, %s) -> %d = %s", filename, flags, locale, result, path); } } -static void hook_ditf_queue_job_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) +static void hook_ditf_queue_job_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) { - _hook_ditf_(ditf, "queue_job(%p, %p, %p, %d) -> %d", callback, argument, group, timeout, result); + _hook_ditf_(export, "queue_job(%p, %p, %p, %d) -> %d", callback, argument, group, timeout, result); } -static void hook_ditf_unstore_req_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct afb_stored_req *sreq) +static void hook_ditf_unstore_req_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq) { - _hook_ditf_(ditf, "unstore_req(%p)", sreq); + _hook_ditf_(export, "unstore_req(%p)", sreq); } -static void hook_ditf_require_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, int initialized) +static void hook_ditf_require_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized) { - _hook_ditf_(ditf, "require_api(%s, %d)...", name, initialized); + _hook_ditf_(export, "require_api(%s, %d)...", name, initialized); } -static void hook_ditf_require_api_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, int initialized, int result) +static void hook_ditf_require_api_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result) { - _hook_ditf_(ditf, "...require_api(%s, %d) -> %d", name, initialized, result); + _hook_ditf_(export, "...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) +static void hook_ditf_rename_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *oldname, const char *newname, int result) { - _hook_ditf_(ditf, "rename_api(%s -> %s) -> %d", oldname, newname, result); + _hook_ditf_(export, "rename_api(%s -> %s) -> %d", oldname, newname, result); } static struct afb_hook_ditf_itf hook_ditf_default_itf = { @@ -775,107 +774,108 @@ static struct afb_hook_ditf_itf hook_ditf_default_itf = { }; /****************************************************************************** - * section: hooks for tracing daemon interface (ditf) + * section: hooks for tracing daemon interface (export) *****************************************************************************/ #define _HOOK_DITF_(what,...) \ struct afb_hook_ditf *hook; \ struct afb_hookid hookid; \ + const char *apiname = afb_export_apiname(export); \ pthread_rwlock_rdlock(&rwlock); \ init_hookid(&hookid); \ hook = list_of_ditf_hooks; \ while (hook) { \ if (hook->itf->hook_ditf_##what \ && (hook->flags & afb_hook_flag_ditf_##what) != 0 \ - && (!hook->api || !strcasecmp(hook->api, ditf->api))) { \ + && (!hook->api || !strcasecmp(hook->api, apiname))) { \ hook->itf->hook_ditf_##what(hook->closure, &hookid, __VA_ARGS__); \ } \ hook = hook->next; \ } \ pthread_rwlock_unlock(&rwlock); -void afb_hook_ditf_event_broadcast_before(const struct afb_ditf *ditf, const char *name, struct json_object *object) +void afb_hook_ditf_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object) { - _HOOK_DITF_(event_broadcast_before, ditf, name, object); + _HOOK_DITF_(event_broadcast_before, export, name, object); } -int afb_hook_ditf_event_broadcast_after(const struct afb_ditf *ditf, const char *name, struct json_object *object, int result) +int afb_hook_ditf_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result) { - _HOOK_DITF_(event_broadcast_after, ditf, name, object, result); + _HOOK_DITF_(event_broadcast_after, export, name, object, result); return result; } -struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_ditf *ditf, struct sd_event *result) +struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_export *export, struct sd_event *result) { - _HOOK_DITF_(get_event_loop, ditf, result); + _HOOK_DITF_(get_event_loop, export, result); return result; } -struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_ditf *ditf, struct sd_bus *result) +struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_export *export, struct sd_bus *result) { - _HOOK_DITF_(get_user_bus, ditf, result); + _HOOK_DITF_(get_user_bus, export, result); return result; } -struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_ditf *ditf, struct sd_bus *result) +struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_export *export, struct sd_bus *result) { - _HOOK_DITF_(get_system_bus, ditf, result); + _HOOK_DITF_(get_system_bus, export, result); return result; } -void afb_hook_ditf_vverbose(const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +void afb_hook_ditf_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args) { - _HOOK_DITF_(vverbose, ditf, level, file, line, function, fmt, args); + _HOOK_DITF_(vverbose, export, level, file, line, function, fmt, args); } -struct afb_event afb_hook_ditf_event_make(const struct afb_ditf *ditf, const char *name, struct afb_event result) +struct afb_event afb_hook_ditf_event_make(const struct afb_export *export, const char *name, struct afb_event result) { - _HOOK_DITF_(event_make, ditf, name, result); + _HOOK_DITF_(event_make, export, name, result); return result; } -int afb_hook_ditf_rootdir_get_fd(const struct afb_ditf *ditf, int result) +int afb_hook_ditf_rootdir_get_fd(const struct afb_export *export, int result) { - _HOOK_DITF_(rootdir_get_fd, ditf, result); + _HOOK_DITF_(rootdir_get_fd, export, result); return result; } -int afb_hook_ditf_rootdir_open_locale(const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, int result) +int afb_hook_ditf_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result) { - _HOOK_DITF_(rootdir_open_locale, ditf, filename, flags, locale, result); + _HOOK_DITF_(rootdir_open_locale, export, filename, flags, locale, result); return result; } -int afb_hook_ditf_queue_job(const struct afb_ditf *ditf, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) +int afb_hook_ditf_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) { - _HOOK_DITF_(queue_job, ditf, callback, argument, group, timeout, result); + _HOOK_DITF_(queue_job, export, callback, argument, group, timeout, result); return result; } -void afb_hook_ditf_unstore_req(const struct afb_ditf *ditf, struct afb_stored_req *sreq) +void afb_hook_ditf_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq) { - _HOOK_DITF_(unstore_req, ditf, sreq); + _HOOK_DITF_(unstore_req, export, sreq); } -void afb_hook_ditf_require_api(const struct afb_ditf *ditf, const char *name, int initialized) +void afb_hook_ditf_require_api(const struct afb_export *export, const char *name, int initialized) { - _HOOK_DITF_(require_api, ditf, name, initialized); + _HOOK_DITF_(require_api, export, name, initialized); } -int afb_hook_ditf_require_api_result(const struct afb_ditf *ditf, const char *name, int initialized, int result) +int afb_hook_ditf_require_api_result(const struct afb_export *export, const char *name, int initialized, int result) { - _HOOK_DITF_(require_api_result, ditf, name, initialized, result); + _HOOK_DITF_(require_api_result, export, name, initialized, result); return result; } -int afb_hook_ditf_rename_api(const struct afb_ditf *ditf, const char *oldname, const char *newname, int result) +int afb_hook_ditf_rename_api(const struct afb_export *export, const char *oldname, const char *newname, int result) { - _HOOK_DITF_(rename_api, ditf, oldname, newname, result); + _HOOK_DITF_(rename_api, export, oldname, newname, result); return result; } /****************************************************************************** - * section: hooking ditf + * section: hooking export *****************************************************************************/ int afb_hook_flags_ditf(const char *api) @@ -961,55 +961,55 @@ void afb_hook_unref_ditf(struct afb_hook_ditf *hook) } /****************************************************************************** - * section: default callbacks for tracing service interface (svc) + * section: default callbacks for tracing service interface (export) *****************************************************************************/ -static void _hook_svc_(const struct afb_svc *svc, const char *format, ...) +static void _hook_svc_(const struct afb_export *export, const char *format, ...) { va_list ap; va_start(ap, format); - _hook_("svc-%s", format, ap, svc->api); + _hook_("export-%s", format, ap, afb_export_apiname(export)); va_end(ap); } -static void hook_svc_start_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc) +static void hook_svc_start_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export) { - _hook_svc_(svc, "start.before"); + _hook_svc_(export, "start.before"); } -static void hook_svc_start_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status) +static void hook_svc_start_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status) { - _hook_svc_(svc, "start.after -> %d", status); + _hook_svc_(export, "start.after -> %d", status); } -static void hook_svc_on_event_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +static void hook_svc_on_event_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - _hook_svc_(svc, "on_event.before(%s, %d, %s)", event, eventid, json_object_to_json_string(object)); + _hook_svc_(export, "on_event.before(%s, %d, %s)", event, eventid, json_object_to_json_string(object)); } -static void hook_svc_on_event_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +static void hook_svc_on_event_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - _hook_svc_(svc, "on_event.after(%s, %d, %s)", event, eventid, json_object_to_json_string(object)); + _hook_svc_(export, "on_event.after(%s, %d, %s)", event, eventid, json_object_to_json_string(object)); } -static void hook_svc_call_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +static void hook_svc_call_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - _hook_svc_(svc, "call(%s/%s, %s) ...", api, verb, json_object_to_json_string(args)); + _hook_svc_(export, "call(%s/%s, %s) ...", api, verb, json_object_to_json_string(args)); } -static void hook_svc_call_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result) +static void hook_svc_call_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result) { - _hook_svc_(svc, " ...call... -> %d: %s", status, json_object_to_json_string(result)); + _hook_svc_(export, " ...call... -> %d: %s", status, json_object_to_json_string(result)); } -static void hook_svc_callsync_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +static void hook_svc_callsync_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - _hook_svc_(svc, "callsync(%s/%s, %s) ...", api, verb, json_object_to_json_string(args)); + _hook_svc_(export, "callsync(%s/%s, %s) ...", api, verb, json_object_to_json_string(args)); } -static void hook_svc_callsync_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result) +static void hook_svc_callsync_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result) { - _hook_svc_(svc, " ...callsync... -> %d: %s", status, json_object_to_json_string(result)); + _hook_svc_(export, " ...callsync... -> %d: %s", status, json_object_to_json_string(result)); } static struct afb_hook_svc_itf hook_svc_default_itf = { @@ -1024,69 +1024,70 @@ static struct afb_hook_svc_itf hook_svc_default_itf = { }; /****************************************************************************** - * section: hooks for tracing service interface (svc) + * section: hooks for tracing service interface (export) *****************************************************************************/ #define _HOOK_SVC_(what,...) \ struct afb_hook_svc *hook; \ struct afb_hookid hookid; \ + const char *apiname = afb_export_apiname(export); \ pthread_rwlock_rdlock(&rwlock); \ init_hookid(&hookid); \ hook = list_of_svc_hooks; \ while (hook) { \ if (hook->itf->hook_svc_##what \ && (hook->flags & afb_hook_flag_svc_##what) != 0 \ - && (!hook->api || !strcasecmp(hook->api, svc->api))) { \ + && (!hook->api || !strcasecmp(hook->api, apiname))) { \ hook->itf->hook_svc_##what(hook->closure, &hookid, __VA_ARGS__); \ } \ hook = hook->next; \ } \ pthread_rwlock_unlock(&rwlock); -void afb_hook_svc_start_before(const struct afb_svc *svc) +void afb_hook_svc_start_before(const struct afb_export *export) { - _HOOK_SVC_(start_before, svc); + _HOOK_SVC_(start_before, export); } -int afb_hook_svc_start_after(const struct afb_svc *svc, int status) +int afb_hook_svc_start_after(const struct afb_export *export, int status) { - _HOOK_SVC_(start_after, svc, status); + _HOOK_SVC_(start_after, export, status); return status; } -void afb_hook_svc_on_event_before(const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +void afb_hook_svc_on_event_before(const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - _HOOK_SVC_(on_event_before, svc, event, eventid, object); + _HOOK_SVC_(on_event_before, export, event, eventid, object); } -void afb_hook_svc_on_event_after(const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +void afb_hook_svc_on_event_after(const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - _HOOK_SVC_(on_event_after, svc, event, eventid, object); + _HOOK_SVC_(on_event_after, export, event, eventid, object); } -void afb_hook_svc_call(const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +void afb_hook_svc_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - _HOOK_SVC_(call, svc, api, verb, args); + _HOOK_SVC_(call, export, api, verb, args); } -void afb_hook_svc_call_result(const struct afb_svc *svc, int status, struct json_object *result) +void afb_hook_svc_call_result(const struct afb_export *export, int status, struct json_object *result) { - _HOOK_SVC_(call_result, svc, status, result); + _HOOK_SVC_(call_result, export, status, result); } -void afb_hook_svc_callsync(const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +void afb_hook_svc_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - _HOOK_SVC_(callsync, svc, api, verb, args); + _HOOK_SVC_(callsync, export, api, verb, args); } -int afb_hook_svc_callsync_result(const struct afb_svc *svc, int status, struct json_object *result) +int afb_hook_svc_callsync_result(const struct afb_export *export, int status, struct json_object *result) { - _HOOK_SVC_(callsync_result, svc, status, result); + _HOOK_SVC_(callsync_result, export, status, result); return status; } /****************************************************************************** - * section: hooking services (svc) + * section: hooking services (export) *****************************************************************************/ int afb_hook_flags_svc(const char *api) diff --git a/src/afb-hook.h b/src/afb-hook.h index 6f54f703..a9c3894e 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -27,8 +27,7 @@ struct afb_arg; struct afb_event; struct afb_session; struct afb_xreq; -struct afb_ditf; -struct afb_svc; +struct afb_export; struct afb_stored_req; struct sd_bus; struct sd_event; @@ -160,7 +159,7 @@ extern void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int st extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result); /********************************************************* -* section hooking ditf (daemon interface) +* section hooking export (daemon interface) *********************************************************/ #define afb_hook_flag_ditf_vverbose 0x000001 @@ -196,36 +195,36 @@ extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char #define afb_hook_flags_ditf_all (afb_hook_flags_ditf_common|afb_hook_flags_ditf_extra) struct afb_hook_ditf_itf { - void (*hook_ditf_event_broadcast_before)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object); - void (*hook_ditf_event_broadcast_after)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object, int result); - void (*hook_ditf_get_event_loop)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_event *result); - void (*hook_ditf_get_user_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result); - void (*hook_ditf_get_system_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result); - void (*hook_ditf_vverbose)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args); - void (*hook_ditf_event_make)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct afb_event result); - void (*hook_ditf_rootdir_get_fd)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int result); - void (*hook_ditf_rootdir_open_locale)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, int result); - void (*hook_ditf_queue_job)(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result); - 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); + void (*hook_ditf_event_broadcast_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object); + void (*hook_ditf_event_broadcast_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result); + void (*hook_ditf_get_event_loop)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result); + void (*hook_ditf_get_user_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result); + void (*hook_ditf_get_system_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result); + void (*hook_ditf_vverbose)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args); + void (*hook_ditf_event_make)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event result); + void (*hook_ditf_rootdir_get_fd)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result); + void (*hook_ditf_rootdir_open_locale)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result); + void (*hook_ditf_queue_job)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result); + void (*hook_ditf_unstore_req)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq); + void (*hook_ditf_require_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized); + void (*hook_ditf_require_api_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result); + void (*hook_ditf_rename_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, 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); -extern int afb_hook_ditf_event_broadcast_after(const struct afb_ditf *ditf, const char *name, struct json_object *object, int result); -extern struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_ditf *ditf, struct sd_event *result); -extern struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_ditf *ditf, struct sd_bus *result); -extern struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_ditf *ditf, struct sd_bus *result); -extern void afb_hook_ditf_vverbose(const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args); -extern struct afb_event afb_hook_ditf_event_make(const struct afb_ditf *ditf, const char *name, struct afb_event result); -extern int afb_hook_ditf_rootdir_get_fd(const struct afb_ditf *ditf, int result); -extern int afb_hook_ditf_rootdir_open_locale(const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, int result); -extern int afb_hook_ditf_queue_job(const struct afb_ditf *ditf, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result); -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 void afb_hook_ditf_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object); +extern int afb_hook_ditf_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result); +extern struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_export *export, struct sd_event *result); +extern struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_export *export, struct sd_bus *result); +extern struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_export *export, struct sd_bus *result); +extern void afb_hook_ditf_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args); +extern struct afb_event afb_hook_ditf_event_make(const struct afb_export *export, const char *name, struct afb_event result); +extern int afb_hook_ditf_rootdir_get_fd(const struct afb_export *export, int result); +extern int afb_hook_ditf_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result); +extern int afb_hook_ditf_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result); +extern void afb_hook_ditf_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq); +extern void afb_hook_ditf_require_api(const struct afb_export *export, const char *name, int initialized); +extern int afb_hook_ditf_require_api_result(const struct afb_export *export, const char *name, int initialized, int result); +extern int afb_hook_ditf_rename_api(const struct afb_export *export, 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); @@ -233,7 +232,7 @@ extern struct afb_hook_ditf *afb_hook_addref_ditf(struct afb_hook_ditf *hook); extern void afb_hook_unref_ditf(struct afb_hook_ditf *hook); /********************************************************* -* section hooking svc (service interface) +* section hooking export (service interface) *********************************************************/ #define afb_hook_flag_svc_start_before 0x000001 @@ -251,24 +250,24 @@ extern void afb_hook_unref_ditf(struct afb_hook_ditf *hook); |afb_hook_flag_svc_callsync|afb_hook_flag_svc_callsync_result) struct afb_hook_svc_itf { - void (*hook_svc_start_before)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc); - void (*hook_svc_start_after)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status); - void (*hook_svc_on_event_before)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object); - void (*hook_svc_on_event_after)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object); - void (*hook_svc_call)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args); - void (*hook_svc_call_result)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result); - void (*hook_svc_callsync)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args); - void (*hook_svc_callsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result); + void (*hook_svc_start_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export); + void (*hook_svc_start_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status); + void (*hook_svc_on_event_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object); + void (*hook_svc_on_event_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object); + void (*hook_svc_call)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args); + void (*hook_svc_call_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result); + void (*hook_svc_callsync)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args); + void (*hook_svc_callsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result); }; -extern void afb_hook_svc_start_before(const struct afb_svc *svc); -extern int afb_hook_svc_start_after(const struct afb_svc *svc, int status); -extern void afb_hook_svc_on_event_before(const struct afb_svc *svc, const char *event, int eventid, struct json_object *object); -extern void afb_hook_svc_on_event_after(const struct afb_svc *svc, const char *event, int eventid, struct json_object *object); -extern void afb_hook_svc_call(const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args); -extern void afb_hook_svc_call_result(const struct afb_svc *svc, int status, struct json_object *result); -extern void afb_hook_svc_callsync(const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args); -extern int afb_hook_svc_callsync_result(const struct afb_svc *svc, int status, struct json_object *result); +extern void afb_hook_svc_start_before(const struct afb_export *export); +extern int afb_hook_svc_start_after(const struct afb_export *export, int status); +extern void afb_hook_svc_on_event_before(const struct afb_export *export, const char *event, int eventid, struct json_object *object); +extern void afb_hook_svc_on_event_after(const struct afb_export *export, const char *event, int eventid, struct json_object *object); +extern void afb_hook_svc_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args); +extern void afb_hook_svc_call_result(const struct afb_export *export, int status, struct json_object *result); +extern void afb_hook_svc_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args); +extern int afb_hook_svc_callsync_result(const struct afb_export *export, int status, struct json_object *result); extern int afb_hook_flags_svc(const char *api); extern struct afb_hook_svc *afb_hook_create_svc(const char *api, int flags, struct afb_hook_svc_itf *itf, void *closure); diff --git a/src/afb-monitor.c b/src/afb-monitor.c index 168b13de..4b1c0384 100644 --- a/src/afb-monitor.c +++ b/src/afb-monitor.c @@ -26,7 +26,6 @@ #include "afb-api.h" #include "afb-apiset.h" #include "afb-api-so-v2.h" -#include "afb-ditf.h" #include "afb-evt.h" #include "afb-xreq.h" #include "afb-trace.h" diff --git a/src/afb-svc.c b/src/afb-svc.c deleted file mode 100644 index 212ecfa3..00000000 --- a/src/afb-svc.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2016, 2017 "IoT.bzh" - * Author: José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE - -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include <json-c/json.h> - -#include <afb/afb-binding-v1.h> -#include <afb/afb-binding-v2.h> - -#include "afb-session.h" -#include "afb-context.h" -#include "afb-evt.h" -#include "afb-msg-json.h" -#include "afb-svc.h" -#include "afb-xreq.h" -#include "afb-cred.h" -#include "afb-apiset.h" -#include "afb-hook.h" -#include "jobs.h" -#include "verbose.h" - - -#define HOOK(x,...) if((svc)->hookflags & afb_hook_flag_svc_##x) afb_hook_svc_##x(__VA_ARGS__) - -/* - * Structure for requests initiated by the service - */ -struct svc_req -{ - struct afb_xreq xreq; - - struct afb_svc *svc; - - /* the args */ - void (*callback)(void*, int, struct json_object*); - void *closure; - - /* sync */ - struct jobloop *jobloop; - struct json_object *result; - int status; - int async; -}; - -/* functions for services */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object); -static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, - void (*callback)(void*, int, struct json_object*), void *cbclosure); -static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result); - -/* the interface for services */ -static const struct afb_service_itf service_itf = { - .call = svc_call, - .call_sync = svc_call_sync -}; - -/* the interface for events */ -static const struct afb_evt_itf evt_itf = { - .broadcast = svc_on_event, - .push = svc_on_event -}; - -/* functions for requests of services */ -static void svcreq_destroy(struct afb_xreq *xreq); -static void svcreq_reply(struct afb_xreq *xreq, int status, json_object *obj); - -/* interface for requests of services */ -const struct afb_xreq_query_itf afb_svc_xreq_itf = { - .unref = svcreq_destroy, - .reply = svcreq_reply -}; - -/* the common session for services sharing their session */ -static struct afb_session *common_session; - -static inline struct afb_service to_afb_service(struct afb_svc *svc) -{ - return (struct afb_service){ .itf = &service_itf, .closure = svc }; -} - -/* - * Frees a service - */ -void afb_svc_destroy(struct afb_svc *svc, struct afb_service *service) -{ - if (service) - *service = (struct afb_service){ .itf = NULL, .closure = NULL }; - if (svc) { - if (svc->listener != NULL) - afb_evt_listener_unref(svc->listener); - if (svc->session) - afb_session_unref(svc->session); - afb_apiset_unref(svc->apiset); - free(svc); - } -} - -/* - * Creates a new service - */ -struct afb_svc *afb_svc_create( - const char *api, - struct afb_apiset *apiset, - int share_session, - void (*on_event)(const char *event, struct json_object *object), - struct afb_service *service -) -{ - struct afb_svc *svc; - - /* allocates the svc handler */ - svc = calloc(1, sizeof * svc); - if (svc == NULL) { - errno = ENOMEM; - return NULL; - } - - /* instanciate the apiset */ - svc->api = api; - svc->apiset = afb_apiset_addref(apiset); - - /* instanciate the session */ - if (share_session) { - /* session shared with other svcs */ - if (common_session == NULL) { - common_session = afb_session_create (NULL, 0); - if (common_session == NULL) - goto error; - } - svc->session = afb_session_addref(common_session); - } else { - /* session dedicated to the svc */ - svc->session = afb_session_create (NULL, 0); - if (svc->session == NULL) - goto error; - } - - svc->hookflags = afb_hook_flags_svc(svc->api); - if (service) - *service = to_afb_service(svc); - - /* initialises the listener if needed */ - if (on_event) { - svc->on_event = on_event; - svc->listener = afb_evt_listener_create(&evt_itf, svc); - if (svc->listener == NULL) - goto error; - } - - return svc; - -error: - afb_svc_destroy(svc, service); - return NULL; -} - -/* - * Starts a new service (v1) - */ -int afb_svc_start_v1(struct afb_svc *svc, int (*start)(struct afb_service)) -{ - int rc; - - HOOK(start_before, svc); - rc = start(to_afb_service(svc)); - HOOK(start_after, svc, rc); - return rc; -} - -/* - * Starts a new service (v2) - */ -int afb_svc_start_v2(struct afb_svc *svc, int (*start)()) -{ - int rc; - - HOOK(start_before, svc); - rc = start(); - HOOK(start_after, svc, rc); - return rc; -} - -/* - * Request to updates the hooks - */ -void afb_svc_update_hook(struct afb_svc *svc) -{ - svc->hookflags = afb_hook_flags_svc(svc->api); -} - -/* - * Propagates the event to the service - */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object) -{ - struct afb_svc *svc = closure; - - HOOK(on_event_before, svc, event, eventid, object); - svc->on_event(event, object); - HOOK(on_event_after, svc, event, eventid, object); - json_object_put(object); -} - -/* - * create an svc_req - */ -static struct svc_req *svcreq_create(struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) -{ - struct svc_req *svcreq; - size_t lenapi, lenverb; - char *copy; - - /* allocates the request */ - lenapi = 1 + strlen(api); - lenverb = 1 + strlen(verb); - svcreq = malloc(lenapi + lenverb + sizeof *svcreq); - if (svcreq != NULL) { - /* initialises the request */ - afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf); - afb_context_init(&svcreq->xreq.context, svc->session, NULL); - svcreq->xreq.context.validated = 1; - copy = (char*)&svcreq[1]; - memcpy(copy, api, lenapi); - svcreq->xreq.api = copy; - copy = ©[lenapi]; - memcpy(copy, verb, lenverb); - svcreq->xreq.verb = copy; - svcreq->xreq.listener = svc->listener; - svcreq->xreq.json = args; - svcreq->svc = svc; - } - return svcreq; -} - -/* - * destroys the svc_req - */ -static void svcreq_destroy(struct afb_xreq *xreq) -{ - struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq); - - afb_context_disconnect(&svcreq->xreq.context); - json_object_put(svcreq->xreq.json); - afb_cred_unref(svcreq->xreq.cred); - free(svcreq); -} - -static void svcreq_sync_leave(struct svc_req *svcreq) -{ - struct jobloop *jobloop = svcreq->jobloop; - - if (jobloop) { - svcreq->jobloop = NULL; - jobs_leave(jobloop); - } -} - -static void svcreq_reply(struct afb_xreq *xreq, int status, json_object *obj) -{ - struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq); - if (svcreq->async) { - struct afb_svc *svc = svcreq->svc; - if (svcreq->callback) - svcreq->callback(svcreq->closure, status, obj); - HOOK(call_result, svc, status, obj); - json_object_put(obj); - } else { - svcreq->status = status; - svcreq->result = obj; - svcreq_sync_leave(svcreq); - } -} - -static void svcreq_sync_enter(int signum, void *closure, struct jobloop *jobloop) -{ - struct svc_req *svcreq = closure; - - if (!signum) { - svcreq->jobloop = jobloop; - afb_xreq_process(&svcreq->xreq, svcreq->svc->apiset); - } else { - svcreq->result = afb_msg_json_internal_error(); - svcreq->status = -1; - svcreq_sync_leave(svcreq); - } -} - -/* - * Initiates a call for the service - */ -static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure) -{ - struct afb_svc *svc = closure; - struct svc_req *svcreq; - struct json_object *ierr; - - HOOK(call, svc, api, verb, args); - - /* allocates the request */ - svcreq = svcreq_create(svc, api, verb, args); - if (svcreq == NULL) { - ERROR("out of memory"); - json_object_put(args); - ierr = afb_msg_json_internal_error(); - if (callback) - callback(cbclosure, -1, ierr); - HOOK(call_result, svc, -1, ierr); - json_object_put(ierr); - return; - } - - /* initialises the request */ - svcreq->jobloop = NULL; - svcreq->callback = callback; - svcreq->closure = cbclosure; - svcreq->async = 1; - - /* terminates and frees ressources if needed */ - afb_xreq_process(&svcreq->xreq, svc->apiset); -} - -static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result) -{ - struct afb_svc *svc = closure; - struct svc_req *svcreq; - struct json_object *resu; - int rc; - - HOOK(callsync, svc, api, verb, args); - - /* allocates the request */ - svcreq = svcreq_create(svc, api, verb, args); - if (svcreq == NULL) { - ERROR("out of memory"); - errno = ENOMEM; - json_object_put(args); - resu = afb_msg_json_internal_error(); - rc = -1; - } else { - /* initialises the request */ - svcreq->jobloop = NULL; - svcreq->callback = NULL; - svcreq->result = NULL; - svcreq->status = 0; - svcreq->async = 0; - afb_xreq_addref(&svcreq->xreq); - rc = jobs_enter(NULL, 0, svcreq_sync_enter, svcreq); - if (rc >= 0) - rc = svcreq->status; - resu = (rc >= 0 || svcreq->result) ? svcreq->result : afb_msg_json_internal_error(); - afb_xreq_unref(&svcreq->xreq); - } - HOOK(callsync_result, svc, rc, resu); - if (result) - *result = resu; - else - json_object_put(resu); - return rc; -} - diff --git a/src/afb-svc.h b/src/afb-svc.h deleted file mode 100644 index e23c2867..00000000 --- a/src/afb-svc.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2016, 2017 "IoT.bzh" - * Author: José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -struct afb_svc; -struct afb_service; -struct afb_session; -struct afb_apiset; -struct afb_evt_listener; -struct afb_binding_data_v2; - -struct json_object; - -/* - * Structure for recording service - */ -struct afb_svc -{ - /* api/prefix */ - const char *api; - - /* session of the service */ - struct afb_session *session; - - /* the apiset for the service */ - struct afb_apiset *apiset; - - /* event listener of the service or NULL */ - struct afb_evt_listener *listener; - - /* on event callback for the service */ - void (*on_event)(const char *event, struct json_object *object); - - /* hooking flags */ - int hookflags; -}; - -extern void afb_svc_destroy(struct afb_svc *svc, struct afb_service *service); - -extern struct afb_svc *afb_svc_create( - const char *api, - struct afb_apiset *apiset, - int share_session, - void (*on_event)(const char *event, struct json_object *object), - struct afb_service *service); - -extern int afb_svc_start_v1(struct afb_svc *svc, int (*start)(struct afb_service)); -extern int afb_svc_start_v2(struct afb_svc *svc, int (*start)()); - -extern void afb_svc_update_hook(struct afb_svc *svc); - diff --git a/src/afb-trace.c b/src/afb-trace.c index 8537081c..c581611b 100644 --- a/src/afb-trace.c +++ b/src/afb-trace.c @@ -33,8 +33,7 @@ #include "afb-cred.h" #include "afb-session.h" #include "afb-xreq.h" -#include "afb-ditf.h" -#include "afb-svc.h" +#include "afb-export.h" #include "afb-evt.h" #include "afb-trace.h" @@ -95,8 +94,8 @@ struct hook { enum trace_type { Trace_Type_Xreq, /* xreq hooks */ - Trace_Type_Ditf, /* ditf hooks */ - Trace_Type_Svc, /* svc hooks */ + Trace_Type_Ditf, /* export hooks */ + Trace_Type_Svc, /* export hooks */ Trace_Type_Evt, /* evt hooks */ Trace_Type_Global, /* global hooks */ Trace_Type_Count /* count of types of hooks */ @@ -506,52 +505,52 @@ static struct flag ditf_flags[] = { /* must be sorted by names */ { "vverbose", afb_hook_flag_ditf_vverbose }, }; -/* get the ditf value for flag of 'name' */ +/* get the export value for flag of 'name' */ static int get_ditf_flag(const char *name) { return get_flag(name, ditf_flags, (int)(sizeof ditf_flags / sizeof *ditf_flags)); } -static void hook_ditf(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *action, const char *format, ...) +static void hook_ditf(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...) { va_list ap; va_start(ap, format); emit(closure, hookid, "daemon", "{ss ss}", format, ap, - "api", ditf->api, + "api", afb_export_apiname(export), "action", action); va_end(ap); } -static void hook_ditf_event_broadcast_before(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object) +static void hook_ditf_event_broadcast_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object) { - hook_ditf(closure, hookid, ditf, "event_broadcast_before", "{ss sO*}", + hook_ditf(closure, hookid, export, "event_broadcast_before", "{ss sO*}", "name", name, "data", object); } -static void hook_ditf_event_broadcast_after(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct json_object *object, int result) +static void hook_ditf_event_broadcast_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result) { - hook_ditf(closure, hookid, ditf, "event_broadcast_after", "{ss sO* si}", + hook_ditf(closure, hookid, export, "event_broadcast_after", "{ss sO* si}", "name", name, "data", object, "result", result); } -static void hook_ditf_get_event_loop(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_event *result) +static void hook_ditf_get_event_loop(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result) { - hook_ditf(closure, hookid, ditf, "get_event_loop", NULL); + hook_ditf(closure, hookid, export, "get_event_loop", NULL); } -static void hook_ditf_get_user_bus(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result) +static void hook_ditf_get_user_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result) { - hook_ditf(closure, hookid, ditf, "get_user_bus", NULL); + hook_ditf(closure, hookid, export, "get_user_bus", NULL); } -static void hook_ditf_get_system_bus(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct sd_bus *result) +static void hook_ditf_get_system_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result) { - hook_ditf(closure, hookid, ditf, "get_system_bus", NULL); + hook_ditf(closure, hookid, export, "get_system_bus", NULL); } -static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args) { struct json_object *pos; int len; @@ -568,7 +567,7 @@ static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, c if (file) wrap_json_pack(&pos, "{ss si ss*}", "file", file, "line", line, "function", function); - hook_ditf(closure, hookid, ditf, "vverbose", "{si ss* ss? so*}", + hook_ditf(closure, hookid, export, "vverbose", "{si ss* ss? so*}", "level", level, "type", verbosity_level_name(level), len < 0 ? "format" : "message", len < 0 ? fmt : msg, @@ -577,13 +576,13 @@ static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, c free(msg); } -static void hook_ditf_event_make(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, struct afb_event result) +static void hook_ditf_event_make(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event result) { - hook_ditf(closure, hookid, ditf, "event_make", "{ss ss si}", + hook_ditf(closure, hookid, export, "event_make", "{ss ss si}", "name", name, "event", afb_evt_event_name(result), "id", afb_evt_event_id(result)); } -static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, int result) +static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result) { char path[PATH_MAX]; @@ -592,12 +591,12 @@ static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hoo readlink(path, path, sizeof path); } - hook_ditf(closure, hookid, ditf, "rootdir_get_fd", "{ss}", + hook_ditf(closure, hookid, export, "rootdir_get_fd", "{ss}", result < 0 ? "path" : "error", result < 0 ? strerror(errno) : path); } -static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, int result) +static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result) { char path[PATH_MAX]; @@ -606,7 +605,7 @@ static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid readlink(path, path, sizeof path); } - hook_ditf(closure, hookid, ditf, "rootdir_open_locale", "{ss si ss* ss}", + hook_ditf(closure, hookid, export, "rootdir_open_locale", "{ss si ss* ss}", "file", filename, "flags", flags, "locale", locale, @@ -614,24 +613,24 @@ static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid result < 0 ? strerror(errno) : path); } -static void hook_ditf_queue_job(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) +static void hook_ditf_queue_job(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result) { - hook_ditf(closure, hookid, ditf, "queue_job", "{ss}", "result", result); + hook_ditf(closure, hookid, export, "queue_job", "{ss}", "result", result); } -static void hook_ditf_unstore_req(void * closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, struct afb_stored_req *sreq) +static void hook_ditf_unstore_req(void * closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq) { - hook_ditf(closure, hookid, ditf, "unstore_req", NULL); + hook_ditf(closure, hookid, export, "unstore_req", NULL); } -static void hook_ditf_require_api(void *closure, const struct afb_hookid *hookid, const struct afb_ditf *ditf, const char *name, int initialized) +static void hook_ditf_require_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized) { - hook_ditf(closure, hookid, ditf, "require_api", "{ss sb}", "name", name, "initialized", initialized); + hook_ditf(closure, hookid, export, "require_api", "{ss sb}", "name", name, "initialized", initialized); } -static 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) +static void hook_ditf_require_api_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result) { - hook_ditf(closure, hookid, ditf, "require_api_result", "{ss sb si}", "name", name, "initialized", initialized, "result", result); + hook_ditf(closure, hookid, export, "require_api_result", "{ss sb si}", "name", name, "initialized", initialized, "result", result); } static struct afb_hook_ditf_itf hook_ditf_itf = { @@ -666,66 +665,66 @@ static struct flag svc_flags[] = { /* must be sorted by names */ { "start_before", afb_hook_flag_svc_start_before }, }; -/* get the svc value for flag of 'name' */ +/* get the export value for flag of 'name' */ static int get_svc_flag(const char *name) { return get_flag(name, svc_flags, (int)(sizeof svc_flags / sizeof *svc_flags)); } -static void hook_svc(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *action, const char *format, ...) +static void hook_svc(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...) { va_list ap; va_start(ap, format); emit(closure, hookid, "service", "{ss ss}", format, ap, - "api", svc->api, + "api", afb_export_apiname(export), "action", action); va_end(ap); } -static void hook_svc_start_before(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc) +static void hook_svc_start_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export) { - hook_svc(closure, hookid, svc, "start_before", NULL); + hook_svc(closure, hookid, export, "start_before", NULL); } -static void hook_svc_start_after(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status) +static void hook_svc_start_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status) { - hook_svc(closure, hookid, svc, "start_after", "{si}", "result", status); + hook_svc(closure, hookid, export, "start_after", "{si}", "result", status); } -static void hook_svc_on_event_before(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +static void hook_svc_on_event_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - hook_svc(closure, hookid, svc, "on_event_before", "{ss si sO*}", + hook_svc(closure, hookid, export, "on_event_before", "{ss si sO*}", "event", event, "id", eventid, "data", object); } -static void hook_svc_on_event_after(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *event, int eventid, struct json_object *object) +static void hook_svc_on_event_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object) { - hook_svc(closure, hookid, svc, "on_event_after", "{ss si sO*}", + hook_svc(closure, hookid, export, "on_event_after", "{ss si sO*}", "event", event, "id", eventid, "data", object); } -static void hook_svc_call(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +static void hook_svc_call(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - hook_svc(closure, hookid, svc, "call", "{ss ss sO*}", + hook_svc(closure, hookid, export, "call", "{ss ss sO*}", "api", api, "verb", verb, "args", args); } -static void hook_svc_call_result(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result) +static void hook_svc_call_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result) { - hook_svc(closure, hookid, svc, "call_result", "{si sO*}", + hook_svc(closure, hookid, export, "call_result", "{si sO*}", "status", status, "result", result); } -static void hook_svc_callsync(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) +static void hook_svc_callsync(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args) { - hook_svc(closure, hookid, svc, "callsync", "{ss ss sO*}", + hook_svc(closure, hookid, export, "callsync", "{ss ss sO*}", "api", api, "verb", verb, "args", args); } -static void hook_svc_callsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_svc *svc, int status, struct json_object *result) +static void hook_svc_callsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result) { - hook_svc(closure, hookid, svc, "callsync_result", "{si sO*}", + hook_svc(closure, hookid, export, "callsync_result", "{si sO*}", "status", status, "result", result); } |