diff options
author | José Bollo <jose.bollo@iot.bzh> | 2017-04-07 17:05:24 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2017-04-07 17:07:22 +0200 |
commit | b529ded85a3e50a1aa6529e870b2e2f43e377ca2 (patch) | |
tree | c46d606619ae77206b75b7eb7b599554b9d34408 | |
parent | 59db7c73c9d98414be9edf7056d7afe025512b3e (diff) |
Add hooking of daemon interface
Change-Id: I5840609f4300ade98412e8527ac5ce1f1e8c0c59
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | src/afb-api-dbus.c | 1 | ||||
-rw-r--r-- | src/afb-api-so-v1.c | 16 | ||||
-rw-r--r-- | src/afb-api-so-v2.c | 16 | ||||
-rw-r--r-- | src/afb-api-ws.c | 1 | ||||
-rw-r--r-- | src/afb-apis.c | 16 | ||||
-rw-r--r-- | src/afb-apis.h | 3 | ||||
-rw-r--r-- | src/afb-config.c | 17 | ||||
-rw-r--r-- | src/afb-config.h | 1 | ||||
-rw-r--r-- | src/afb-ditf.c | 100 | ||||
-rw-r--r-- | src/afb-ditf.h | 1 | ||||
-rw-r--r-- | src/afb-hook.c | 332 | ||||
-rw-r--r-- | src/afb-hook.h | 85 | ||||
-rw-r--r-- | src/main.c | 12 |
13 files changed, 542 insertions, 59 deletions
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c index dc5273a8..161c0941 100644 --- a/src/afb-api-dbus.c +++ b/src/afb-api-dbus.c @@ -616,6 +616,7 @@ int afb_api_dbus_add_client(const char *path) afb_api.closure = api; afb_api.call = api_dbus_client_call; afb_api.service_start = api_dbus_service_start; + afb_api.update_hooks = NULL; if (afb_apis_add(api->api, afb_api) < 0) goto error2; diff --git a/src/afb-api-so-v1.c b/src/afb-api-so-v1.c index f9c1ef38..cb61019c 100644 --- a/src/afb-api-so-v1.c +++ b/src/afb-api-so-v1.c @@ -115,10 +115,17 @@ static int service_start_cb(void *closure, int share_session, int onneed) return 0; } +static void update_hooks_cb(void *closure) +{ + struct api_so_v1 *desc = closure; + afb_ditf_update_hook(&desc->ditf); +} + int afb_api_so_v1_add(const char *path, void *handle) { struct api_so_v1 *desc; struct afb_binding *(*register_function) (const struct afb_binding_interface *interface); + struct afb_api afb_api; /* retrieves the register function */ register_function = dlsym(handle, afb_api_so_v1_register); @@ -169,10 +176,11 @@ int afb_api_so_v1_add(const char *path, void *handle) /* records the binding */ afb_ditf_rename(&desc->ditf, desc->binding->v1.prefix); - if (afb_apis_add(desc->binding->v1.prefix, (struct afb_api){ - .closure = desc, - .call = call_cb, - .service_start = service_start_cb }) < 0) { + afb_api.closure = desc; + afb_api.call = call_cb; + afb_api.service_start = service_start_cb; + afb_api.update_hooks = update_hooks_cb; + if (afb_apis_add(desc->binding->v1.prefix, afb_api) < 0) { ERROR("binding [%s] can't be registered...", path); goto error2; } diff --git a/src/afb-api-so-v2.c b/src/afb-api-so-v2.c index 7df83dd8..12b83aca 100644 --- a/src/afb-api-so-v2.c +++ b/src/afb-api-so-v2.c @@ -113,11 +113,18 @@ static int service_start_cb(void *closure, int share_session, int onneed) return 0; } +static void update_hooks_cb(void *closure) +{ + struct api_so_v2 *desc = closure; + afb_ditf_update_hook(&desc->ditf); +} + int afb_api_so_v2_add(const char *path, void *handle) { int rc; struct api_so_v2 *desc; struct afb_binding_v2 *binding; + struct afb_api afb_api; /* retrieves the register function */ binding = dlsym(handle, afb_api_so_v2_descriptor); @@ -169,10 +176,11 @@ int afb_api_so_v2_add(const char *path, void *handle) } /* records the binding */ - if (afb_apis_add(binding->api, (struct afb_api){ - .closure = desc, - .call = call_cb, - .service_start = service_start_cb }) < 0) { + afb_api.closure = desc; + afb_api.call = call_cb; + afb_api.service_start = service_start_cb; + afb_api.update_hooks = update_hooks_cb; + if (afb_apis_add(binding->api, afb_api) < 0) { ERROR("binding [%s] can't be registered...", path); goto error2; } diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c index 5c3dcd47..6995b2fa 100644 --- a/src/afb-api-ws.c +++ b/src/afb-api-ws.c @@ -879,6 +879,7 @@ int afb_api_ws_add_client(const char *path) afb_api.closure = api; afb_api.call = api_ws_client_call_cb; afb_api.service_start = api_ws_service_start_cb; + afb_api.update_hooks = NULL; if (afb_apis_add(api->api, afb_api) < 0) goto error3; diff --git a/src/afb-apis.c b/src/afb-apis.c index 1355894d..ba8e0ddc 100644 --- a/src/afb-apis.c +++ b/src/afb-apis.c @@ -293,3 +293,19 @@ void afb_apis_call(struct afb_xreq *xreq) } } +/** + * Ask to update the hook flags + */ +void afb_apis_update_hooks() +{ + const struct api_desc *i, *e; + + i = apis_array; + e = &apis_array[apis_count]; + while (i != e) { + if (i->api.update_hooks) + i->api.update_hooks(i->api.closure); + i++; + } +} + diff --git a/src/afb-apis.h b/src/afb-apis.h index dd3e6b6d..ce33de13 100644 --- a/src/afb-apis.h +++ b/src/afb-apis.h @@ -26,6 +26,7 @@ struct afb_api void *closure; void (*call)(void *closure, struct afb_xreq *xreq); int (*service_start)(void *closure, int share_session, int onneed); + void (*update_hooks)(void *closure); }; extern void afb_apis_set_timeout(int to); @@ -40,4 +41,4 @@ extern int afb_apis_start_service(const char *name, int share_session, int onnee extern void afb_apis_call(struct afb_xreq *xreq); extern void afb_apis_call_direct(struct afb_xreq *xreq); - +extern void afb_apis_update_hooks(); diff --git a/src/afb-config.c b/src/afb-config.c index b06f01db..347198da 100644 --- a/src/afb-config.c +++ b/src/afb-config.c @@ -85,6 +85,7 @@ #define SET_NO_HTTPD 28 +#define SET_TRACEDITF 'D' #define SET_EXEC 'e' #define DISPLAY_HELP 'h' #define SET_QUIET 'q' @@ -96,7 +97,7 @@ #define SET_VERBOSE 'v' #define SET_WORK_DIR 'w' -#define SHORTOPTS "ehqrT:t:u:Vvw:" +#define SHORTOPTS "D:ehqrT:t:u:Vvw:" // Command line structure hold cli --command + help text typedef struct { @@ -149,6 +150,7 @@ static AFB_options cliOptions[] = { {SET_SESSIONMAX, 1, "session-max", "Max count of session simultaneously [default 10]"}, {SET_TRACEREQ, 1, "tracereq", "Log the requests: no, common, extra, all"}, + {SET_TRACEDITF, 1, "traceditf", "Log the requests: no, common, extra, all"}, {SET_NO_HTTPD, 0, "no-httpd", "Forbids HTTP service"}, {SET_EXEC, 0, "exec", "Execute the remaining arguments"}, @@ -172,6 +174,14 @@ static struct enumdesc tracereq_desc[] = { { NULL, 0 } }; +static struct enumdesc traceditf_desc[] = { + { "no", 0 }, + { "common", afb_hook_flags_ditf_common }, + { "extra", afb_hook_flags_ditf_extra }, + { "all", afb_hook_flags_ditf_all }, + { NULL, 0 } +}; + static struct enumdesc mode_desc[] = { { "local", AFB_MODE_LOCAL }, { "remote", AFB_MODE_REMOTE }, @@ -486,6 +496,10 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config) config->tracereq = argvalenum(optc, tracereq_desc); break; + case SET_TRACEDITF: + config->traceditf = argvalenum(optc, traceditf_desc); + break; + case SET_NO_HTTPD: noarg(optc); config->noHttpd = 1; @@ -617,6 +631,7 @@ void afb_config_dump(struct afb_config *config) D(nbSessionMax) E(mode,mode_desc) E(tracereq,tracereq_desc) + E(traceditf,traceditf_desc) B(noHttpd) P("---END-OF-CONFIG---\n"); diff --git a/src/afb-config.h b/src/afb-config.h index 09be2165..4c9f6241 100644 --- a/src/afb-config.h +++ b/src/afb-config.h @@ -54,6 +54,7 @@ struct afb_config { int nbSessionMax; // max count of sessions int mode; // mode of listening int tracereq; + int traceditf; int noHttpd; }; diff --git a/src/afb-ditf.c b/src/afb-ditf.c index 3eedbdb8..012ef029 100644 --- a/src/afb-ditf.c +++ b/src/afb-ditf.c @@ -21,14 +21,19 @@ #include <string.h> #include <errno.h> +#include <json-c/json.h> + #include <afb/afb-binding.h> #include "afb-ditf.h" #include "afb-evt.h" #include "afb-common.h" +#include "afb-hook.h" #include "verbose.h" - +/********************************************** +* 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; @@ -88,6 +93,78 @@ static int rootdir_open_locale_cb(void *closure, const char *filename, int flags return afb_common_rootdir_open_locale(filename, flags, locale); } +/********************************************** +* 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; + vverbose_cb(closure, level, file, line, function, fmt, args); + afb_hook_ditf_vverbose(ditf, level, file, line, function, fmt, args); + vverbose_cb(closure, level, file, line, function, fmt, args); +} + +static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args) +{ + struct afb_ditf *ditf = closure; + old_vverbose_cb(closure, level, file, line, fmt, args); + afb_hook_ditf_vverbose(ditf, level, file, line, "", 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 const struct afb_daemon_itf daemon_itf = { .vverbose = old_vverbose_cb, .event_make = event_make_cb, @@ -99,11 +176,21 @@ static const struct afb_daemon_itf daemon_itf = { .rootdir_open_locale = rootdir_open_locale_cb }; +static const struct afb_daemon_itf hooked_daemon_itf = { + .vverbose = hooked_old_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 +}; + void afb_ditf_init(struct afb_ditf *ditf, const char *prefix) { 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); } @@ -111,5 +198,14 @@ void afb_ditf_init(struct afb_ditf *ditf, const char *prefix) void afb_ditf_rename(struct afb_ditf *ditf, const char *prefix) { ditf->prefix = prefix; + afb_ditf_update_hook(ditf); +} + +void afb_ditf_update_hook(struct afb_ditf *ditf) +{ + if (afb_hook_flags_ditf(ditf->prefix)) + ditf->interface.daemon.itf = &hooked_daemon_itf; + else + ditf->interface.daemon.itf = &daemon_itf; } diff --git a/src/afb-ditf.h b/src/afb-ditf.h index 7d56c604..ad8c9920 100644 --- a/src/afb-ditf.h +++ b/src/afb-ditf.h @@ -44,4 +44,5 @@ struct afb_ditf extern void afb_ditf_init(struct afb_ditf *ditf, const char *prefix); extern void afb_ditf_rename(struct afb_ditf *ditf, const char *prefix); +extern void afb_ditf_update_hook(struct afb_ditf *ditf); diff --git a/src/afb-hook.c b/src/afb-hook.c index bafbbe90..2e0255d0 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -17,10 +17,12 @@ #define _GNU_SOURCE +#include <limits.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #include <pthread.h> +#include <unistd.h> #include <json-c/json.h> @@ -31,36 +33,43 @@ #include "afb-hook.h" #include "afb-session.h" #include "afb-xreq.h" +#include "afb-ditf.h" #include "verbose.h" /** - * Definition of a hook + * Definition of a hook for xreq */ -struct afb_hook { - struct afb_hook *next; /**< next hook */ +struct afb_hook_xreq { + struct afb_hook_xreq *next; /**< next hook */ unsigned refcount; /**< reference count */ char *api; /**< api hooked or NULL for any */ char *verb; /**< verb hooked or NULL for any */ struct afb_session *session; /**< session hooked or NULL if any */ unsigned flags; /**< hook flags */ - struct afb_hook_xreq_itf *reqitf; /**< interface of hook */ + struct afb_hook_xreq_itf *itf; /**< interface of hook */ void *closure; /**< closure for callbacks */ }; -/* - * Structure for handling subcalls callbacks +/** + * Definition of a hook for ditf */ -struct hook_subcall { - struct afb_xreq *xreq; /* hookd request */ - void (*callback)(void*, int, struct json_object*); /* client callback */ - void *cb_closure; /* cient closure */ +struct afb_hook_ditf { + struct afb_hook_ditf *next; /**< next hook */ + unsigned refcount; /**< reference count */ + char *api; /**< api hooked or NULL for any */ + unsigned flags; /**< hook flags */ + struct afb_hook_ditf_itf *itf; /**< interface of hook */ + void *closure; /**< closure for callbacks */ }; /* synchronisation across threads */ static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; -/* list of hooks */ -static struct afb_hook *list_of_hooks = NULL; +/* list of hooks for xreq */ +static struct afb_hook_xreq *list_of_xreq_hooks = NULL; + +/* list of hooks for ditf */ +static struct afb_hook_ditf *list_of_ditf_hooks = NULL; /****************************************************************************** * section: default callbacks for tracing requests @@ -212,16 +221,16 @@ static struct afb_hook_xreq_itf hook_xreq_default_itf = { *****************************************************************************/ #define _HOOK_XREQ_(what,...) \ - struct afb_hook *hook; \ + struct afb_hook_xreq *hook; \ pthread_rwlock_rdlock(&rwlock); \ - hook = list_of_hooks; \ + hook = list_of_xreq_hooks; \ while (hook) { \ - if (hook->reqitf->hook_xreq_##what \ + if (hook->itf->hook_xreq_##what \ && (hook->flags & afb_hook_flag_req_##what) != 0 \ && (!hook->session || hook->session == xreq->context.session) \ && (!hook->api || !strcasecmp(hook->api, xreq->api)) \ && (!hook->verb || !strcasecmp(hook->verb, xreq->verb))) { \ - hook->reqitf->hook_xreq_##what(hook->closure, __VA_ARGS__); \ + hook->itf->hook_xreq_##what(hook->closure, __VA_ARGS__); \ } \ hook = hook->next; \ } \ @@ -346,12 +355,12 @@ void afb_hook_init_xreq(struct afb_xreq *xreq) int f, flags; int add; - struct afb_hook *hook; + struct afb_hook_xreq *hook; /* scan hook list to get the expected flags */ flags = 0; pthread_rwlock_rdlock(&rwlock); - hook = list_of_hooks; + hook = list_of_xreq_hooks; while (hook) { f = hook->flags & afb_hook_flags_req_all; add = f != 0 @@ -375,12 +384,12 @@ void afb_hook_init_xreq(struct afb_xreq *xreq) } } -struct afb_hook *afb_hook_xreq_create(const char *api, const char *verb, struct afb_session *session, unsigned flags, struct afb_hook_xreq_itf *itf, void *closure) +struct afb_hook_xreq *afb_hook_create_xreq(const char *api, const char *verb, struct afb_session *session, int flags, struct afb_hook_xreq_itf *itf, void *closure) { - struct afb_hook *hook; + struct afb_hook_xreq *hook; /* alloc the result */ - hook = malloc(sizeof *hook); + hook = calloc(1, sizeof *hook); if (hook == NULL) return NULL; @@ -400,20 +409,20 @@ struct afb_hook *afb_hook_xreq_create(const char *api, const char *verb, struct afb_session_addref(session); hook->refcount = 1; hook->flags = flags; - hook->reqitf = itf ? itf : &hook_xreq_default_itf; + hook->itf = itf ? itf : &hook_xreq_default_itf; hook->closure = closure; /* record the hook */ pthread_rwlock_wrlock(&rwlock); - hook->next = list_of_hooks; - list_of_hooks = hook; + hook->next = list_of_xreq_hooks; + list_of_xreq_hooks = hook; pthread_rwlock_unlock(&rwlock); /* returns it */ return hook; } -struct afb_hook *afb_hook_addref(struct afb_hook *hook) +struct afb_hook_xreq *afb_hook_addref_xreq(struct afb_hook_xreq *hook) { pthread_rwlock_wrlock(&rwlock); hook->refcount++; @@ -421,9 +430,9 @@ struct afb_hook *afb_hook_addref(struct afb_hook *hook) return hook; } -void afb_hook_unref(struct afb_hook *hook) +void afb_hook_unref_xreq(struct afb_hook_xreq *hook) { - struct afb_hook **prv; + struct afb_hook_xreq **prv; if (hook) { pthread_rwlock_wrlock(&rwlock); @@ -431,7 +440,7 @@ void afb_hook_unref(struct afb_hook *hook) hook = NULL; else { /* unlink */ - prv = &list_of_hooks; + prv = &list_of_xreq_hooks; while (*prv && *prv != hook) prv = &(*prv)->next; if(*prv) @@ -449,3 +458,270 @@ void afb_hook_unref(struct afb_hook *hook) } } +/****************************************************************************** + * section: default callbacks for tracing daemon interface + *****************************************************************************/ + +static void _hook_ditf_(const struct afb_ditf *ditf, const char *format, ...) +{ + int len; + char *buffer; + va_list ap; + + va_start(ap, format); + len = vasprintf(&buffer, format, ap); + va_end(ap); + + if (len < 0) + NOTICE("hook ditf-%s allocation error for %s", ditf->prefix, format); + else { + NOTICE("hook ditf-%s %s", ditf->prefix, buffer); + free(buffer); + } +} + +static void hook_ditf_event_broadcast_before_cb(void *closure, const struct afb_ditf *ditf, const char *name, struct json_object *object) +{ + _hook_ditf_(ditf, "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_ditf *ditf, 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); +} + +static void hook_ditf_get_event_loop_cb(void *closure, const struct afb_ditf *ditf, struct sd_event *result) +{ + _hook_ditf_(ditf, "get_event_loop() -> %p", result); +} + +static void hook_ditf_get_user_bus_cb(void *closure, const struct afb_ditf *ditf, struct sd_bus *result) +{ + _hook_ditf_(ditf, "get_user_bus() -> %p", result); +} + +static void hook_ditf_get_system_bus_cb(void *closure, const struct afb_ditf *ditf, struct sd_bus *result) +{ + _hook_ditf_(ditf, "get_system_bus() -> %p", result); +} + +static void hook_ditf_vverbose_cb(void*closure, const struct afb_ditf *ditf, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +{ + int len; + char *msg; + va_list ap; + + va_copy(ap, args); + len = vasprintf(&msg, fmt, ap); + va_end(ap); + + if (len < 0) + _hook_ditf_(ditf, "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); + free(msg); + } +} + +static void hook_ditf_event_make_cb(void *closure, const struct afb_ditf *ditf, const char *name, struct afb_event result) +{ + _hook_ditf_(ditf, "event_make(%s) -> %s:%p", name, afb_event_name(result), result.closure); +} + +static void hook_ditf_rootdir_get_fd_cb(void *closure, const struct afb_ditf *ditf, int result) +{ + char path[PATH_MAX]; + if (result < 0) + _hook_ditf_(ditf, "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); + } +} + +static void hook_ditf_rootdir_open_locale_cb(void *closure, const struct afb_ditf *ditf, 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); + 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); + } +} + + +static struct afb_hook_ditf_itf hook_ditf_default_itf = { + .hook_ditf_event_broadcast_before = hook_ditf_event_broadcast_before_cb, + .hook_ditf_event_broadcast_after = hook_ditf_event_broadcast_after_cb, + .hook_ditf_get_event_loop = hook_ditf_get_event_loop_cb, + .hook_ditf_get_user_bus = hook_ditf_get_user_bus_cb, + .hook_ditf_get_system_bus = hook_ditf_get_system_bus_cb, + .hook_ditf_vverbose = hook_ditf_vverbose_cb, + .hook_ditf_event_make = hook_ditf_event_make_cb, + .hook_ditf_rootdir_get_fd = hook_ditf_rootdir_get_fd_cb, + .hook_ditf_rootdir_open_locale = hook_ditf_rootdir_open_locale_cb, +}; + +/****************************************************************************** + * section: hooks for tracing requests + *****************************************************************************/ + +#define _HOOK_DITF_(what,...) \ + struct afb_hook_ditf *hook; \ + pthread_rwlock_rdlock(&rwlock); \ + 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->prefix))) { \ + hook->itf->hook_ditf_##what(hook->closure, __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) +{ + _HOOK_DITF_(event_broadcast_before, ditf, name, object); +} + +int afb_hook_ditf_event_broadcast_after(const struct afb_ditf *ditf, const char *name, struct json_object *object, int result) +{ + _HOOK_DITF_(event_broadcast_after, ditf, name, object, result); + return result; +} + +struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_ditf *ditf, struct sd_event *result) +{ + _HOOK_DITF_(get_event_loop, ditf, result); + return result; +} + +struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_ditf *ditf, struct sd_bus *result) +{ + _HOOK_DITF_(get_user_bus, ditf, result); + return result; +} + +struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_ditf *ditf, struct sd_bus *result) +{ + _HOOK_DITF_(get_system_bus, ditf, 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) +{ + _HOOK_DITF_(vverbose, ditf, 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) +{ + _HOOK_DITF_(event_make, ditf, name, result); + return result; +} + +int afb_hook_ditf_rootdir_get_fd(const struct afb_ditf *ditf, int result) +{ + _HOOK_DITF_(rootdir_get_fd, ditf, 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) +{ + _HOOK_DITF_(rootdir_open_locale, ditf, filename, flags, locale, result); + return result; +} + + + +/****************************************************************************** + * section: + *****************************************************************************/ + +int afb_hook_flags_ditf(const char *api) +{ + int flags; + struct afb_hook_ditf *hook; + + pthread_rwlock_rdlock(&rwlock); + flags = 0; + hook = list_of_ditf_hooks; + while (hook) { + if (!api || !hook->api || !strcasecmp(hook->api, api)) + flags |= hook->flags; + hook = hook->next; + } + pthread_rwlock_unlock(&rwlock); + return flags; +} + +struct afb_hook_ditf *afb_hook_create_ditf(const char *api, int flags, struct afb_hook_ditf_itf *itf, void *closure) +{ + struct afb_hook_ditf *hook; + + /* alloc the result */ + hook = calloc(1, sizeof *hook); + if (hook == NULL) + return NULL; + + /* get a copy of the names */ + hook->api = api ? strdup(api) : NULL; + if (api && !hook->api) { + free(hook); + return NULL; + } + + /* initialise the rest */ + hook->refcount = 1; + hook->flags = flags; + hook->itf = itf ? itf : &hook_ditf_default_itf; + hook->closure = closure; + + /* record the hook */ + pthread_rwlock_wrlock(&rwlock); + hook->next = list_of_ditf_hooks; + list_of_ditf_hooks = hook; + pthread_rwlock_unlock(&rwlock); + + /* returns it */ + return hook; +} + +struct afb_hook_ditf *afb_hook_addref_ditf(struct afb_hook_ditf *hook) +{ + pthread_rwlock_wrlock(&rwlock); + hook->refcount++; + pthread_rwlock_unlock(&rwlock); + return hook; +} + +void afb_hook_unref_ditf(struct afb_hook_ditf *hook) +{ + struct afb_hook_ditf **prv; + + if (hook) { + pthread_rwlock_wrlock(&rwlock); + if (--hook->refcount) + hook = NULL; + else { + /* unlink */ + prv = &list_of_ditf_hooks; + while (*prv && *prv != hook) + prv = &(*prv)->next; + if(*prv) + *prv = hook->next; + } + pthread_rwlock_unlock(&rwlock); + if (hook) { + /* free */ + free(hook->api); + free(hook); + } + } +} + diff --git a/src/afb-hook.h b/src/afb-hook.h index 53804d40..46dd55b4 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -17,6 +17,22 @@ #pragma once +struct req; +struct afb_context; +struct json_object; +struct afb_arg; +struct afb_event; +struct afb_session; +struct afb_xreq; +struct afb_ditf; +struct sd_bus; +struct sd_event; + +/********************************************************* +* section hooking xreq +*********************************************************/ +struct afb_hook_xreq; + /* individual flags */ #define afb_hook_flag_req_begin 0x000001 #define afb_hook_flag_req_end 0x000002 @@ -61,16 +77,6 @@ #define afb_hook_flags_req_extra (afb_hook_flags_req_common|afb_hook_flags_req_ref|afb_hook_flags_req_context) #define afb_hook_flags_req_all (afb_hook_flags_req_extra|afb_hook_flags_req_internal) -struct req; -struct afb_context; -struct json_object; -struct afb_arg; -struct afb_event; -struct afb_session; -struct afb_xreq; - -struct afb_hook; - struct afb_hook_xreq_itf { void (*hook_xreq_begin)(void * closure, const struct afb_xreq *xreq); void (*hook_xreq_end)(void * closure, const struct afb_xreq *xreq); @@ -96,9 +102,9 @@ struct afb_hook_xreq_itf { extern void afb_hook_init_xreq(struct afb_xreq *xreq); -extern struct afb_hook *afb_hook_xreq_create(const char *api, const char *verb, struct afb_session *session, unsigned flags, struct afb_hook_xreq_itf *itf, void *closure); -extern struct afb_hook *afb_hook_addref(struct afb_hook *spec); -extern void afb_hook_unref(struct afb_hook *spec); +extern struct afb_hook_xreq *afb_hook_create_xreq(const char *api, const char *verb, struct afb_session *session, int flags, struct afb_hook_xreq_itf *itf, void *closure); +extern struct afb_hook_xreq *afb_hook_addref_xreq(struct afb_hook_xreq *spec); +extern void afb_hook_unref_xreq(struct afb_hook_xreq *spec); /* hooks for xreq */ extern void afb_hook_xreq_begin(const struct afb_xreq *xreq); @@ -122,3 +128,56 @@ extern void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, int status extern void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args); extern int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *result); +/********************************************************* +* section hooking ditf +*********************************************************/ + +#define afb_hook_flag_ditf_vverbose 0x000001 +#define afb_hook_flag_ditf_event_make 0x000002 +#define afb_hook_flag_ditf_event_broadcast_before 0x000004 +#define afb_hook_flag_ditf_event_broadcast_after 0x000008 +#define afb_hook_flag_ditf_get_event_loop 0x000010 +#define afb_hook_flag_ditf_get_user_bus 0x000020 +#define afb_hook_flag_ditf_get_system_bus 0x000040 +#define afb_hook_flag_ditf_rootdir_get_fd 0x000080 +#define afb_hook_flag_ditf_rootdir_open_locale 0x000100 + +#define afb_hook_flags_ditf_common (afb_hook_flag_ditf_vverbose\ + |afb_hook_flag_ditf_event_make\ + |afb_hook_flag_ditf_event_broadcast_before\ + |afb_hook_flag_ditf_event_broadcast_after) +#define afb_hook_flags_ditf_extra (afb_hook_flag_ditf_get_event_loop\ + |afb_hook_flag_ditf_get_user_bus\ + |afb_hook_flag_ditf_get_system_bus\ + |afb_hook_flag_ditf_rootdir_get_fd\ + |afb_hook_flag_ditf_rootdir_open_locale) + +#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_ditf *ditf, const char *name, struct json_object *object); + void (*hook_ditf_event_broadcast_after)(void *closure, 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_ditf *ditf, struct sd_event *result); + void (*hook_ditf_get_user_bus)(void *closure, const struct afb_ditf *ditf, struct sd_bus *result); + void (*hook_ditf_get_system_bus)(void *closure, const struct afb_ditf *ditf, struct sd_bus *result); + void (*hook_ditf_vverbose)(void*closure, 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_ditf *ditf, const char *name, struct afb_event result); + void (*hook_ditf_rootdir_get_fd)(void *closure, const struct afb_ditf *ditf, int result); + void (*hook_ditf_rootdir_open_locale)(void *closure, const struct afb_ditf *ditf, const char *filename, int flags, const char *locale, 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_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); +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); + @@ -411,6 +411,12 @@ static void start() goto error; } + /* install hooks */ + if (config->tracereq) + afb_hook_create_xreq(NULL, NULL, NULL, config->tracereq, NULL, NULL); + if (config->traceditf) + afb_hook_create_ditf(NULL, config->traceditf, NULL, NULL); + afb_apis_set_timeout(config->apiTimeout); start_list(config->dbus_clients, afb_api_dbus_add_client, "the afb-dbus client"); start_list(config->ws_clients, afb_api_ws_add_client, "the afb-websocket client"); @@ -435,10 +441,6 @@ static void start() DEBUG("Init config done"); - /* install trace of requests */ - if (config->tracereq) - afb_hook_xreq_create(NULL, NULL, NULL, config->tracereq, NULL, NULL); - /* start the services */ if (afb_apis_start_all_services(1) < 0) goto error; @@ -470,8 +472,6 @@ int main(int argc, char *argv[]) // let's run this program with a low priority nice(20); - LOGAUTH("afb-daemon"); - sd_fds_init(); // ------------- Build session handler & init config ------- |