X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-ditf.c;h=d3db9bb0721b198fde1126fbe8cd693cbd982ea0;hb=c65113c390a5337924729e21f74f45df8c109291;hp=3eedbdb80433e5f0fe7a0798039241fc47c85c28;hpb=59db7c73c9d98414be9edf7056d7afe025512b3e;p=src%2Fapp-framework-binder.git diff --git a/src/afb-ditf.c b/src/afb-ditf.c index 3eedbdb8..d3db9bb0 100644 --- a/src/afb-ditf.c +++ b/src/afb-ditf.c @@ -16,35 +16,47 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#include #include #include -#include +#include + +#include +#include #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 (vasprintf(&p, fmt, args) < 0) + if (!fmt || vasprintf(&p, fmt, args) < 0) vverbose(level, file, line, function, fmt, args); else { - verbose(level, file, line, function, "%s {binding %s}", p, ditf->prefix); + 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, "?", fmt, args); + vverbose_cb(closure, level, file, line, NULL, fmt, args); } static struct afb_event event_make_cb(void *closure, const char *name) @@ -53,11 +65,19 @@ static struct afb_event event_make_cb(void *closure, const char *name) 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->prefix); + plen = strlen(ditf->api); nlen = strlen(name); event = alloca(nlen + plen + 2); - memcpy(event, ditf->prefix, plen); + memcpy(event, ditf->api, plen); event[plen] = '/'; memcpy(event + plen + 1, name, nlen + 1); @@ -71,11 +91,19 @@ static int event_broadcast_cb(void *closure, const char *name, struct json_objec 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->prefix); + plen = strlen(ditf->api); nlen = strlen(name); event = alloca(nlen + plen + 2); - memcpy(event, ditf->prefix, plen); + memcpy(event, ditf->api, plen); event[plen] = '/'; memcpy(event + plen + 1, name, nlen + 1); @@ -88,28 +116,220 @@ static int rootdir_open_locale_cb(void *closure, const char *filename, int flags 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 = old_vverbose_cb, + .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 + .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(struct afb_ditf *ditf, const char *prefix) +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->interface.verbosity = verbosity; - ditf->interface.mode = AFB_MODE_LOCAL; - ditf->interface.daemon.itf = &daemon_itf; - ditf->interface.daemon.closure = ditf; - afb_ditf_rename(ditf, prefix); + 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 *prefix) +void afb_ditf_rename(struct afb_ditf *ditf, const char *api) { - ditf->prefix = prefix; + 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; + } }