From: José Bollo Date: Fri, 20 Jul 2018 15:57:59 +0000 (+0200) Subject: afb-config: Rewrite the config as JSON object X-Git-Tag: 5.99.3~17 X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?p=src%2Fapp-framework-binder.git;a=commitdiff_plain;h=f96bbb49cc9bcd81693300191cf7a01b879fd83d afb-config: Rewrite the config as JSON object Despite its poor performance, this changes is good at the end because: - it allows to put config in files - it removes dirty code to translate to JSON - it removes dirty code to dump the config - it unifies code for scanning hook's flag's names - it improves unity of naming between option's names and JSON's names Change-Id: I2487c8746d78a0cff80505a12b9fa60e40da9951 Signed-off-by: José Bollo --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 421866da..ba6ba77e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,7 @@ SET(AFB_LIB_SOURCES afb-export.c afb-fdev.c afb-hook.c + afb-hook-flags.c afb-hreq.c afb-hsrv.c afb-hswitch.c diff --git a/src/afb-config.c b/src/afb-config.c index 60788700..3c0d28e9 100644 --- a/src/afb-config.c +++ b/src/afb-config.c @@ -32,7 +32,8 @@ #include "verbose.h" #include "afb-config.h" -#include "afb-hook.h" +#include "afb-hook-flags.h" +#include "wrap-json.h" #define _d2s_(x) #x #define d2s(x) _d2s_(x) @@ -70,218 +71,249 @@ #define DEFAULT_HTTP_PORT 1234 // Define command line option -#define SET_BACKGROUND 1 -#define SET_FORGROUND 2 -#define SET_ROOT_DIR 3 -#define SET_ROOT_BASE 4 -#define SET_ROOT_API 5 -#define SET_ALIAS 6 +#define SET_BACKGROUND 1 +#define SET_FOREGROUND 2 +#define SET_ROOT_DIR 3 +#define SET_ROOT_BASE 4 +#define SET_ROOT_API 5 +#define ADD_ALIAS 6 -#define SET_CACHE_TIMEOUT 7 +#define SET_CACHE_TIMEOUT 7 -#define AUTO_WS 8 -#define AUTO_LINK 9 +#define AUTO_WS 8 +#define AUTO_LINK 9 -#define SET_LDPATH 10 -#define SET_APITIMEOUT 11 -#define SET_CNTXTIMEOUT 12 -#define SET_WEAK_LDPATH 13 -#define NO_LDPATH 14 +#define ADD_LDPATH 10 +#define SET_API_TIMEOUT 11 +#define SET_SESSION_TIMEOUT 12 +#define ADD_WEAK_LDPATH 13 +#define SET_NO_LDPATH 14 -#define SET_SESSIONMAX 15 +#define SET_SESSIONMAX 15 -#define WS_CLIENT 16 -#define WS_SERVICE 17 +#define ADD_WS_CLIENT 16 +#define ADD_WS_SERVICE 17 -#define SET_ROOT_HTTP 18 +#define SET_ROOT_HTTP 18 -#define SET_NO_HTTPD 19 +#define SET_NO_HTTPD 19 -#define SET_TRACEEVT 20 -#define SET_TRACESES 21 -#define SET_TRACEREQ 22 -#define SET_TRACEAPI 23 +#define SET_TRACEEVT 20 +#define SET_TRACESES 21 +#define SET_TRACEREQ 22 +#define SET_TRACEAPI 23 +#define SET_TRACEGLOB 24 #if !defined(REMOVE_LEGACY_TRACE) -#define SET_TRACEDITF 24 -#define SET_TRACESVC 25 +#define SET_TRACEDITF 25 +#define SET_TRACESVC 26 #endif #if defined(WITH_DBUS_TRANSPARENCY) -# define DBUS_CLIENT 30 -# define DBUS_SERVICE 31 +# define ADD_DBUS_CLIENT 30 +# define ADD_DBUS_SERVICE 31 #endif -#define AUTO_API 'A' -#define SO_BINDING 'b' +#define ADD_AUTO_API 'A' +#define ADD_BINDING 'b' +#define SET_CONFIG 'C' #define ADD_CALL 'c' +#define SET_DAEMON 'D' #define SET_EXEC 'e' -#define DISPLAY_HELP 'h' +#define GET_HELP 'h' #define SET_LOG 'l' #if defined(WITH_MONITORING_OPTION) #define SET_MONITORING 'M' #endif #define SET_NAME 'n' -#define SET_TCP_PORT 'p' +#define SET_OUTPUT 'o' +#define SET_PORT 'p' #define SET_QUIET 'q' -#define SET_RNDTOKEN 'r' -#define SET_AUTH_TOKEN 't' +#define SET_RANDOM_TOKEN 'r' +#define SET_TOKEN 't' #define SET_UPLOAD_DIR 'u' -#define DISPLAY_VERSION 'V' +#define GET_VERSION 'V' #define SET_VERBOSE 'v' #define SET_WORK_DIR 'w' -const char shortopts[] = - "A:" - "b:" - "c:" - "e" - "h" - "l:" -#if defined(WITH_MONITORING_OPTION) - "M" -#endif - "n:" - "p:" - "q" - "r" - "t:" - "u:" - "V" - "v" - "w:" -; - -// Command line structure hold cli --command + help text -typedef struct { - int val; // command number within application - int has_arg; // command number within application - char *name; // command as used in --xxxx cli - char *help; // help text -} AFB_options; - -// Supported option -static AFB_options cliOptions[] = { +/* structure for defining of options */ +struct option_desc { + int id; /* id of the option */ + int has_arg; /* is a value required */ + char *name; /* long name of the option */ + char *help; /* help text */ +}; + +/* definition of options */ +static struct option_desc optdefs[] = { /* *INDENT-OFF* */ - {SET_VERBOSE, 0, "verbose", "Verbose Mode, repeat to increase verbosity"}, - {SET_QUIET, 0, "quiet", "Quiet Mode, repeat to decrease verbosity"}, - {SET_LOG, 1, "log", "Tune log level"}, + {SET_VERBOSE, 0, "verbose", "Verbose Mode, repeat to increase verbosity"}, + {SET_QUIET, 0, "quiet", "Quiet Mode, repeat to decrease verbosity"}, + {SET_LOG, 1, "log", "Tune log level"}, - {SET_FORGROUND, 0, "foreground", "Get all in foreground mode"}, - {SET_BACKGROUND, 0, "daemon", "Get all in background mode"}, + {SET_FOREGROUND, 0, "foreground", "Get all in foreground mode"}, + {SET_BACKGROUND, 0, "background", "Get all in background mode"}, + {SET_DAEMON, 0, "daemon", "Get all in background mode"}, - {SET_NAME, 1, "name", "Set the visible name"}, + {SET_NAME, 1, "name", "Set the visible name"}, - {SET_TCP_PORT, 1, "port", "HTTP listening TCP port [default " d2s(DEFAULT_HTTP_PORT) "]"}, - {SET_ROOT_HTTP, 1, "roothttp", "HTTP Root Directory [default no root http (files not served but apis still available)]"}, - {SET_ROOT_BASE, 1, "rootbase", "Angular Base Root URL [default /opa]"}, - {SET_ROOT_API, 1, "rootapi", "HTML Root API URL [default /api]"}, - {SET_ALIAS, 1, "alias", "Multiple url map outside of rootdir [eg: --alias=/icons:/usr/share/icons]"}, + {SET_PORT, 1, "port", "HTTP listening TCP port [default " d2s(DEFAULT_HTTP_PORT) "]"}, + {SET_ROOT_HTTP, 1, "roothttp", "HTTP Root Directory [default no root http (files not served but apis still available)]"}, + {SET_ROOT_BASE, 1, "rootbase", "Angular Base Root URL [default /opa]"}, + {SET_ROOT_API, 1, "rootapi", "HTML Root API URL [default /api]"}, + {ADD_ALIAS, 1, "alias", "Multiple url map outside of rootdir [eg: --alias=/icons:/usr/share/icons]"}, - {SET_APITIMEOUT, 1, "apitimeout", "Binding API timeout in seconds [default " d2s(DEFAULT_API_TIMEOUT) "]"}, - {SET_CNTXTIMEOUT, 1, "cntxtimeout", "Client Session Context Timeout [default " d2s(DEFAULT_SESSION_TIMEOUT) "]"}, - {SET_CACHE_TIMEOUT, 1, "cache-eol", "Client cache end of live [default " d2s(DEFAULT_CACHE_TIMEOUT) "]"}, + {SET_API_TIMEOUT, 1, "apitimeout", "Binding API timeout in seconds [default " d2s(DEFAULT_API_TIMEOUT) "]"}, + {SET_SESSION_TIMEOUT, 1, "cntxtimeout", "Client Session Context Timeout [default " d2s(DEFAULT_SESSION_TIMEOUT) "]"}, + {SET_CACHE_TIMEOUT, 1, "cache-eol", "Client cache end of live [default " d2s(DEFAULT_CACHE_TIMEOUT) "]"}, - {SET_WORK_DIR, 1, "workdir", "Set the working directory [default: $PWD or current working directory]"}, - {SET_UPLOAD_DIR, 1, "uploaddir", "Directory for uploading files [default: workdir]"}, - {SET_ROOT_DIR, 1, "rootdir", "Root Directory of the application [default: workdir]"}, + {SET_WORK_DIR, 1, "workdir", "Set the working directory [default: $PWD or current working directory]"}, + {SET_UPLOAD_DIR, 1, "uploaddir", "Directory for uploading files [default: workdir]"}, + {SET_ROOT_DIR, 1, "rootdir", "Root Directory of the application [default: workdir]"}, - {SET_LDPATH, 1, "ldpaths", "Load bindings from dir1:dir2:... [default = " BINDING_INSTALL_DIR "]"}, - {SO_BINDING, 1, "binding", "Load the binding of path"}, - {SET_WEAK_LDPATH, 1, "weak-ldpaths","Same as --ldpaths but ignore errors"}, - {NO_LDPATH, 0, "no-ldpaths", "Discard default ldpaths loading"}, + {ADD_LDPATH, 1, "ldpaths", "Load bindings from dir1:dir2:... [default = " BINDING_INSTALL_DIR "]"}, + {ADD_BINDING, 1, "binding", "Load the binding of path"}, + {ADD_WEAK_LDPATH, 1, "weak-ldpaths","Same as --ldpaths but ignore errors"}, + {SET_NO_LDPATH, 0, "no-ldpaths", "Discard default ldpaths loading"}, - {SET_AUTH_TOKEN, 1, "token", "Initial Secret [default=random, use --token="" to allow any token]"}, - {SET_RNDTOKEN, 0, "random-token","Enforce a random token"}, + {SET_TOKEN, 1, "token", "Initial Secret [default=random, use --token="" to allow any token]"}, + {SET_RANDOM_TOKEN, 0, "random-token","Enforce a random token"}, - {DISPLAY_VERSION, 0, "version", "Display version and copyright"}, - {DISPLAY_HELP, 0, "help", "Display this help"}, + {GET_VERSION, 0, "version", "Display version and copyright"}, + {GET_HELP, 0, "help", "Display this help"}, #if defined(WITH_DBUS_TRANSPARENCY) - {DBUS_CLIENT, 1, "dbus-client", "Bind to an afb service through dbus"}, - {DBUS_SERVICE, 1, "dbus-server", "Provide an afb service through dbus"}, + {ADD_DBUS_CLIENT, 1, "dbus-client", "Bind to an afb service through dbus"}, + {ADD_DBUS_SERVICE, 1, "dbus-server", "Provide an afb service through dbus"}, #endif - {WS_CLIENT, 1, "ws-client", "Bind to an afb service through websocket"}, - {WS_SERVICE, 1, "ws-server", "Provide an afb service through websockets"}, + {ADD_WS_CLIENT, 1, "ws-client", "Bind to an afb service through websocket"}, + {ADD_WS_SERVICE, 1, "ws-server", "Provide an afb service through websockets"}, - {AUTO_API, 1, "auto-api", "Automatic load of api of the given directory"}, + {ADD_AUTO_API, 1, "auto-api", "Automatic load of api of the given directory"}, - {SET_SESSIONMAX, 1, "session-max", "Max count of session simultaneously [default " d2s(DEFAULT_MAX_SESSION_COUNT) "]"}, + {SET_SESSIONMAX, 1, "session-max", "Max count of session simultaneously [default " d2s(DEFAULT_MAX_SESSION_COUNT) "]"}, - {SET_TRACEREQ, 1, "tracereq", "Log the requests: no, common, extra, all"}, + {SET_TRACEREQ, 1, "tracereq", "Log the requests: none, common, extra, all"}, + {SET_TRACEEVT, 1, "traceevt", "Log the events: none, common, extra, all"}, + {SET_TRACESES, 1, "traceses", "Log the sessions: none, all"}, + {SET_TRACEAPI, 1, "traceapi", "Log the apis: none, common, api, event, all"}, + {SET_TRACEGLOB, 1, "traceglob", "Log the globals: none, all"}, #if !defined(REMOVE_LEGACY_TRACE) - {SET_TRACEDITF, 1, "traceditf", "Log the daemons: no, common, all"}, - {SET_TRACESVC, 1, "tracesvc", "Log the services: no, all"}, + {SET_TRACEDITF, 1, "traceditf", "Log the daemons: no, common, all"}, + {SET_TRACESVC, 1, "tracesvc", "Log the services: no, all"}, #endif - {SET_TRACEEVT, 1, "traceevt", "Log the events: no, common, extra, all"}, - {SET_TRACESES, 1, "traceses", "Log the sessions: no, all"}, - {SET_TRACEAPI, 1, "traceapi", "Log the apis: no, common, api, event, all"}, - {ADD_CALL, 1, "call", "call at start format of val: API/VERB:json-args"}, + {ADD_CALL, 1, "call", "Call at start, format of val: API/VERB:json-args"}, - {SET_NO_HTTPD, 0, "no-httpd", "Forbid HTTP service"}, - {SET_EXEC, 0, "exec", "Execute the remaining arguments"}, + {SET_NO_HTTPD, 0, "no-httpd", "Forbid HTTP service"}, + {SET_EXEC, 0, "exec", "Execute the remaining arguments"}, #if defined(WITH_MONITORING_OPTION) - {SET_MONITORING, 0, "monitoring", "Enable HTTP monitoring at /monitoring/"}, + {SET_MONITORING, 0, "monitoring", "Enable HTTP monitoring at /monitoring/"}, #endif + + {SET_CONFIG, 1, "config", "Load options from the given config file"}, + {SET_OUTPUT, 1, "output", "Redirect stdout and stderr to output file (when --daemon)"}, + {0, 0, NULL, NULL} /* *INDENT-ON* */ }; +#if defined(WITH_MONITORING_OPTION) +static const char MONITORING_ALIAS[] = "/monitoring:"BINDING_INSTALL_DIR"/monitoring"; +#endif -struct enumdesc -{ - const char *name; - int value; +static const struct { + int optid; + int valdef; +} default_optint_values[] = { + { SET_PORT, DEFAULT_HTTP_PORT }, + { SET_API_TIMEOUT, DEFAULT_API_TIMEOUT }, + { SET_CACHE_TIMEOUT, DEFAULT_CACHE_TIMEOUT }, + { SET_SESSION_TIMEOUT, DEFAULT_SESSION_TIMEOUT }, + { SET_SESSIONMAX, DEFAULT_MAX_SESSION_COUNT } }; -static struct enumdesc tracereq_desc[] = { - { "no", 0 }, - { "common", afb_hook_flags_req_common }, - { "extra", afb_hook_flags_req_extra }, - { "all", afb_hook_flags_req_all }, - { NULL, 0 } +static const struct { + int optid; + const char *valdef; +} default_optstr_values[] = { + { SET_WORK_DIR, "." }, + { SET_ROOT_DIR, "." }, + { SET_UPLOAD_DIR, "." }, + { SET_ROOT_BASE, "/opa" }, + { SET_ROOT_API, "/api" } }; -#if !defined(REMOVE_LEGACY_TRACE) -static struct enumdesc traceditf_desc[] = { - { "no", 0 }, - { "common", afb_hook_flags_api_ditf_common }, - { "all", afb_hook_flags_api_ditf_all }, - { NULL, 0 } -}; +/********************************** +* preparing items +***********************************/ -static struct enumdesc tracesvc_desc[] = { - { "no", 0 }, - { "all", afb_hook_flags_api_svc_all }, - { NULL, 0 } -}; -#endif +static char *shortopts = NULL; +static int *id2idx = NULL; -static struct enumdesc traceevt_desc[] = { - { "no", 0 }, - { "common", afb_hook_flags_evt_common }, - { "extra", afb_hook_flags_evt_extra }, - { "all", afb_hook_flags_evt_all }, - { NULL, 0 } -}; +static void *oomchk(void *ptr) +{ + if (!ptr) { + ERROR("Out of memory"); + exit(1); + } + return ptr; +} -static struct enumdesc traceses_desc[] = { - { "no", 0 }, - { "common", afb_hook_flags_session_common }, - { "all", afb_hook_flags_session_all }, - { NULL, 0 } -}; +static char is_short_option(int val) +{ + return (val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z') || (val >= '0' && val <= '9'); +} + +static void init_options() +{ + int i, ns, mi, id; + + if (!shortopts) { + ns = 2; + mi = -1; + for (i = 0 ; optdefs[i].name ; i++) { + id = optdefs[i].id; + if (id > mi) + mi = id; + if (is_short_option(id)) + ns += 1 + !!optdefs[i].has_arg; + } + shortopts = oomchk(malloc(2 + ns)); + id2idx = oomchk(calloc(1 + mi, sizeof *id2idx)); + shortopts[ns = 0] = ':'; + for (i = 0 ; optdefs[i].name ; i++) { + id = optdefs[i].id; + id2idx[id] = i; + if (is_short_option(id)) { + shortopts[++ns] = (char)id; + if (optdefs[i].has_arg) + shortopts[++ns] = ':'; + } + } + shortopts[++ns] = 0; + } +} + +static const char *name_of_optid(int optid) +{ + return optdefs[id2idx[optid]].name; +} + +static int get_enum_val(const char *name, int optid, int (*func)(const char*)) +{ + int i; + + i = func(name); + if (i < 0) { + ERROR("option [--%s] bad value (found %s)", + name_of_optid(optid), name); + exit(1); + } + return i; +} -static struct enumdesc traceapi_desc[] = { - { "no", 0 }, - { "common", afb_hook_flags_api_common }, - { "api", afb_hook_flags_api_api|afb_hook_flag_api_start }, - { "event", afb_hook_flags_api_event|afb_hook_flag_api_start }, - { "all", afb_hook_flags_api_all }, - { NULL, 0 } -}; /*---------------------------------------------------------- | printversion @@ -342,183 +374,210 @@ static void printHelp(FILE * file, const char *name) int ind; char command[50], sht[4]; + fprintf(file, "%s:\nallowed options\n", strrchr(name, '/') ? strrchr(name, '/') + 1 : name); sht[3] = 0; - fprintf(file, "%s:\nallowed options\n", name); - for (ind = 0; cliOptions[ind].name != NULL; ind++) { - if (((cliOptions[ind].val >= 'a' && cliOptions[ind].val <= 'z') - || (cliOptions[ind].val >= 'A' && cliOptions[ind].val <= 'Z') - || (cliOptions[ind].val >= '0' && cliOptions[ind].val <= '9')) - && strchr(shortopts, (char)cliOptions[ind].val)) { + for (ind = 0; optdefs[ind].name != NULL; ind++) { + if (is_short_option(optdefs[ind].id)) { sht[0] = '-'; - sht[1] = (char)cliOptions[ind].val; + sht[1] = (char)optdefs[ind].id; sht[2] = ','; } else { sht[0] = sht[1] = sht[2] = ' '; } - strcpy(command, cliOptions[ind].name); - if (cliOptions[ind].has_arg) + strcpy(command, optdefs[ind].name); + if (optdefs[ind].has_arg) strcat(command, "=xxxx"); - fprintf(file, " %s --%-17s %s\n", sht, command, cliOptions[ind].help); + fprintf(file, " %s --%-17s %s\n", sht, command, optdefs[ind].help); } fprintf(file, - "Example:\n %s --verbose --port=" d2s(DEFAULT_HTTP_PORT) " --token='azerty' --ldpaths=build/bindings:/usr/lib64/agl/bindings\n", + "Example:\n %s --verbose --port=" + d2s(DEFAULT_HTTP_PORT) + " --token='azerty' --ldpaths=build/bindings:/usr/lib64/agl/bindings\n", name); } - -/*---------------------------------------------------------- - | adds a string to the list +/*--------------------------------------------------------- + | helpers for argument scanning +--------------------------------------------------------- */ -static void list_add(struct afb_config_list **head, char *value) + +static const char *current_argument(int optid) { - struct afb_config_list *item; - - /* - * search tail - */ - item = *head; - while (item != NULL) { - head = &item->next; - item = item->next; + if (optarg == 0) { + ERROR("option [--%s] needs a value i.e. --%s=xxx", + name_of_optid(optid), name_of_optid(optid)); + exit(1); } + return optarg; +} - /* - * alloc the item - */ - item = malloc(sizeof *item); - if (item == NULL) { - ERROR("out of memory"); +static char *argvalstr(int optid) +{ + char *result = strdup(current_argument(optid)); + if (result == NULL) { + ERROR("can't alloc memory"); exit(1); } + return result; +} + +/********************************** +* json helpers +***********************************/ - /* - * init the item - */ - *head = item; - item->value = value; - item->next = NULL; +static struct json_object *joomchk(struct json_object *value) +{ + return oomchk(value); } -/*--------------------------------------------------------- - | helpers for argument scanning - +--------------------------------------------------------- */ +static struct json_object *to_jstr(const char *value) +{ + return joomchk(json_object_new_string(value)); +} + +static struct json_object *to_jint(int value) +{ + return joomchk(json_object_new_int(value)); +} -static const char *name_of_option(int optc) +static struct json_object *to_jbool(int value) { - AFB_options *o = cliOptions; - while (o->name && o->val != optc) - o++; - return o->name ? : ""; + return joomchk(json_object_new_boolean(value)); } -static const char *current_argument(int optc) +/********************************** +* arguments helpers +***********************************/ + +static void noarg(int optid) +{ + if (optarg) { + ERROR("option [--%s] need no value (found %s)", name_of_optid(optid), optarg); + exit(1); + } +} + +static const char *get_arg(int optid) { if (optarg == 0) { ERROR("option [--%s] needs a value i.e. --%s=xxx", - name_of_option(optc), name_of_option(optc)); + name_of_optid(optid), name_of_optid(optid)); exit(1); } return optarg; } -static char *argvalstr(int optc) +static void config_del(struct json_object *config, int optid) { - char *result = strdup(current_argument(optc)); - if (result == NULL) { - ERROR("can't alloc memory"); - exit(1); - } - return result; + return json_object_object_del(config, name_of_optid(optid)); } -static int argvalenum(int optc, struct enumdesc *desc) +static int config_has(struct json_object *config, int optid) { - int i; - size_t len; - char *list; - const char *name = current_argument(optc); + return json_object_object_get_ex(config, name_of_optid(optid), NULL); +} - i = 0; - while(desc[i].name && strcmp(desc[i].name, name)) - i++; - if (!desc[i].name) { - len = 0; - i = 0; - while(desc[i].name) - len += strlen(desc[i++].name); - list = malloc(len + i + i); - if (!i || !list) - ERROR("option [--%s] bad value (found %s)", - name_of_option(optc), name); - else { - i = 0; - strcpy(list, desc[i].name ? : ""); - while(desc[++i].name) - strcat(strcat(list, ", "), desc[i].name); - ERROR("option [--%s] bad value, only accepts values %s (found %s)", - name_of_option(optc), list, name); - } - free(list); - exit(1); +static int config_has_bool(struct json_object *config, int optid) +{ + struct json_object *x; + return json_object_object_get_ex(config, name_of_optid(optid), &x) + && json_object_get_boolean(x); +} + +static int config_has_str(struct json_object *config, int optid, const char *val) +{ + int i, n; + struct json_object *a; + + if (!json_object_object_get_ex(config, name_of_optid(optid), &a)) + return 0; + + if (!json_object_is_type(a, json_type_array)) + return !strcmp(val, json_object_get_string(a)); + + n = (int)json_object_array_length(a); + for (i = 0 ; i < n ; i++) { + if (!strcmp(val, json_object_get_string(json_object_array_get_idx(a, i)))) + return 1; } - return desc[i].value; + return 0; +} + +static void config_set(struct json_object *config, int optid, struct json_object *val) +{ + json_object_object_add(config, name_of_optid(optid), val); +} + +static void config_set_str(struct json_object *config, int optid, const char *val) +{ + config_set(config, optid, to_jstr(val)); +} + +static void config_set_optstr(struct json_object *config, int optid) +{ + config_set_str(config, optid, get_arg(optid)); +} + +static void config_set_int(struct json_object *config, int optid, int value) +{ + config_set(config, optid, to_jint(value)); +} + +static void config_set_bool(struct json_object *config, int optid, int value) +{ + config_set(config, optid, to_jbool(value)); } -static int argvalint(int optc, int mini, int maxi, int base) +static void config_set_optint_base(struct json_object *config, int optid, int mini, int maxi, int base) { const char *beg, *end; long int val; - beg = current_argument(optc); + + beg = get_arg(optid); val = strtol(beg, (char**)&end, base); if (*end || end == beg) { ERROR("option [--%s] requires a valid integer (found %s)", - name_of_option(optc), beg); + name_of_optid(optid), beg); exit(1); } if (val < (long int)mini || val > (long int)maxi) { - ERROR("option [--%s] value out of bounds (not %d<=%ld<=%d)", - name_of_option(optc), mini, val, maxi); + ERROR("option [--%s] value %ld out of bounds (not in [%d , %d])", + name_of_optid(optid), val, mini, maxi); exit(1); } - return (int)val; + config_set_int(config, optid, (int)val); } -static int argvalintdec(int optc, int mini, int maxi) +static void config_set_optint(struct json_object *config, int optid, int mini, int maxi) { - return argvalint(optc, mini, maxi, 10); + return config_set_optint_base(config, optid, mini, maxi, 10); } -static void noarg(int optc) +static void config_set_optenum(struct json_object *config, int optid, int (*func)(const char*)) { - if (optarg != 0) { - ERROR("option [--%s] need no value (found %s)", name_of_option(optc), optarg); - exit(1); - } + const char *name = get_arg(optid); + get_enum_val(name, optid, func); + config_set_str(config, optid, name); } -static char **make_exec(char **argv) +static void config_add(struct json_object *config, int optid, struct json_object *val) { - char **result, *iter; - size_t length; - int i; - - length = 0; - for (i = 0 ; argv[i] ; i++) - length += strlen(argv[i]) + 1; - - result = malloc(length + ((unsigned)(i + 1)) * sizeof *result); - if (result == NULL) { - ERROR("can't alloc memory"); - exit(1); + struct json_object *a; + if (!json_object_object_get_ex(config, name_of_optid(optid), &a)) { + a = json_object_new_array(); + oomchk(a); + json_object_object_add(config, name_of_optid(optid), a); } + json_object_array_add(a, val); +} - iter = (char*)&result[i+1]; - for (i = 0 ; argv[i] ; i++) { - result[i] = iter; - iter = stpcpy(iter, argv[i]) + 1; - } - result[i] = NULL; - return result; +static void config_add_str(struct json_object *config, int optid, const char *val) +{ + config_add(config, optid, to_jstr(val)); +} + +static void config_add_optstr(struct json_object *config, int optid) +{ + config_add_str(config, optid, get_arg(optid)); } /*--------------------------------------------------------- @@ -572,28 +631,19 @@ static void set_log(char *args) | Parse option and launch action +--------------------------------------------------------- */ -static void parse_arguments(int argc, char **argv, struct afb_config *config) +static void parse_arguments_inner(int argc, char **argv, struct json_object *config, struct option *options) { - char *programName = argv[0]; - int optc, ind; - int nbcmd; - struct option *gnuOptions; - - // ------------------ Process Command Line ----------------------- - - // build GNU getopt info from cliOptions - nbcmd = sizeof(cliOptions) / sizeof(AFB_options); - gnuOptions = malloc(sizeof(*gnuOptions) * (unsigned)nbcmd); - for (ind = 0; ind < nbcmd; ind++) { - gnuOptions[ind].name = cliOptions[ind].name; - gnuOptions[ind].has_arg = cliOptions[ind].has_arg; - gnuOptions[ind].flag = 0; - gnuOptions[ind].val = cliOptions[ind].val; - } + struct json_object *conf; + int optid, cind; - // get all options from command line - while ((optc = getopt_long(argc, argv, shortopts, gnuOptions, NULL)) != EOF) { - switch (optc) { + for (;;) { + cind = optind; + optid = getopt_long(argc, argv, shortopts, options, NULL); + if (optid < 0) { + /* end of options */ + break; + } + switch (optid) { case SET_VERBOSE: verbose_inc(); break; @@ -603,369 +653,258 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config) break; case SET_LOG: - set_log(argvalstr(optc)); + set_log(argvalstr(optid)); break; - case SET_TCP_PORT: - config->http_port = argvalintdec(optc, 1024, 32767); + case SET_PORT: + config_set_optint(config, optid, 1024, 32767); break; - case SET_APITIMEOUT: - config->api_timeout = argvalintdec(optc, 0, INT_MAX); + case SET_API_TIMEOUT: + case SET_SESSION_TIMEOUT: + case SET_CACHE_TIMEOUT: + config_set_optint(config, optid, 0, INT_MAX); break; - case SET_CNTXTIMEOUT: - config->session_timeout = argvalintdec(optc, 0, INT_MAX); + case SET_SESSIONMAX: + config_set_optint(config, optid, 1, INT_MAX); break; case SET_ROOT_DIR: - config->rootdir = argvalstr(optc); - INFO("Forcing Rootdir=%s", config->rootdir); - break; - case SET_ROOT_HTTP: - config->roothttp = argvalstr(optc); - INFO("Forcing Root HTTP=%s", config->roothttp); - break; - case SET_ROOT_BASE: - config->rootbase = argvalstr(optc); - INFO("Forcing Rootbase=%s", config->rootbase); - break; - case SET_ROOT_API: - config->rootapi = argvalstr(optc); - INFO("Forcing Rootapi=%s", config->rootapi); - break; - - case SET_ALIAS: - list_add(&config->aliases, argvalstr(optc)); - break; - - case SET_AUTH_TOKEN: - config->token = argvalstr(optc); - break; - - case SET_LDPATH: - list_add(&config->ldpaths, argvalstr(optc)); - break; - - case SET_WEAK_LDPATH: - list_add(&config->weak_ldpaths, argvalstr(optc)); - break; - - case NO_LDPATH: - noarg(optc); - config->no_ldpaths = 1; - break; - - case ADD_CALL: - list_add(&config->calls, argvalstr(optc)); - break; - + case SET_TOKEN: case SET_UPLOAD_DIR: - config->uploaddir = argvalstr(optc); - break; - case SET_WORK_DIR: - config->workdir = argvalstr(optc); + case SET_NAME: + config_set_optstr(config, optid); break; - case SET_CACHE_TIMEOUT: - config->cache_timeout = argvalintdec(optc, 0, INT_MAX); +#if defined(WITH_DBUS_TRANSPARENCY) + case ADD_DBUS_CLIENT: + case ADD_DBUS_SERVICE: +#endif + case ADD_ALIAS: + case ADD_LDPATH: + case ADD_WEAK_LDPATH: + case ADD_CALL: + case ADD_WS_CLIENT: + case ADD_WS_SERVICE: + case ADD_BINDING: + case ADD_AUTO_API: + config_add_optstr(config, optid); break; - case SET_SESSIONMAX: - config->max_session_count = argvalintdec(optc, 1, INT_MAX); +#if defined(WITH_MONITORING_OPTION) + case SET_MONITORING: +#endif + case SET_RANDOM_TOKEN: + case SET_NO_HTTPD: + case SET_NO_LDPATH: + noarg(optid); + config_set_bool(config, optid, 1); break; - case SET_FORGROUND: - noarg(optc); - config->background = 0; - break; + case SET_FOREGROUND: case SET_BACKGROUND: - noarg(optc); - config->background = 1; + case SET_DAEMON: + noarg(optid); + config_set_bool(config, SET_DAEMON, optid != SET_FOREGROUND); break; - case SET_NAME: - config->name = argvalstr(optc); - break; - -#if defined(WITH_DBUS_TRANSPARENCY) - case DBUS_CLIENT: - list_add(&config->dbus_clients, argvalstr(optc)); - break; - - case DBUS_SERVICE: - list_add(&config->dbus_servers, argvalstr(optc)); - break; -#endif - - case WS_CLIENT: - list_add(&config->ws_clients, argvalstr(optc)); + case SET_TRACEREQ: + config_set_optenum(config, optid, afb_hook_flags_xreq_from_text); break; - case WS_SERVICE: - list_add(&config->ws_servers, argvalstr(optc)); + case SET_TRACEEVT: + config_set_optenum(config, optid, afb_hook_flags_evt_from_text); break; - case SO_BINDING: - list_add(&config->so_bindings, argvalstr(optc)); + case SET_TRACESES: + config_set_optenum(config, optid, afb_hook_flags_session_from_text); break; - case AUTO_API: - list_add(&config->auto_api, argvalstr(optc)); + case SET_TRACEAPI: + config_set_optenum(config, optid, afb_hook_flags_api_from_text); break; - case SET_TRACEREQ: - config->tracereq = argvalenum(optc, tracereq_desc); + case SET_TRACEGLOB: + config_set_optenum(config, optid, afb_hook_flags_global_from_text); break; #if !defined(REMOVE_LEGACY_TRACE) case SET_TRACEDITF: - config->traceditf = argvalenum(optc, traceditf_desc); + config_set_optenum(config, optid, afb_hook_flags_legacy_ditf_from_text); break; case SET_TRACESVC: - config->tracesvc = argvalenum(optc, tracesvc_desc); + config_set_optenum(config, optid, afb_hook_flags_legacy_svc_from_text); break; #endif - case SET_TRACEEVT: - config->traceevt = argvalenum(optc, traceevt_desc); - break; - - case SET_TRACESES: - config->traceses = argvalenum(optc, traceses_desc); - break; - - case SET_TRACEAPI: - config->traceapi = argvalenum(optc, traceapi_desc); - break; - - case SET_NO_HTTPD: - noarg(optc); - config->no_httpd = 1; - break; - case SET_EXEC: - config->exec = make_exec(&argv[optind]); - optind = argc; /* stop option scanning */ - break; - - case SET_RNDTOKEN: - config->random_token = 1; + if (optind == argc) { + ERROR("The option --exec requires arguments"); + exit(1); + } + while (optind != argc) + config_add_str(config, optid, argv[optind++]); break; -#if defined(WITH_MONITORING_OPTION) - case SET_MONITORING: - config->monitoring = 1; + case SET_CONFIG: + conf = json_object_from_file(get_arg(optid)); + if (!conf) { + ERROR("Can't read config file %s", get_arg(optid)); + exit(1); + } + wrap_json_object_add(config, conf); + json_object_put(conf); break; -#endif - case DISPLAY_VERSION: - noarg(optc); + case GET_VERSION: + noarg(optid); printVersion(stdout); exit(0); - case DISPLAY_HELP: - printHelp(stdout, programName); + case GET_HELP: + printHelp(stdout, argv[0]); exit(0); default: + ERROR("Bad option detected, check %s", argv[cind]); exit(1); } } - free(gnuOptions); + /* TODO: check for extra value */ } -static void fulfill_config(struct afb_config *config) +static void parse_arguments(int argc, char **argv, struct json_object *config) { - // default HTTP port - if (config->http_port == 0) - config->http_port = DEFAULT_HTTP_PORT; + int ind; + struct option *options; + + /* create GNU getopt options from optdefs */ + options = malloc((sizeof optdefs / sizeof * optdefs) * sizeof * options); + for (ind = 0; optdefs[ind].name; ind++) { + options[ind].name = optdefs[ind].name; + options[ind].has_arg = optdefs[ind].has_arg; + options[ind].flag = NULL; + options[ind].val = optdefs[ind].id; + } + memset(&options[ind], 0, sizeof options[ind]); - // default binding API timeout - if (config->api_timeout == 0) - config->api_timeout = DEFAULT_API_TIMEOUT; + /* parse the arguments */ + parse_arguments_inner(argc, argv, config, options); - // default AUTH_TOKEN - if (config->random_token) - config->token = NULL; + /* release the memory of options */ + free(options); +} - // cache timeout default one hour - if (config->cache_timeout == 0) - config->cache_timeout = DEFAULT_CACHE_TIMEOUT; +static void fulfill_config(struct json_object *config) +{ + int i; - // cache timeout default one hour - if (config->session_timeout == 0) - config->session_timeout = DEFAULT_SESSION_TIMEOUT; + for (i = 0 ; i < sizeof default_optint_values / sizeof * default_optint_values ; i++) + if (!config_has(config, default_optint_values[i].optid)) + config_set_int(config, default_optint_values[i].optid, default_optint_values[i].valdef); - // max count of sessions - if (config->max_session_count == 0) - config->max_session_count = DEFAULT_MAX_SESSION_COUNT; + for (i = 0 ; i < sizeof default_optstr_values / sizeof * default_optstr_values ; i++) + if (!config_has(config, default_optstr_values[i].optid)) + config_set_str(config, default_optstr_values[i].optid, default_optstr_values[i].valdef); - /* set directories */ - if (config->workdir == NULL) - config->workdir = "."; + // default AUTH_TOKEN + if (config_has_bool(config, SET_RANDOM_TOKEN)) + config_del(config, SET_TOKEN); - if (config->rootdir == NULL) - config->rootdir = "."; + if (!config_has(config, ADD_LDPATH) && !config_has(config, ADD_WEAK_LDPATH) && !config_has_bool(config, SET_NO_LDPATH)) + config_add_str(config, ADD_LDPATH, BINDING_INSTALL_DIR); - if (config->uploaddir == NULL) - config->uploaddir = "."; +#if defined(WITH_MONITORING_OPTION) + if (config_has_bool(config, SET_MONITORING) && !config_has_str(config, ADD_ALIAS, MONITORING_ALIAS)) + config_add_str(config, ADD_ALIAS, MONITORING_ALIAS); +#endif - // if no Angular/HTML5 rootbase let's try '/' as default - if (config->rootbase == NULL) - config->rootbase = "/opa"; +#if !defined(REMOVE_LEGACY_TRACE) && 0 + config->traceapi |= config->traceditf | config->tracesvc; +#endif +} - if (config->rootapi == NULL) - config->rootapi = "/api"; +static void dump(struct json_object *config, FILE *file, const char *prefix, const char *title) +{ + char z; + const char *head, *tail; - if (config->ldpaths == NULL && config->weak_ldpaths == NULL && !config->no_ldpaths) - list_add(&config->ldpaths, BINDING_INSTALL_DIR); + if (!prefix) { + z = 0; + prefix = &z; + } -#if defined(WITH_MONITORING_OPTION) - if (config->monitoring) - list_add(&config->aliases, strdup("/monitoring:"BINDING_INSTALL_DIR"/monitoring")); -#endif + if (title) + fprintf(file, "%s----BEGIN OF %s-----\n", prefix, title); + + head = json_object_to_json_string_ext(config, JSON_C_TO_STRING_PRETTY + |JSON_C_TO_STRING_SPACED|JSON_C_TO_STRING_NOSLASHESCAPE); - // if no config dir create a default path from uploaddir - if (config->console == NULL) { - config->console = malloc(512); - strncpy(config->console, config->uploaddir, 512); - strncat(config->console, "/AFB-console.out", 512); + if (head) { + while(*head) { + for (tail = head ; *tail && *tail != '\n' ; tail++); + fprintf(file, "%s %.*s\n", prefix, (int)(tail - head), head); + head = tail + !!*tail; + } } -#if !defined(REMOVE_LEGACY_TRACE) - config->traceapi |= config->traceditf | config->tracesvc; -#endif + if (title) + fprintf(file, "%s----END OF %s-----\n", prefix, title); } -void afb_config_dump(struct afb_config *config) +void afb_config_dump(struct json_object *config) { - struct afb_config_list *l; - struct enumdesc *e; - char **v; - -#define NN(x) (x)?:"" -#define P(...) fprintf(stderr, __VA_ARGS__) -#define PF(x) P("-- %15s: ", #x) -#define PE P("\n") -#define S(x) PF(x);P("%s",NN(config->x));PE; -#define D(x) PF(x);P("%d",config->x);PE; -#define B(x) PF(x);P("%s",config->x?"yes":"no");PE; -#define L(x) PF(x);l=config->x;if(l){P("%s\n",NN(l->value));for(l=l->next;l;l=l->next)P("-- %15s %s\n","",NN(l->value));}else PE; -#define E(x,d) for(e=d;e->name&&e->value!=config->x;e++);if(e->name){PF(x);P("%s",e->name);PE;}else{D(x);} -#define V(x) P("-- %15s:", #x);for(v=config->x;v&&*v;v++)P(" %s",*v); PE; - - P("---BEGIN-OF-CONFIG---\n"); - S(console) - S(rootdir) - S(roothttp) - S(rootbase) - S(rootapi) - S(workdir) - S(uploaddir) - S(token) - S(name) - - L(aliases) -#if defined(WITH_DBUS_TRANSPARENCY) - L(dbus_clients) - L(dbus_servers) -#endif - L(ws_clients) - L(ws_servers) - L(so_bindings) - L(auto_api) - L(ldpaths) - L(weak_ldpaths) - L(calls) - - V(exec) - - D(http_port) - D(cache_timeout) - D(api_timeout) - D(session_timeout) - D(max_session_count) - - E(tracereq,tracereq_desc) -#if !defined(REMOVE_LEGACY_TRACE) - E(traceditf,traceditf_desc) - E(tracesvc,tracesvc_desc) -#endif - E(traceevt,traceevt_desc) - E(traceses,traceses_desc) - E(traceapi,traceapi_desc) - - B(no_ldpaths) - B(no_httpd) - B(background) -#if defined(WITH_MONITORING_OPTION) - B(monitoring) -#endif - B(random_token) - P("---END-OF-CONFIG---\n"); - -#undef V -#undef E -#undef L -#undef B -#undef D -#undef S -#undef PE -#undef PF -#undef P -#undef NN + dump(config, stderr, "--", "CONFIG"); } -static void on_environment_list(struct afb_config_list **to, const char *name) +static void on_environment_add(struct json_object *config, int optid, const char *name) { char *value = getenv(name); - if (value) - list_add(to, value); + if (value && *value) + config_add_str(config, optid, value); } -static void on_environment_enum(int *to, const char *name, struct enumdesc *desc) +static void on_environment_enum(struct json_object *config, int optid, const char *name, int (*func)(const char*)) { char *value = getenv(name); if (value) { - while (desc->name) { - if (strcmp(desc->name, value)) - desc++; - else { - *to = desc->value; - return; - } - } - WARNING("Unknown value %s for environment variable %s, ignored", value, name); + if (func(value) == -1) + WARNING("Unknown value %s for environment variable %s, ignored", value, name); + else + config_set_str(config, optid, value); } } -static void parse_environment(struct afb_config *config) +static void parse_environment(struct json_object *config) { - on_environment_enum(&config->tracereq, "AFB_TRACEREQ", tracereq_desc); + on_environment_enum(config, SET_TRACEREQ, "AFB_TRACEREQ", afb_hook_flags_xreq_from_text); + on_environment_enum(config, SET_TRACEEVT, "AFB_TRACEEVT", afb_hook_flags_evt_from_text); + on_environment_enum(config, SET_TRACESES, "AFB_TRACESES", afb_hook_flags_session_from_text); + on_environment_enum(config, SET_TRACEAPI, "AFB_TRACEAPI", afb_hook_flags_api_from_text); + on_environment_enum(config, SET_TRACEGLOB, "AFB_TRACEGLOB", afb_hook_flags_global_from_text); + on_environment_add(config, ADD_LDPATH, "AFB_LDPATHS"); #if !defined(REMOVE_LEGACY_TRACE) - on_environment_enum(&config->traceditf, "AFB_TRACEDITF", traceditf_desc); - on_environment_enum(&config->tracesvc, "AFB_TRACESVC", tracesvc_desc); + on_environment_enum(config, SET_TRACEDITF, "AFB_TRACEDITF", afb_hook_flags_legacy_ditf_from_text); + on_environment_enum(config, SET_TRACESVC, "AFB_TRACESVC", afb_hook_flags_legacy_svc_from_text); #endif - on_environment_enum(&config->traceevt, "AFB_TRACEEVT", traceevt_desc); - on_environment_enum(&config->traceses, "AFB_TRACESES", traceses_desc); - on_environment_enum(&config->traceapi, "AFB_TRACEAPI", traceapi_desc); - on_environment_list(&config->ldpaths, "AFB_LDPATHS"); } -struct afb_config *afb_config_parse_arguments(int argc, char **argv) +struct json_object *afb_config_parse_arguments(int argc, char **argv) { - struct afb_config *result; + struct json_object *result; + + init_options(); - result = calloc(1, sizeof *result); + result = json_object_new_object(); parse_environment(result); parse_arguments(argc, argv, result); @@ -975,100 +914,8 @@ struct afb_config *afb_config_parse_arguments(int argc, char **argv) return result; } -struct json_object *afb_config_json(struct afb_config *config) +struct json_object *afb_config_json(struct json_object *config) { - struct json_object *r, *a; - struct afb_config_list *l; - struct enumdesc *e; - char **v; - -#define XA(t,o) json_object_array_add(t,o); -#define XO(t,x,o) json_object_object_add(t,x,o); -#define YS(s) ((s)?json_object_new_string(s):NULL) - -#define AO(o) XA(a,o) -#define AS(s) AO(YS(s)) -#define RO(x,o) XO(r,x,o) -#define RS(x,s) RO(x,YS(s)) -#define RA(x) RO(x,(a=json_object_new_array())) -#define RI(x,i) RO(x,json_object_new_int(i)) -#define RB(x,b) RO(x,json_object_new_boolean(b)) - -#define S(x) RS(#x,config->x) -#define V(x) RA(#x);for(v=config->x;v&&*v;v++)AS(*v); -#define L(x) RA(#x);for(l=config->x;l;l=l->next)AS(l->value); -#define D(x) RI(#x,config->x) -#define B(x) RB(#x,config->x) -#define E(x,d) for(e=d;e->name&&e->value!=config->x;e++);if(e->name){RS(#x,e->name);}else{D(x);} - - r = json_object_new_object(); - S(console) - S(rootdir) - S(roothttp) - S(rootbase) - S(rootapi) - S(workdir) - S(uploaddir) - S(token) - S(name) - - L(aliases) -#if defined(WITH_DBUS_TRANSPARENCY) - L(dbus_clients) - L(dbus_servers) -#endif - L(ws_clients) - L(ws_servers) - L(so_bindings) - L(auto_api) - L(ldpaths) - L(weak_ldpaths) - L(calls) - - V(exec) - - D(http_port) - D(cache_timeout) - D(api_timeout) - D(session_timeout) - D(max_session_count) - - E(tracereq,tracereq_desc) -#if !defined(REMOVE_LEGACY_TRACE) - E(traceditf,traceditf_desc) - E(tracesvc,tracesvc_desc) -#endif - E(traceevt,traceevt_desc) - E(traceses,traceses_desc) - E(traceapi,traceapi_desc) - - B(no_ldpaths) - B(no_httpd) - B(background) -#if defined(WITH_MONITORING_OPTION) - B(monitoring) -#endif - B(random_token) - -#undef E -#undef B -#undef D -#undef L -#undef V -#undef S - -#undef RB -#undef RI -#undef RA -#undef RS -#undef RS -#undef AS -#undef AO - -#undef YS -#undef XO -#undef XA - - return r; + return NULL; } diff --git a/src/afb-config.h b/src/afb-config.h index c3900082..5b45a00f 100644 --- a/src/afb-config.h +++ b/src/afb-config.h @@ -18,78 +18,5 @@ struct json_object; -/* - * other definitions --------------------------------------------------- - */ - -/** - * list of configuration values - */ -struct afb_config_list { - struct afb_config_list *next; - char *value; -}; - -/** - * main config structure - */ -struct afb_config { - char *console; /*< console device name (can be a file or a tty) */ - char *rootdir; /*< base dir for files */ - char *roothttp; /*< directory for http files */ - char *rootbase; /*< Angular HTML5 base URL */ - char *rootapi; /*< Base URL for REST APIs */ - char *workdir; /*< where to run the program */ - char *uploaddir; /*< where to store transient files */ - char *token; /*< initial authentication token [default NULL no session] */ - char *name; /*< name to set to the daemon */ - - struct afb_config_list *aliases; -#if defined(WITH_DBUS_TRANSPARENCY) - struct afb_config_list *dbus_clients; - struct afb_config_list *dbus_servers; -#endif - struct afb_config_list *ws_clients; - struct afb_config_list *ws_servers; - struct afb_config_list *so_bindings; - struct afb_config_list *ldpaths; - struct afb_config_list *weak_ldpaths; - struct afb_config_list *calls; - struct afb_config_list *auto_api; - - char **exec; - - /* integers */ - int http_port; - int cache_timeout; - int api_timeout; - int session_timeout; /*< session timeout */ - int max_session_count; /*< max count of sessions */ - - /* enums */ -#if defined(KEEP_LEGACY_MODE) - int mode; // mode of listening -#endif - int tracereq; -#if !defined(REMOVE_LEGACY_TRACE) - int traceditf; - int tracesvc; -#endif - int traceevt; - int traceses; - int traceapi; - - /* booleans */ - unsigned no_ldpaths: 1; /**< disable default ldpaths */ - unsigned no_httpd: 1; - unsigned background: 1; /**< run in backround mode */ - unsigned random_token: 1; /**< expects a random token */ -#if defined(WITH_MONITORING_OPTION) - unsigned monitoring: 1; /**< activates monitoring */ -#endif -}; - -extern struct afb_config *afb_config_parse_arguments(int argc, char **argv); -extern void afb_config_dump(struct afb_config *config); -extern struct json_object *afb_config_json(struct afb_config *config); +extern struct json_object *afb_config_parse_arguments(int argc, char **argv); diff --git a/src/afb-hook-flags.c b/src/afb-hook-flags.c new file mode 100644 index 00000000..738e54ce --- /dev/null +++ b/src/afb-hook-flags.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author José Bollo + * + * 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 +#include +#include + +#include "afb-hook.h" +#include "afb-hook-flags.h" + +/* structure for searching flags by names */ +struct flag +{ + const char *name; /** the name */ + int value; /** the value */ +}; + +struct flags +{ + struct flag *flags; + int count; +}; + +#define FLAGS(x) ((struct flags){ .flags = x, .count = (int)(sizeof x / sizeof * x) }) + +static struct flag xreq_flags[] = { /* must be sorted by names */ + { "addref", afb_hook_flag_req_addref }, + { "all", afb_hook_flags_req_all }, + { "args", afb_hook_flags_req_args }, + { "begin", afb_hook_flag_req_begin }, + { "common", afb_hook_flags_req_common }, + { "context", afb_hook_flags_req_context }, + { "context_get", afb_hook_flag_req_legacy_context_get }, + { "context_make", afb_hook_flag_req_context_make }, + { "context_set", afb_hook_flag_req_legacy_context_set }, + { "end", afb_hook_flag_req_end }, + { "event", afb_hook_flags_req_event }, + { "extra", afb_hook_flags_req_extra }, + { "get", afb_hook_flag_req_get }, + { "get_application_id", afb_hook_flag_req_get_application_id }, + { "get_client_info", afb_hook_flag_req_get_client_info }, + { "get_uid", afb_hook_flag_req_get_uid }, + { "has_permission", afb_hook_flag_req_has_permission }, + { "json", afb_hook_flag_req_json }, + { "life", afb_hook_flags_req_life }, + { "ref", afb_hook_flags_req_ref }, + { "reply", afb_hook_flag_req_reply }, + { "security", afb_hook_flags_req_security }, + { "session", afb_hook_flags_req_session }, + { "session_close", afb_hook_flag_req_session_close }, + { "session_set_LOA", afb_hook_flag_req_session_set_LOA }, + { "store", afb_hook_flag_req_legacy_store }, + { "stores", afb_hook_flags_req_stores }, + { "subcall", afb_hook_flag_req_subcall }, + { "subcall_result", afb_hook_flag_req_subcall_result }, + { "subcalls", afb_hook_flags_req_subcalls }, + { "subcallsync", afb_hook_flag_req_subcallsync }, + { "subcallsync_result", afb_hook_flag_req_subcallsync_result }, + { "subscribe", afb_hook_flag_req_subscribe }, + { "unref", afb_hook_flag_req_unref }, + { "unstore", afb_hook_flag_req_legacy_unstore }, + { "unsubscribe", afb_hook_flag_req_unsubscribe }, + { "vverbose", afb_hook_flag_req_vverbose }, +}; + +static struct flag api_flags[] = { /* must be sorted by names */ + { "add_alias", afb_hook_flag_api_add_alias }, + { "all", afb_hook_flags_api_all }, + { "api_add_verb", afb_hook_flag_api_api_add_verb }, + { "api", afb_hook_flags_api_api }, + { "api_del_verb", afb_hook_flag_api_api_del_verb }, + { "api_seal", afb_hook_flag_api_api_seal }, + { "api_set_on_event", afb_hook_flag_api_api_set_on_event }, + { "api_set_on_init", afb_hook_flag_api_api_set_on_init }, + { "api_set_verbs", afb_hook_flag_api_api_set_verbs }, + { "call", afb_hook_flag_api_call }, + { "callsync", afb_hook_flag_api_callsync }, + { "class_provide", afb_hook_flag_api_class_provide }, + { "class_require", afb_hook_flag_api_class_require }, + { "common", afb_hook_flags_api_common }, + { "delete_api", afb_hook_flag_api_delete_api }, + { "event", afb_hook_flags_api_event }, + { "event_broadcast", afb_hook_flag_api_event_broadcast }, + { "event_handler_add", afb_hook_flag_api_event_handler_add }, + { "event_handler_del", afb_hook_flag_api_event_handler_del }, + { "event_make", afb_hook_flag_api_event_make }, + { "extra", afb_hook_flags_api_extra }, + { "get_event_loop", afb_hook_flag_api_get_event_loop }, + { "get_system_bus", afb_hook_flag_api_get_system_bus }, + { "get_user_bus", afb_hook_flag_api_get_user_bus }, + { "legacy_unstore_req", afb_hook_flag_api_legacy_unstore_req }, + { "new_api", afb_hook_flag_api_new_api }, + { "on_event", afb_hook_flag_api_on_event }, + { "on_event_handler", afb_hook_flag_api_on_event_handler }, + { "queue_job", afb_hook_flag_api_queue_job }, + { "require_api", afb_hook_flag_api_require_api }, + { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd }, + { "rootdir_open_locale",afb_hook_flag_api_rootdir_open_locale }, + { "start", afb_hook_flag_api_start }, + { "vverbose", afb_hook_flag_api_vverbose }, +}; + +static struct flag evt_flags[] = { /* must be sorted by names */ + { "addref", afb_hook_flag_evt_addref }, + { "all", afb_hook_flags_evt_all }, + { "broadcast_after", afb_hook_flag_evt_broadcast_after }, + { "broadcast_before", afb_hook_flag_evt_broadcast_before }, + { "common", afb_hook_flags_evt_common }, + { "create", afb_hook_flag_evt_create }, + { "extra", afb_hook_flags_evt_extra }, + { "name", afb_hook_flag_evt_name }, + { "push_after", afb_hook_flag_evt_push_after }, + { "push_before", afb_hook_flag_evt_push_before }, + { "unref", afb_hook_flag_evt_unref }, +}; + +static struct flag session_flags[] = { /* must be sorted by names */ + { "addref", afb_hook_flag_session_addref }, + { "all", afb_hook_flags_session_all }, + { "close", afb_hook_flag_session_close }, + { "common", afb_hook_flags_session_common }, + { "create", afb_hook_flag_session_create }, + { "destroy", afb_hook_flag_session_destroy }, + { "renew", afb_hook_flag_session_renew }, + { "unref", afb_hook_flag_session_unref }, +}; + +static struct flag global_flags[] = { /* must be sorted by names */ + { "all", afb_hook_flags_global_all }, + { "vverbose", afb_hook_flag_global_vverbose }, +}; + +static int compare(const char *query, const char *value, size_t query_length) +{ + size_t i; + char q, v; + + for (i = 0 ; i < query_length ; i++) { + v = value[i]; + q = query[i]; + if (!v) + return -1; + v = v == '_' ? '-' : (char)toupper(v); + q = q == '_' ? '-' : (char)toupper(q); + if (q != v) + return (int)((unsigned)q - (unsigned)v); + } + return !!value[i]; +} + +/* get the value of the flag of 'name' in the array 'flags' of 'count elements */ +static int get_flag(const char *name, struct flags flags, size_t length) +{ + /* replace "*" by "all" */ + if (length == 1 && *name == '*') { + name = "all"; + length = 3; + } + + /* dichotomic search */ + int lower = 0, upper = flags.count; + while (lower < upper) { + int mid = (lower + upper) >> 1; + int cmp = compare(name, flags.flags[mid].name, length); + if (!cmp) + return flags.flags[mid].value; + if (cmp < 0) + upper = mid; + else + lower = mid + 1; + } + + return -(compare(name, "no", length) && compare(name, "none", length)); +} + +static int from_text(const char *text, struct flags flags) +{ + static const char sep[] = " \t,"; + size_t s; + int result = 0, val; + + if (text) { + for (;;) { + text += strspn(text, sep); + if (!*text) + break; + s = strcspn(text, sep); + val = get_flag(text, flags, s); + if (val == -1) + return val; + result |= val; + text += s; + } + } + return result; +} + +static char *to_text(int value, struct flags flags) +{ + int borrow = 0, mask = 0, i, v, imask; + size_t s = 0; + char *result; + + if (!value) + return strdup("none"); + + do { + if (s) { + result = malloc(s + 1); + if (!result) + break; + } + borrow = 0; + while (borrow != value) { + mask = 0; + i = flags.count; + while (i) { + v = flags.flags[--i].value; + if ((mask & v) == mask && (borrow & v) == 0 && (value & v) == v) { + mask = v; + imask = i; + } + } + if (mask == 0) + borrow = value; + else { + if (!result) + s += strlen(flags.flags[imask].name) + !!s; + else { + if (s) + result[s++] = ','; + strcpy(&result[s], flags.flags[imask].name); + s += strlen(flags.flags[imask].name); + } + } + } + } while (!result); + return result; +} + +int afb_hook_flags_xreq_from_text(const char *text) +{ + return from_text(text, FLAGS(xreq_flags)); +} + +int afb_hook_flags_api_from_text(const char *text) +{ + return from_text(text, FLAGS(api_flags)); +} + +int afb_hook_flags_evt_from_text(const char *text) +{ + return from_text(text, FLAGS(evt_flags)); +} + +int afb_hook_flags_session_from_text(const char *text) +{ + return from_text(text, FLAGS(session_flags)); +} + +int afb_hook_flags_global_from_text(const char *text) +{ + return from_text(text, FLAGS(global_flags)); +} + +char *afb_hook_flags_xreq_to_text(int value) +{ + return to_text(value, FLAGS(xreq_flags)); +} + +char *afb_hook_flags_api_to_text(int value) +{ + return to_text(value, FLAGS(api_flags)); +} + +char *afb_hook_flags_evt_to_text(int value) +{ + return to_text(value, FLAGS(evt_flags)); +} + +char *afb_hook_flags_session_to_text(int value) +{ + return to_text(value, FLAGS(session_flags)); +} + +char *afb_hook_flags_global_to_text(int value) +{ + return to_text(value, FLAGS(global_flags)); +} + +#if !defined(REMOVE_LEGACY_TRACE) +static struct flag legacy_ditf_flags[] = { /* must be sorted by names */ + { "all", afb_hook_flags_api_ditf_all }, + { "common", afb_hook_flags_api_ditf_common }, + { "event_broadcast_after", afb_hook_flag_api_event_broadcast }, + { "event_broadcast_before", afb_hook_flag_api_event_broadcast }, + { "event_make", afb_hook_flag_api_event_make }, + { "extra", afb_hook_flags_api_ditf_extra }, + { "get_event_loop", afb_hook_flag_api_get_event_loop }, + { "get_system_bus", afb_hook_flag_api_get_system_bus }, + { "get_user_bus", afb_hook_flag_api_get_user_bus }, + { "queue_job", afb_hook_flag_api_queue_job }, + { "require_api", afb_hook_flag_api_require_api }, + { "require_api_result", afb_hook_flag_api_require_api }, + { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd }, + { "rootdir_open_locale", afb_hook_flag_api_rootdir_open_locale }, + { "unstore_req", afb_hook_flag_api_legacy_unstore_req }, + { "vverbose", afb_hook_flag_api_vverbose }, +}; + +static struct flag legacy_svc_flags[] = { /* must be sorted by names */ + { "all", afb_hook_flags_api_svc_all }, + { "call", afb_hook_flag_api_call }, + { "call_result", afb_hook_flag_api_call }, + { "callsync", afb_hook_flag_api_callsync }, + { "callsync_result", afb_hook_flag_api_callsync }, + { "on_event_after", afb_hook_flag_api_on_event }, + { "on_event_before", afb_hook_flag_api_on_event }, + { "start_after", afb_hook_flag_api_start }, + { "start_before", afb_hook_flag_api_start }, +}; + +int afb_hook_flags_legacy_ditf_from_text(const char *text) +{ + return from_text(text, FLAGS(legacy_ditf_flags)); +} + +int afb_hook_flags_legacy_svc_from_text(const char *text) +{ + return from_text(text, FLAGS(legacy_svc_flags)); +} + +char *afb_hook_flags_legacy_ditf_to_text(int value) +{ + return to_text(value, FLAGS(legacy_ditf_flags)); +} + +char *afb_hook_flags_legacy_svc_to_text(int value) +{ + return to_text(value, FLAGS(legacy_svc_flags)); +} +#endif + diff --git a/src/afb-hook-flags.h b/src/afb-hook-flags.h new file mode 100644 index 00000000..5b373c25 --- /dev/null +++ b/src/afb-hook-flags.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author José Bollo + * + * 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 + +extern int afb_hook_flags_xreq_from_text(const char *text); +extern int afb_hook_flags_api_from_text(const char *text); +extern int afb_hook_flags_evt_from_text(const char *text); +extern int afb_hook_flags_session_from_text(const char *text); +extern int afb_hook_flags_global_from_text(const char *text); + +extern char *afb_hook_flags_xreq_to_text(int value); +extern char *afb_hook_flags_api_to_text(int value); +extern char *afb_hook_flags_evt_to_text(int value); +extern char *afb_hook_flags_session_to_text(int value); + +#if !defined(REMOVE_LEGACY_TRACE) +extern int afb_hook_flags_legacy_ditf_from_text(const char *text); +extern int afb_hook_flags_legacy_svc_from_text(const char *text); + +extern char *afb_hook_flags_legacy_ditf_to_text(int value); +extern char *afb_hook_flags_legacy_svc_to_text(int value); +#endif + diff --git a/src/afb-supervision.c b/src/afb-supervision.c index 2482a082..8636ef03 100644 --- a/src/afb-supervision.c +++ b/src/afb-supervision.c @@ -64,7 +64,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* the standard apiset */ static struct { struct afb_apiset *apiset; - struct afb_config *config; + struct json_object *config; } global; /* the supervision apiset (not exported) */ @@ -238,7 +238,7 @@ static void on_sighup(int signum) /** * initialize the supervision */ -int afb_supervision_init(struct afb_apiset *apiset, struct afb_config *config) +int afb_supervision_init(struct afb_apiset *apiset, struct json_object *config) { int rc; struct sigaction sa; @@ -351,7 +351,7 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq) afb_xreq_reply(xreq, list, NULL, NULL); break; case Config: - afb_xreq_reply(xreq, afb_config_json(global.config), NULL, NULL); + afb_xreq_reply(xreq, json_object_get(global.config), NULL, NULL); break; case Trace: if (!trace) diff --git a/src/afb-supervision.h b/src/afb-supervision.h index 0acf7f6e..a7c0f1e1 100644 --- a/src/afb-supervision.h +++ b/src/afb-supervision.h @@ -19,6 +19,6 @@ #pragma once struct afb_apiset; -struct afb_config; +struct json_object; -extern int afb_supervision_init(struct afb_apiset *apiset, struct afb_config *config); +extern int afb_supervision_init(struct afb_apiset *apiset, struct json_object *config); diff --git a/src/afb-trace.c b/src/afb-trace.c index d81e09c2..3f773953 100644 --- a/src/afb-trace.c +++ b/src/afb-trace.c @@ -35,6 +35,7 @@ #include #include "afb-hook.h" +#include "afb-hook-flags.h" #include "afb-cred.h" #include "afb-session.h" #include "afb-xreq.h" @@ -61,13 +62,6 @@ /***** types *****/ /*******************************************************************************/ -/* structure for searching flags by names */ -struct flag -{ - const char *name; /** the name */ - int value; /** the value */ -}; - /* struct for tags */ struct tag { struct tag *next; /* link to the next */ @@ -151,24 +145,6 @@ static void ctxt_error(char **errors, const char *format, ...) } } -/* get the value of the flag of 'name' in the array 'flags' of 'count elements */ -static int get_flag(const char *name, struct flag flags[], int count) -{ - /* dichotomic search */ - int lower = 0, upper = count; - while (lower < upper) { - int mid = (lower + upper) >> 1; - int cmp = strcmp(name, flags[mid].name); - if (!cmp) - return flags[mid].value; - if (cmp < 0) - upper = mid; - else - lower = mid + 1; - } - return 0; -} - /* timestamp */ static struct json_object *timestamp(const struct afb_hookid *hookid) { @@ -181,7 +157,7 @@ static struct json_object *timestamp(const struct afb_hookid *hookid) return json_object_new_double_s(0.0f, ts); /* the real value isn't used */ #else - return json_object_new_double((double)hookid->time.tv_sec + + return json_object_new_double((double)hookid->time.tv_sec + (double)hookid->time.tv_nsec * .000000001); #endif } @@ -229,52 +205,6 @@ static void emit(void *closure, const struct afb_hookid *hookid, const char *typ /***** trace the requests *****/ /*******************************************************************************/ -static struct flag xreq_flags[] = { /* must be sorted by names */ - { "addref", afb_hook_flag_req_addref }, - { "all", afb_hook_flags_req_all }, - { "args", afb_hook_flags_req_args }, - { "begin", afb_hook_flag_req_begin }, - { "common", afb_hook_flags_req_common }, - { "context", afb_hook_flags_req_context }, - { "context_get", afb_hook_flag_req_legacy_context_get }, - { "context_make", afb_hook_flag_req_context_make }, - { "context_set", afb_hook_flag_req_legacy_context_set }, - { "end", afb_hook_flag_req_end }, - { "event", afb_hook_flags_req_event }, - { "extra", afb_hook_flags_req_extra }, - { "get", afb_hook_flag_req_get }, - { "get_application_id", afb_hook_flag_req_get_application_id }, - { "get_client_info", afb_hook_flag_req_get_client_info }, - { "get_uid", afb_hook_flag_req_get_uid }, - { "has_permission", afb_hook_flag_req_has_permission }, - { "json", afb_hook_flag_req_json }, - { "life", afb_hook_flags_req_life }, - { "ref", afb_hook_flags_req_ref }, - { "reply", afb_hook_flag_req_reply }, - { "security", afb_hook_flags_req_security }, - { "session", afb_hook_flags_req_session }, - { "session_close", afb_hook_flag_req_session_close }, - { "session_set_LOA", afb_hook_flag_req_session_set_LOA }, - { "store", afb_hook_flag_req_legacy_store }, - { "stores", afb_hook_flags_req_stores }, - { "subcall", afb_hook_flag_req_subcall }, - { "subcall_result", afb_hook_flag_req_subcall_result }, - { "subcalls", afb_hook_flags_req_subcalls }, - { "subcallsync", afb_hook_flag_req_subcallsync }, - { "subcallsync_result", afb_hook_flag_req_subcallsync_result }, - { "subscribe", afb_hook_flag_req_subscribe }, - { "unref", afb_hook_flag_req_unref }, - { "unstore", afb_hook_flag_req_legacy_unstore }, - { "unsubscribe", afb_hook_flag_req_unsubscribe }, - { "vverbose", afb_hook_flag_req_vverbose }, -}; - -/* get the xreq value for flag of 'name' */ -static int get_xreq_flag(const char *name) -{ - return get_flag(name, xreq_flags, (int)(sizeof xreq_flags / sizeof *xreq_flags)); -} - static void hook_xreq(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *action, const char *format, ...) { struct json_object *cred = NULL; @@ -529,94 +459,6 @@ static struct afb_hook_xreq_itf hook_xreq_itf = { /***** trace the api interface *****/ /*******************************************************************************/ -#if !defined(REMOVE_LEGACY_TRACE) -static struct flag legacy_ditf_flags[] = { /* must be sorted by names */ - { "all", afb_hook_flags_api_ditf_all }, - { "common", afb_hook_flags_api_ditf_common }, - { "event_broadcast_after", afb_hook_flag_api_event_broadcast }, - { "event_broadcast_before", afb_hook_flag_api_event_broadcast }, - { "event_make", afb_hook_flag_api_event_make }, - { "extra", afb_hook_flags_api_ditf_extra }, - { "get_event_loop", afb_hook_flag_api_get_event_loop }, - { "get_system_bus", afb_hook_flag_api_get_system_bus }, - { "get_user_bus", afb_hook_flag_api_get_user_bus }, - { "queue_job", afb_hook_flag_api_queue_job }, - { "require_api", afb_hook_flag_api_require_api }, - { "require_api_result", afb_hook_flag_api_require_api }, - { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd }, - { "rootdir_open_locale", afb_hook_flag_api_rootdir_open_locale }, - { "unstore_req", afb_hook_flag_api_legacy_unstore_req }, - { "vverbose", afb_hook_flag_api_vverbose }, -}; - -static struct flag legacy_svc_flags[] = { /* must be sorted by names */ - { "all", afb_hook_flags_api_svc_all }, - { "call", afb_hook_flag_api_call }, - { "call_result", afb_hook_flag_api_call }, - { "callsync", afb_hook_flag_api_callsync }, - { "callsync_result", afb_hook_flag_api_callsync }, - { "on_event_after", afb_hook_flag_api_on_event }, - { "on_event_before", afb_hook_flag_api_on_event }, - { "start_after", afb_hook_flag_api_start }, - { "start_before", afb_hook_flag_api_start }, -}; - -/* get the export value for flag of 'name' */ -static int get_legacy_ditf_flag(const char *name) -{ - return get_flag(name, legacy_ditf_flags, (int)(sizeof legacy_ditf_flags / sizeof *legacy_ditf_flags)); -} - -/* get the export value for flag of 'name' */ -static int get_legacy_svc_flag(const char *name) -{ - return get_flag(name, legacy_svc_flags, (int)(sizeof legacy_svc_flags / sizeof *legacy_svc_flags)); -} -#endif - -static struct flag api_flags[] = { /* must be sorted by names */ - { "add_alias", afb_hook_flag_api_add_alias }, - { "all", afb_hook_flags_api_all }, - { "api_add_verb", afb_hook_flag_api_api_add_verb }, - { "api", afb_hook_flags_api_api }, - { "api_del_verb", afb_hook_flag_api_api_del_verb }, - { "api_seal", afb_hook_flag_api_api_seal }, - { "api_set_on_event", afb_hook_flag_api_api_set_on_event }, - { "api_set_on_init", afb_hook_flag_api_api_set_on_init }, - { "api_set_verbs", afb_hook_flag_api_api_set_verbs }, - { "call", afb_hook_flag_api_call }, - { "callsync", afb_hook_flag_api_callsync }, - { "class_provide", afb_hook_flag_api_class_provide }, - { "class_require", afb_hook_flag_api_class_require }, - { "common", afb_hook_flags_api_common }, - { "delete_api", afb_hook_flag_api_delete_api }, - { "event", afb_hook_flags_api_event }, - { "event_broadcast", afb_hook_flag_api_event_broadcast }, - { "event_handler_add", afb_hook_flag_api_event_handler_add }, - { "event_handler_del", afb_hook_flag_api_event_handler_del }, - { "event_make", afb_hook_flag_api_event_make }, - { "extra", afb_hook_flags_api_extra }, - { "get_event_loop", afb_hook_flag_api_get_event_loop }, - { "get_system_bus", afb_hook_flag_api_get_system_bus }, - { "get_user_bus", afb_hook_flag_api_get_user_bus }, - { "legacy_unstore_req", afb_hook_flag_api_legacy_unstore_req }, - { "new_api", afb_hook_flag_api_new_api }, - { "on_event", afb_hook_flag_api_on_event }, - { "on_event_handler", afb_hook_flag_api_on_event_handler }, - { "queue_job", afb_hook_flag_api_queue_job }, - { "require_api", afb_hook_flag_api_require_api }, - { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd }, - { "rootdir_open_locale",afb_hook_flag_api_rootdir_open_locale }, - { "start", afb_hook_flag_api_start }, - { "vverbose", afb_hook_flag_api_vverbose }, -}; - -/* get the export value for flag of 'name' */ -static int get_api_flag(const char *name) -{ - return get_flag(name, api_flags, (int)(sizeof api_flags / sizeof *api_flags)); -} - static void hook_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...) { va_list ap; @@ -918,26 +760,6 @@ static struct afb_hook_api_itf hook_api_itf = { /***** trace the events *****/ /*******************************************************************************/ -static struct flag evt_flags[] = { /* must be sorted by names */ - { "addref", afb_hook_flag_evt_addref }, - { "all", afb_hook_flags_evt_all }, - { "broadcast_after", afb_hook_flag_evt_broadcast_after }, - { "broadcast_before", afb_hook_flag_evt_broadcast_before }, - { "common", afb_hook_flags_evt_common }, - { "create", afb_hook_flag_evt_create }, - { "extra", afb_hook_flags_evt_extra }, - { "name", afb_hook_flag_evt_name }, - { "push_after", afb_hook_flag_evt_push_after }, - { "push_before", afb_hook_flag_evt_push_before }, - { "unref", afb_hook_flag_evt_unref }, -}; - -/* get the evt value for flag of 'name' */ -static int get_evt_flag(const char *name) -{ - return get_flag(name, evt_flags, (int)(sizeof evt_flags / sizeof *evt_flags)); -} - static void hook_evt(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *action, const char *format, ...) { va_list ap; @@ -1006,23 +828,6 @@ static struct afb_hook_evt_itf hook_evt_itf = { /***** trace the sessions *****/ /*******************************************************************************/ -static struct flag session_flags[] = { /* must be sorted by names */ - { "addref", afb_hook_flag_session_addref }, - { "all", afb_hook_flags_session_all }, - { "close", afb_hook_flag_session_close }, - { "common", afb_hook_flags_session_common }, - { "create", afb_hook_flag_session_create }, - { "destroy", afb_hook_flag_session_destroy }, - { "renew", afb_hook_flag_session_renew }, - { "unref", afb_hook_flag_session_unref }, -}; - -/* get the session value for flag of 'name' */ -static int get_session_flag(const char *name) -{ - return get_flag(name, session_flags, (int)(sizeof session_flags / sizeof *session_flags)); -} - static void hook_session(void *closure, const struct afb_hookid *hookid, struct afb_session *session, const char *action, const char *format, ...) { va_list ap; @@ -1077,17 +882,6 @@ static struct afb_hook_session_itf hook_session_itf = { /***** trace the globals *****/ /*******************************************************************************/ -static struct flag global_flags[] = { /* must be sorted by names */ - { "all", afb_hook_flags_global_all }, - { "vverbose", afb_hook_flag_global_vverbose }, -}; - -/* get the global value for flag of 'name' */ -static int get_global_flag(const char *name) -{ - return get_flag(name, global_flags, (int)(sizeof global_flags / sizeof *global_flags)); -} - static void hook_global(void *closure, const struct afb_hookid *hookid, const char *action, const char *format, ...) { va_list ap; @@ -1144,44 +938,44 @@ abstracting[Trace_Type_Count] = { .name = "request", .unref = (void(*)(void*))afb_hook_unref_xreq, - .get_flag = get_xreq_flag + .get_flag = afb_hook_flags_xreq_from_text }, [Trace_Type_Api] = { .name = "api", .unref = (void(*)(void*))afb_hook_unref_api, - .get_flag = get_api_flag + .get_flag = afb_hook_flags_api_from_text }, [Trace_Type_Evt] = { .name = "event", .unref = (void(*)(void*))afb_hook_unref_evt, - .get_flag = get_evt_flag + .get_flag = afb_hook_flags_evt_from_text }, [Trace_Type_Session] = { .name = "session", .unref = (void(*)(void*))afb_hook_unref_session, - .get_flag = get_session_flag + .get_flag = afb_hook_flags_session_from_text }, [Trace_Type_Global] = { .name = "global", .unref = (void(*)(void*))afb_hook_unref_global, - .get_flag = get_global_flag + .get_flag = afb_hook_flags_global_from_text }, #if !defined(REMOVE_LEGACY_TRACE) [Trace_Legacy_Type_Ditf] = { .name = "daemon", .unref = (void(*)(void*))afb_hook_unref_api, - .get_flag = get_legacy_ditf_flag + .get_flag = afb_hook_flags_legacy_ditf_from_text }, [Trace_Legacy_Type_Svc] = { .name = "service", .unref = (void(*)(void*))afb_hook_unref_api, - .get_flag = get_legacy_svc_flag + .get_flag = afb_hook_flags_legacy_svc_from_text }, #endif }; diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index 721faf2f..3f32e879 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -54,8 +54,10 @@ #include "afb-common.h" #include "afb-monitor.h" #include "afb-hook.h" +#include "afb-hook-flags.h" #include "afb-debug.h" #include "process-name.h" +#include "wrap-json.h" #if defined(WITH_SUPERVISION) # include "afb-supervision.h" #endif @@ -67,7 +69,7 @@ #define SELF_PGROUP 0 struct afb_apiset *main_apiset; -struct afb_config *main_config; +struct json_object *main_config; static pid_t childpid; @@ -75,35 +77,40 @@ static pid_t childpid; | helpers for handling list of arguments +--------------------------------------------------------- */ -/* - * Calls the callback 'run' for each value of the 'list' - * until the callback returns 0 or the end of the list is reached. - * Returns either NULL if the end of the list is reached or a pointer - * to the item whose value made 'run' return 0. - * 'closure' is used for passing user data. - */ -static struct afb_config_list *run_for_list(struct afb_config_list *list, - int (*run) (void *closure, char *value), +static const char *run_for_config_array_opt(const char *name, + int (*run) (void *closure, const char *value), void *closure) { - while (list && run(closure, list->value)) - list = list->next; - return list; + int i, n, rc; + struct json_object *array, *value; + + if (json_object_object_get_ex(main_config, name, &array)) { + if (!json_object_is_type(array, json_type_array)) + return json_object_get_string(array); + n = (int)json_object_array_length(array); + for (i = 0 ; i < n ; i++) { + value = json_object_array_get_idx(array, i); + rc = run(closure, json_object_get_string(value)); + if (!rc) + return json_object_get_string(value); + } + } + return NULL; } -static int run_start(void *closure, char *value) +static int run_start(void *closure, const char *value) { int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set) = closure; return starter(value, main_apiset, main_apiset) >= 0; } -static void apiset_start_list(struct afb_config_list *list, +static void apiset_start_list(const char *name, int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set), const char *message) { - list = run_for_list(list, run_start, starter); - if (list) { - ERROR("can't start %s %s", message, list->value); + const char *item = run_for_config_array_opt(name, run_start, starter); + if (item) { + ERROR("can't start %s %s", message, item); exit(1); } } @@ -165,50 +172,53 @@ static void setup_daemon() +--------------------------------------------------------- */ static void daemonize() { - int consoleFD; - int pid; + int fd, daemon; + const char *output; + pid_t pid; + + daemon = 0; + output = NULL; + wrap_json_unpack(main_config, "{s?b s?s}", "daemon", &daemon, "output", &output); + + if (output) { + fd = open(output, O_WRONLY | O_APPEND | O_CREAT, 0640); + if (fd < 0) { + ERROR("Can't open output %s", output); + exit(1); + } + } - // open /dev/console to redirect output messAFBes - consoleFD = open(main_config->console, O_WRONLY | O_APPEND | O_CREAT, 0640); - if (consoleFD < 0) { - ERROR("AFB-daemon cannot open /dev/console (use --foreground)"); - exit(1); + if (daemon) { + INFO("entering background mode"); + + pid = fork(); + if (pid == -1) { + ERROR("Failed to fork daemon process"); + exit(1); + } + if (pid != 0) + _exit(0); } - // fork process when running background mode - pid = fork(); - // if fail nothing much to do - if (pid == -1) { - ERROR("AFB-daemon Failed to fork son process"); - exit(1); + /* closes the input */ + if (output) { + NOTICE("Redirecting output to %s", output); + close(2); + dup(fd); + close(1); + dup(fd); + close(fd); } - // if in father process, just leave - if (pid != 0) - _exit(0); - - // son process get all data in standalone mode - NOTICE("background mode [pid:%d console:%s]", getpid(), - main_config->console); - - // redirect default I/O on console - close(2); - dup(consoleFD); // redirect stderr - close(1); - dup(consoleFD); // redirect stdout - close(0); // no need for stdin - close(consoleFD); - -#if 0 - setsid(); // allow father process to fully exit - sleep(2); // allow main to leave and release port -#endif + + /* after that ctrl+C still works */ + close(0); } /*--------------------------------------------------------- | http server | Handles the HTTP server +--------------------------------------------------------- */ -static int init_alias(void *closure, char *spec) +static int init_alias(void *closure, const char *spec) { struct afb_hsrv *hsrv = closure; char *path = strchr(spec, ':'); @@ -225,27 +235,38 @@ static int init_alias(void *closure, char *spec) static int init_http_server(struct afb_hsrv *hsrv) { - if (!afb_hsrv_add_handler - (hsrv, main_config->rootapi, afb_hswitch_websocket_switch, main_apiset, 20)) + int rc; + const char *rootapi, *roothttp, *rootbase; + + roothttp = NULL; + rc = wrap_json_unpack(main_config, "{ss ss s?s}", + "rootapi", &rootapi, + "rootbase", &rootbase, + "roothttp", &roothttp); + if (rc < 0) { + ERROR("Can't get HTTP server config"); + exit(1); + } + + if (!afb_hsrv_add_handler(hsrv, rootapi, + afb_hswitch_websocket_switch, main_apiset, 20)) return 0; - if (!afb_hsrv_add_handler - (hsrv, main_config->rootapi, afb_hswitch_apis, main_apiset, 10)) + if (!afb_hsrv_add_handler(hsrv, rootapi, + afb_hswitch_apis, main_apiset, 10)) return 0; - if (run_for_list(main_config->aliases, init_alias, hsrv)) + if (run_for_config_array_opt("alias", init_alias, hsrv)) return 0; - if (main_config->roothttp != NULL) { - if (!afb_hsrv_add_alias - (hsrv, "", afb_common_rootdir_get_fd(), main_config->roothttp, - -10, 1)) + if (roothttp != NULL) { + if (!afb_hsrv_add_alias(hsrv, "", + afb_common_rootdir_get_fd(), roothttp, -10, 1)) return 0; } - if (!afb_hsrv_add_handler - (hsrv, main_config->rootbase, afb_hswitch_one_page_api_redirect, NULL, - -20)) + if (!afb_hsrv_add_handler(hsrv, rootbase, + afb_hswitch_one_page_api_redirect, NULL, -20)) return 0; return 1; @@ -254,10 +275,22 @@ static int init_http_server(struct afb_hsrv *hsrv) static struct afb_hsrv *start_http_server() { int rc; + const char *uploaddir, *rootdir; struct afb_hsrv *hsrv; + int cache_timeout, http_port; + + rc = wrap_json_unpack(main_config, "{ss ss si si}", + "uploaddir", &uploaddir, + "rootdir", &rootdir, + "cache-eol", &cache_timeout, + "port", &http_port); + if (rc < 0) { + ERROR("Can't get HTTP server start config"); + exit(1); + } - if (afb_hreq_init_download_path(main_config->uploaddir)) { - ERROR("unable to set the upload directory %s", main_config->uploaddir); + if (afb_hreq_init_download_path(uploaddir)) { + ERROR("unable to set the upload directory %s", uploaddir); return NULL; } @@ -267,17 +300,17 @@ static struct afb_hsrv *start_http_server() return NULL; } - if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cache_timeout) + if (!afb_hsrv_set_cache_timeout(hsrv, cache_timeout) || !init_http_server(hsrv)) { ERROR("initialisation of httpd failed"); afb_hsrv_put(hsrv); return NULL; } - NOTICE("Waiting port=%d rootdir=%s", main_config->http_port, main_config->rootdir); - NOTICE("Browser URL= http://localhost:%d", main_config->http_port); + NOTICE("Waiting port=%d rootdir=%s", http_port, rootdir); + NOTICE("Browser URL= http://localhost:%d", http_port); - rc = afb_hsrv_start(hsrv, (uint16_t) main_config->http_port, 15); + rc = afb_hsrv_start(hsrv, (uint16_t) http_port, 15); if (!rc) { ERROR("starting of httpd failed"); afb_hsrv_put(hsrv); @@ -316,7 +349,7 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctx) #define SUBST_CHAR '@' #define SUBST_STR "@" -static char *instanciate_string(char *arg, const char *port, const char *token) +static char *instanciate_string(const char *arg, const char *port, const char *token) { char *resu, *it, *wr; int chg, dif; @@ -337,7 +370,7 @@ static char *instanciate_string(char *arg, const char *port, const char *token) /* return arg when no change */ if (!chg) - return arg; + return strdup(arg); /* allocates the result */ resu = malloc((it - arg) + dif + 1); @@ -372,7 +405,7 @@ static int instanciate_environ(const char *port, const char *token) char *repl; int i; - /* instanciate the environment */ + /* instantiate the environment */ for (i = 0 ; environ[i] ; i++) { repl = instanciate_string(environ[i], port, token); if (!repl) @@ -382,30 +415,46 @@ static int instanciate_environ(const char *port, const char *token) return 0; } -static int instanciate_command_args(const char *port, const char *token) +static char **instanciate_command_args(struct json_object *exec, const char *port, const char *token) { + char **result; char *repl; - int i; + int i, n; + + /* allocates the result */ + n = (int)json_object_array_length(exec); + result = malloc((n + 1) * sizeof * result); + if (!result) { + ERROR("out of memory"); + return NULL; + } /* instanciate the arguments */ - for (i = 0 ; main_config->exec[i] ; i++) { - repl = instanciate_string(main_config->exec[i], port, token); - if (!repl) - return -1; - main_config->exec[i] = repl; + for (i = 0 ; i < n ; i++) { + repl = instanciate_string(json_object_get_string(json_object_array_get_idx(exec, i)), port, token); + if (!repl) { + while(i) + free(result[--i]); + free(result); + return NULL; + } + result[i] = repl; } - return 0; + result[i] = NULL; + return result; } static int execute_command() { + struct json_object *exec, *oport; struct sigaction siga; char port[20]; const char *token; + char **args; int rc; /* check whether a command is to execute or not */ - if (!main_config->exec || !main_config->exec[0]) + if (!json_object_object_get_ex(main_config, "exec", &exec)) return 0; if (SELF_PGROUP) @@ -423,8 +472,8 @@ static int execute_command() return 0; /* compute the string for port */ - if (main_config->http_port) - rc = snprintf(port, sizeof port, "%d", main_config->http_port); + if (json_object_object_get_ex(main_config, "port", &oport)) + rc = snprintf(port, sizeof port, "%s", json_object_get_string(oport)); else rc = snprintf(port, sizeof port, "%cp", SUBST_CHAR); if (rc < 0 || rc >= (int)(sizeof port)) { @@ -433,13 +482,13 @@ static int execute_command() else { /* instanciate arguments and environment */ token = afb_session_initial_token(); - if (instanciate_command_args(port, token) >= 0 - && instanciate_environ(port, token) >= 0) { + args = instanciate_command_args(exec, port, token); + if (args && instanciate_environ(port, token) >= 0) { /* run */ if (!SELF_PGROUP) setpgid(0, 0); - execv(main_config->exec[0], main_config->exec); - ERROR("can't launch %s: %m", main_config->exec[0]); + execv(args[0], args); + ERROR("can't launch %s: %m", args[0]); } } exit(1); @@ -455,7 +504,10 @@ struct startup_req struct afb_xreq xreq; char *api; char *verb; - struct afb_config_list *current; + struct json_object *calls; + int index; + int count; + const char *callspec; struct afb_session *session; }; @@ -465,10 +517,10 @@ static void startup_call_reply(struct afb_xreq *xreq, struct json_object *object info = info ?: ""; if (!error) { - NOTICE("startup call %s returned %s (%s)", sreq->current->value, json_object_get_string(object), info); + NOTICE("startup call %s returned %s (%s)", sreq->callspec, json_object_get_string(object), info); json_object_put(object); } else { - ERROR("startup call %s ERROR! %s (%s)", sreq->current->value, error, info); + ERROR("startup call %s ERROR! %s (%s)", sreq->callspec, error, info); exit(1); } } @@ -482,8 +534,8 @@ static void startup_call_unref(struct afb_xreq *xreq) free(sreq->api); free(sreq->verb); json_object_put(sreq->xreq.json); - sreq->current = sreq->current->next; - if (sreq->current) + sreq->index++; + if (sreq->index < sreq->count) startup_call_current(sreq); else { afb_session_close(sreq->session); @@ -500,9 +552,10 @@ static struct afb_xreq_query_itf startup_xreq_itf = static void startup_call_current(struct startup_req *sreq) { - char *api, *verb, *json; + const char *api, *verb, *json; - api = sreq->current->value; + sreq->callspec = json_object_get_string(json_object_array_get_idx(sreq->calls, sreq->index)), + api = sreq->callspec; verb = strchr(api, '/'); if (verb) { json = strchr(verb, ':'); @@ -521,20 +574,24 @@ static void startup_call_current(struct startup_req *sreq) } } } - ERROR("Bad call specification %s", sreq->current->value); + ERROR("Bad call specification %s", sreq->callspec); exit(1); } static void run_startup_calls() { - struct afb_config_list *list; + struct json_object *calls; struct startup_req *sreq; + int count; - list = main_config->calls; - if (list) { + if (json_object_object_get_ex(main_config, "call", &calls) + && json_object_is_type(calls, json_type_array) + && (count = (int)json_object_array_length(calls))) { sreq = calloc(1, sizeof *sreq); sreq->session = afb_session_create(3600); - sreq->current = list; + sreq->calls = calls; + sreq->index = 0; + sreq->count = count; startup_call_current(sreq); } } @@ -545,7 +602,13 @@ static void run_startup_calls() static void start(int signum, void *arg) { + const char *tracereq, *traceapi, *traceevt, *traceses, *tracesvc, *traceditf, *traceglob; + const char *workdir, *rootdir, *token, *rootapi; struct afb_hsrv *hsrv; + int max_session_count, session_timeout, api_timeout; + int no_httpd, http_port; + int rc; + afb_debug("start-entry"); @@ -554,23 +617,63 @@ static void start(int signum, void *arg) exit(1); } + token = rootapi = tracesvc = traceditf = tracereq = + traceapi = traceevt = traceses = traceglob = NULL; + no_httpd = http_port = 0; + rc = wrap_json_unpack(main_config, "{" + "ss ss s?s" + "si si si" + "s?b s?i s?s" +#if !defined(REMOVE_LEGACY_TRACE) + "s?s s?s" +#endif + "s?s s?s s?s s?s s?s" + "}", + + "rootdir", &rootdir, + "workdir", &workdir, + "token", &token, + + "apitimeout", &api_timeout, + "cntxtimeout", &session_timeout, + "session-max", &max_session_count, + + "no-httpd", &no_httpd, + "port", &http_port, + "rootapi", &rootapi, + +#if !defined(REMOVE_LEGACY_TRACE) + "tracesvc", &tracesvc, + "traceditf", &traceditf, +#endif + "tracereq", &tracereq, + "traceapi", &traceapi, + "traceevt", &traceevt, + "traceses", &traceses, + "traceglob", &traceglob + ); + if (rc < 0) { + ERROR("Unable to get start config"); + exit(1); + } + /* set the directories */ - mkdir(main_config->workdir, S_IRWXU | S_IRGRP | S_IXGRP); - if (chdir(main_config->workdir) < 0) { - ERROR("Can't enter working dir %s", main_config->workdir); + mkdir(workdir, S_IRWXU | S_IRGRP | S_IXGRP); + if (chdir(workdir) < 0) { + ERROR("Can't enter working dir %s", workdir); goto error; } - if (afb_common_rootdir_set(main_config->rootdir) < 0) { + if (afb_common_rootdir_set(rootdir) < 0) { ERROR("failed to set common root directory"); goto error; } /* configure the daemon */ - if (afb_session_init(main_config->max_session_count, main_config->session_timeout, main_config->token)) { + if (afb_session_init(max_session_count, session_timeout, token)) { ERROR("initialisation of session manager failed"); goto error; } - main_apiset = afb_apiset_create("main", main_config->api_timeout); + main_apiset = afb_apiset_create("main", api_timeout); if (!main_apiset) { ERROR("can't create main api set"); goto error; @@ -587,27 +690,36 @@ static void start(int signum, void *arg) #endif /* install hooks */ - if (main_config->tracereq) - afb_hook_create_xreq(NULL, NULL, NULL, main_config->tracereq, NULL, NULL); - if (main_config->traceapi) - afb_hook_create_api(NULL, main_config->traceapi, NULL, NULL); - if (main_config->traceevt) - afb_hook_create_evt(NULL, main_config->traceevt, NULL, NULL); - if (main_config->traceses) - afb_hook_create_session(NULL, main_config->traceses, NULL, NULL); + if (tracereq) + afb_hook_create_xreq(NULL, NULL, NULL, afb_hook_flags_xreq_from_text(tracereq), NULL, NULL); +#if !defined(REMOVE_LEGACY_TRACE) + if (traceapi || tracesvc || traceditf) + afb_hook_create_api(NULL, afb_hook_flags_api_from_text(traceapi) + | afb_hook_flags_legacy_ditf_from_text(traceditf) + | afb_hook_flags_legacy_svc_from_text(tracesvc), NULL, NULL); +#else + if (traceapi) + afb_hook_create_api(NULL, afb_hook_flags_api_from_text(traceapi), NULL, NULL); +#endif + if (traceevt) + afb_hook_create_evt(NULL, afb_hook_flags_evt_from_text(traceevt), NULL, NULL); + if (traceses) + afb_hook_create_session(NULL, afb_hook_flags_session_from_text(traceses), NULL, NULL); + if (traceglob) + afb_hook_create_global(afb_hook_flags_global_from_text(traceglob), NULL, NULL); /* load bindings */ afb_debug("start-load"); - apiset_start_list(main_config->so_bindings, afb_api_so_add_binding, "the binding"); - apiset_start_list(main_config->ldpaths, afb_api_so_add_pathset_fails, "the binding path set"); - apiset_start_list(main_config->weak_ldpaths, afb_api_so_add_pathset_nofails, "the weak binding path set"); - apiset_start_list(main_config->auto_api, afb_autoset_add_any, "the automatic api path set"); - apiset_start_list(main_config->ws_servers, afb_api_ws_add_server, "the afb-websocket service"); + apiset_start_list("binding", afb_api_so_add_binding, "the binding"); + apiset_start_list("ldpaths", afb_api_so_add_pathset_fails, "the binding path set"); + apiset_start_list("weak-ldpaths", afb_api_so_add_pathset_nofails, "the weak binding path set"); + apiset_start_list("auto-api", afb_autoset_add_any, "the automatic api path set"); + apiset_start_list("ws-server", afb_api_ws_add_server, "the afb-websocket service"); #if defined(WITH_DBUS_TRANSPARENCY) - apiset_start_list(main_config->dbus_servers, afb_api_dbus_add_server, "the afb-dbus service"); - apiset_start_list(main_config->dbus_clients, afb_api_dbus_add_client, "the afb-dbus client"); + apiset_start_list("dbus-server", afb_api_dbus_add_server, "the afb-dbus service"); + apiset_start_list("dbus-client", afb_api_dbus_add_client, "the afb-dbus client"); #endif - apiset_start_list(main_config->ws_clients, afb_api_ws_add_client_weak, "the afb-websocket client"); + apiset_start_list("ws-client", afb_api_ws_add_client_weak, "the afb-websocket client"); DEBUG("Init config done"); @@ -621,13 +733,13 @@ static void start(int signum, void *arg) /* start the HTTP server */ afb_debug("start-http"); - if (!main_config->no_httpd) { - if (main_config->http_port <= 0) { + if (!no_httpd) { + if (http_port <= 0) { ERROR("no port is defined"); goto error; } - if (!afb_hreq_init_cookie(main_config->http_port, main_config->rootapi, main_config->session_timeout)) { + if (!afb_hreq_init_cookie(http_port, rootapi, session_timeout)) { ERROR("initialisation of HTTP cookies failed"); goto error; } @@ -660,26 +772,20 @@ error: int main(int argc, char *argv[]) { + struct json_object *name; afb_debug("main-entry"); // ------------- Build session handler & init config ------- main_config = afb_config_parse_arguments(argc, argv); - if (main_config->name) { - verbose_set_name(main_config->name, 0); - process_name_set_name(main_config->name); - process_name_replace_cmdline(argv, main_config->name); + if (json_object_object_get_ex(main_config, "name", &name)) { + verbose_set_name(json_object_get_string(name), 0); + process_name_set_name(json_object_get_string(name)); + process_name_replace_cmdline(argv, json_object_get_string(name)); } afb_debug("main-args"); // --------- run ----------- - if (main_config->background) { - // --------- in background mode ----------- - INFO("entering background mode"); - daemonize(); - } else { - // ---- in foreground mode -------------------- - INFO("entering foreground mode"); - } + daemonize(); INFO("running with pid %d", getpid()); /* set the daemon environment */ diff --git a/src/wrap-json.h b/src/wrap-json.h index d75ebc43..f43659ad 100644 --- a/src/wrap-json.h +++ b/src/wrap-json.h @@ -39,9 +39,6 @@ extern int wrap_json_check(struct json_object *object, const char *desc, ...); extern int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args); extern int wrap_json_match(struct json_object *object, const char *desc, ...); -extern void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure); -extern void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure); - extern void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure); extern void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure); extern void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);