X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fmain.c;h=44580c89e3535ebc8f06cd17e24804fea01948c1;hb=779f425daa66d2b0cd431fdc6f7f4ed976cbae15;hp=9977c7d47349815600e971ee2e8b7f756251bf0a;hpb=67966a2f96613d833f493ef3773c442d35f8ed31;p=src%2Fapp-framework-binder.git diff --git a/src/main.c b/src/main.c index 9977c7d4..44580c89 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 "IoT.bzh" + * Copyright (C) 2015, 2016 "IoT.bzh" * Author "Fulup Ar Foll" * Author José Bollo * @@ -20,34 +20,34 @@ #include #include -#include #include #include #include #include -#include - #include -#include -#include -#include + +#include #include "afb-config.h" #include "afb-hswitch.h" +#include "afb-apis.h" #include "afb-api-so.h" +#include "afb-api-dbus.h" #include "afb-hsrv.h" +#include "afb-context.h" #include "afb-hreq.h" +#include "afb-sig-handler.h" #include "session.h" #include "verbose.h" -#include "utils-upoll.h" +#include "afb-common.h" -#include "afb-plugin.h" +#include #if !defined(PLUGIN_INSTALL_DIR) #error "you should define PLUGIN_INSTALL_DIR" #endif -#define AFB_VERSION "0.1" +#define AFB_VERSION "0.4" // Define command line option #define SET_VERBOSE 1 @@ -74,7 +74,9 @@ #define SET_MODE 18 #define SET_READYFD 19 -static struct afb_hsrv *start(struct afb_config * config); +#define DBUS_CLIENT 20 +#define DBUS_SERVICE 21 +#define SO_PLUGIN 22 // Command line structure hold cli --command + help text typedef struct { @@ -112,26 +114,54 @@ static AFB_options cliOptions [] = { {SET_MODE ,1,"mode" , "set the mode: either local, remote or global"}, {SET_READYFD ,1,"readyfd" , "set the #fd to signal when ready"}, - {0, 0, NULL, NULL} - }; + {DBUS_CLIENT ,1,"dbus-client" , "bind to an afb service through dbus"}, + {DBUS_SERVICE ,1,"dbus-server" , "provides an afb service through dbus"}, + {SO_PLUGIN ,1,"plugin" , "load the plugin of path"}, + {0, 0, NULL, NULL} + }; /*---------------------------------------------------------- | printversion | print version and copyright +--------------------------------------------------------- */ -static void printVersion (void) +static void printVersion (FILE *file) { - fprintf (stderr,"\n----------------------------------------- \n"); - fprintf (stderr,"| AFB [Application Framework Binder] version=%s |\n", AFB_VERSION); - fprintf (stderr,"----------------------------------------- \n"); - fprintf (stderr,"| Copyright(C) 2016 /IoT.bzh [fulup -at- iot.bzh]\n"); - fprintf (stderr,"| AFB comes with ABSOLUTELY NO WARRANTY.\n"); - fprintf (stderr,"| Licence Apache 2\n\n"); + fprintf(file, "\n----------------------------------------- \n"); + fprintf(file, " AFB [Application Framework Binder] version=%s |\n", AFB_VERSION); + fprintf(file, " \n"); + fprintf(file, " Copyright (C) 2015, 2016 \"IoT.bzh\" [fulup -at- iot.bzh]\n"); + fprintf(file, " AFB comes with ABSOLUTELY NO WARRANTY.\n"); + fprintf(file, " Licence Apache 2\n\n"); exit (0); } +/*---------------------------------------------------------- + | printHelp + | print information from long option array + +--------------------------------------------------------- */ + +static void printHelp(FILE *file, const char *name) +{ + int ind; + char command[50]; + + fprintf (file, "%s:\nallowed options\n", name); + for (ind=0; cliOptions [ind].name != NULL;ind++) + { + // display options + if (cliOptions [ind].has_arg == 0 ) + { + fprintf (file, " --%-15s %s\n", cliOptions [ind].name, cliOptions[ind].help); + } else { + sprintf(command, "%s=xxxx", cliOptions [ind].name); + fprintf (file, " --%-15s %s\n", command, cliOptions[ind].help); + } + } + fprintf (file, "Example:\n %s\\\n --verbose --port=1234 --token='azerty' --ldpaths=build/plugins:/usr/lib64/agl/plugins\n", name); +} + // load config from disk and merge with CLI option static void config_set_default (struct afb_config * config) { @@ -192,35 +222,24 @@ static void config_set_default (struct afb_config * config) } -/*---------------------------------------------------------- - | printHelp - | print information from long option array - +--------------------------------------------------------- */ - - static void printHelp(char *name) { - int ind; - char command[20]; - - fprintf (stderr,"%s:\nallowed options\n", name); - for (ind=0; cliOptions [ind].name != NULL;ind++) - { - // display options - if (cliOptions [ind].has_arg == 0 ) - { - fprintf (stderr," --%-15s %s\n", cliOptions [ind].name, cliOptions[ind].help); - } else { - sprintf(command,"%s=xxxx", cliOptions [ind].name); - fprintf (stderr," --%-15s %s\n", command, cliOptions[ind].help); - } - } - fprintf (stderr,"Example:\n %s\\\n --verbose --port=1234 --token='azerty' --ldpaths=build/plugins:/usr/lib64/agl/plugins\n", name); -} // end printHelp - /*--------------------------------------------------------- | main | Parse option and launch action +--------------------------------------------------------- */ +static void add_item(struct afb_config *config, int kind, char *value) +{ + struct afb_config_item *item = malloc(sizeof *item); + if (item == NULL) { + ERROR("out of memory"); + exit(1); + } + item->kind = kind; + item->value = value; + item->previous = config->items; + config->items = item; +} + static void parse_arguments(int argc, char *argv[], struct afb_config *config) { char* programName = argv [0]; @@ -233,7 +252,7 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config) // if no argument print help and return if (argc < 2) { - printHelp(programName); + printHelp(stderr, programName); exit(1); } @@ -275,19 +294,19 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config) case SET_ROOT_DIR: if (optarg == 0) goto needValueForOption; config->rootdir = optarg; - if (verbosity) fprintf(stderr, "Forcing Rootdir=%s\n",config->rootdir); + INFO("Forcing Rootdir=%s",config->rootdir); break; case SET_ROOT_BASE: if (optarg == 0) goto needValueForOption; config->rootbase = optarg; - if (verbosity) fprintf(stderr, "Forcing Rootbase=%s\n",config->rootbase); + INFO("Forcing Rootbase=%s",config->rootbase); break; case SET_ROOT_API: if (optarg == 0) goto needValueForOption; config->rootapi = optarg; - if (verbosity) fprintf(stderr, "Forcing Rootapi=%s\n",config->rootapi); + INFO("Forcing Rootapi=%s",config->rootapi); break; case SET_ALIAS: @@ -295,14 +314,14 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config) if ((unsigned)config->aliascount < sizeof (config->aliasdir) / sizeof (config->aliasdir[0])) { config->aliasdir[config->aliascount].url = strsep(&optarg,":"); if (optarg == NULL) { - fprintf(stderr, "missing ':' in alias %s, ignored\n", config->aliasdir[config->aliascount].url); + ERROR("missing ':' in alias %s, ignored", config->aliasdir[config->aliascount].url); } else { config->aliasdir[config->aliascount].path = optarg; - if (verbosity) fprintf(stderr, "Alias url=%s path=%s\n", config->aliasdir[config->aliascount].url, config->aliasdir[config->aliascount].path); + INFO("Alias url=%s path=%s", config->aliasdir[config->aliascount].url, config->aliasdir[config->aliascount].path); config->aliascount++; } } else { - fprintf(stderr, "Too many aliases [max:%d] %s ignored\n", MAX_ALIAS, optarg); + ERROR("Too many aliases [max:%d] %s ignored", MAX_ALIAS, optarg); } break; @@ -349,14 +368,21 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config) if (!sscanf (optarg, "%u", &config->readyfd)) goto notAnInteger; break; + case DBUS_CLIENT: + case DBUS_SERVICE: + case SO_PLUGIN: + if (optarg == 0) goto needValueForOption; + add_item(config, optc, optarg); + break; + case DISPLAY_VERSION: if (optarg != 0) goto noValueForOption; - printVersion(); - exit(0); + printVersion(stdout); + break; case DISPLAY_HELP: default: - printHelp(programName); + printHelp(stdout, programName); exit(0); } } @@ -367,22 +393,22 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config) needValueForOption: - fprintf (stderr,"\nERR: AFB-daemon option [--%s] need a value i.e. --%s=xxx\n\n" + ERROR("AFB-daemon option [--%s] need a value i.e. --%s=xxx" ,gnuOptions[optionIndex].name, gnuOptions[optionIndex].name); exit (1); notAnInteger: - fprintf (stderr,"\nERR: AFB-daemon option [--%s] requirer an interger i.e. --%s=9\n\n" + ERROR("AFB-daemon option [--%s] requirer an interger i.e. --%s=9" ,gnuOptions[optionIndex].name, gnuOptions[optionIndex].name); exit (1); noValueForOption: - fprintf (stderr,"\nERR: AFB-daemon option [--%s] don't take value\n\n" + ERROR("AFB-daemon option [--%s] don't take value" ,gnuOptions[optionIndex].name); exit (1); badMode: - fprintf (stderr,"\nERR: AFB-daemon option [--%s] only accepts local, global or remote.\n\n" + ERROR("AFB-daemon option [--%s] only accepts local, global or remote." ,gnuOptions[optionIndex].name); exit (1); } @@ -395,50 +421,6 @@ static void closeSession (int status, void *data) { /* struct afb_config *config = data; */ } -/*---------------------------------------------------------- - | timeout signalQuit - +--------------------------------------------------------- */ -void signalQuit (int signum) -{ - fprintf(stderr, "Terminating signal received %s\n", strsignal(signum)); - exit(1); -} - - -/*---------------------------------------------------------- - | Error signals - | - +--------------------------------------------------------- */ -__thread sigjmp_buf *error_handler; -static void signalError(int signum) -{ - sigset_t sigset; - - // unlock signal to allow a new signal to come - if (error_handler != NULL) { - sigemptyset(&sigset); - sigaddset(&sigset, signum); - sigprocmask(SIG_UNBLOCK, &sigset, 0); - longjmp(*error_handler, signum); - } - if (signum == SIGALRM) - return; - fprintf(stderr, "Unmonitored signal received %s\n", strsignal(signum)); - exit(2); -} - -static void install_error_handlers() -{ - int i, signals[] = { SIGALRM, SIGSEGV, SIGFPE, 0 }; - - for (i = 0; signals[i] != 0; i++) { - if (signal(signals[i], signalError) == SIG_ERR) { - fprintf(stderr, "Signal handler error\n"); - exit(1); - } - } -} - /*---------------------------------------------------------- | daemonize | set the process in background @@ -451,7 +433,7 @@ static void daemonize(struct afb_config *config) // open /dev/console to redirect output messAFBes consoleFD = open(config->console, O_WRONLY | O_APPEND | O_CREAT , 0640); if (consoleFD < 0) { - fprintf (stderr,"\nERR: AFB-daemon cannot open /dev/console (use --foreground)\n\n"); + ERROR("AFB-daemon cannot open /dev/console (use --foreground)"); exit (1); } @@ -460,7 +442,7 @@ static void daemonize(struct afb_config *config) // if fail nothing much to do if (pid == -1) { - fprintf (stderr,"\nERR: AFB-daemon Failed to fork son process\n\n"); + ERROR("AFB-daemon Failed to fork son process"); exit (1); } @@ -468,7 +450,7 @@ static void daemonize(struct afb_config *config) if (pid != 0) _exit (0); // son process get all data in standalone mode - fprintf (stderr, "\nAFB: background mode [pid:%d console:%s]\n", getpid(),config->console); + NOTICE("background mode [pid:%d console:%s]", getpid(),config->console); // redirect default I/O on console close (2); dup(consoleFD); // redirect stderr @@ -480,10 +462,102 @@ static void daemonize(struct afb_config *config) setsid(); // allow father process to fully exit sleep (2); // allow main to leave and release port #endif +} - fprintf (stderr, "----------------------------\n"); - fprintf (stderr, "INF: main background pid=%d\n", getpid()); - fflush (stderr); +/*--------------------------------------------------------- + | http server + | Handles the HTTP server + +--------------------------------------------------------- */ +static int init_http_server(struct afb_hsrv *hsrv, struct afb_config * config) +{ + int idx; + + if (!afb_hsrv_add_handler(hsrv, config->rootapi, afb_hswitch_websocket_switch, NULL, 20)) + return 0; + + if (!afb_hsrv_add_handler(hsrv, config->rootapi, afb_hswitch_apis, NULL, 10)) + return 0; + + for (idx = 0; idx < config->aliascount; idx++) + if (!afb_hsrv_add_alias (hsrv, config->aliasdir[idx].url, config->aliasdir[idx].path, 0)) + return 0; + + if (!afb_hsrv_add_alias(hsrv, "", config->rootdir, -10)) + return 0; + + if (!afb_hsrv_add_handler(hsrv, config->rootbase, afb_hswitch_one_page_api_redirect, NULL, -20)) + return 0; + + return 1; +} + +static struct afb_hsrv *start_http_server(struct afb_config * config) +{ + int rc; + struct afb_hsrv *hsrv; + + if (afb_hreq_init_download_path("/tmp")) { /* TODO: sessiondir? */ + ERROR("unable to set the tmp directory"); + return NULL; + } + + hsrv = afb_hsrv_create(); + if (hsrv == NULL) { + ERROR("memory allocation failure"); + return NULL; + } + + if (!afb_hsrv_set_cache_timeout(hsrv, config->cacheTimeout) + || !init_http_server(hsrv, config)) { + ERROR("initialisation of httpd failed"); + afb_hsrv_put(hsrv); + return NULL; + } + + NOTICE("Waiting port=%d rootdir=%s", config->httpdPort, config->rootdir); + NOTICE("Browser URL= http:/*localhost:%d", config->httpdPort); + + rc = afb_hsrv_start(hsrv, (uint16_t) config->httpdPort, 15); + if (!rc) { + ERROR("starting of httpd failed"); + afb_hsrv_put(hsrv); + return NULL; + } + + return hsrv; +} + +static void start_items(struct afb_config_item *item) +{ + if (item != NULL) { + /* keeps the order */ + start_items(item->previous); + switch(item->kind) { + case DBUS_CLIENT: + if (afb_api_dbus_add_client(item->value) < 0) { + ERROR("can't start the afb-dbus client of path %s",item->value); + exit(1); + } + break; + case DBUS_SERVICE: + if (afb_api_dbus_add_server(item->value) < 0) { + ERROR("can't start the afb-dbus service of path %s",item->value); + exit(1); + } + break; + case SO_PLUGIN: + if (afb_api_so_add_plugin(item->value) < 0) { + ERROR("can't start the plugin of path %s",item->value); + exit(1); + } + break; + default: + ERROR("unexpected internal error"); + exit(1); + } + /* frre the item */ + free(item); + } } /*--------------------------------------------------------- @@ -494,9 +568,9 @@ static void daemonize(struct afb_config *config) int main(int argc, char *argv[]) { struct afb_hsrv *hsrv; struct afb_config *config; + struct sd_event *eventloop; - // open syslog if ever needed - openlog("afb-daemon", 0, LOG_DAEMON); + LOGAUTH("afb-daemon"); // ------------- Build session handler & init config ------- config = calloc (1, sizeof (struct afb_config)); @@ -506,24 +580,28 @@ int main(int argc, char *argv[]) { // ------------------ sanity check ---------------------------------------- if (config->httpdPort <= 0) { - fprintf (stderr, "ERR: no port is defined\n"); + ERROR("no port is defined"); exit (1); } - if (config->ldpaths) - afb_api_so_add_pathset(config->ldpaths); + if (config->ldpaths) { + if (afb_api_so_add_pathset(config->ldpaths) < 0) { + ERROR("initialisation of plugins within %s failed", config->ldpaths); + exit(1); + } + } + + start_items(config->items); + config->items = NULL; - ctxStoreInit(CTX_NBCLIENTS, config->cntxTimeout, config->token); + ctxStoreInit(CTX_NBCLIENTS, config->cntxTimeout, config->token, afb_apis_count()); if (!afb_hreq_init_cookie(config->httpdPort, config->rootapi, DEFLT_CNTX_TIMEOUT)) { - fprintf (stderr, "ERR: initialisation of cookies failed\n"); + ERROR("initialisation of cookies failed"); exit (1); } - install_error_handlers(); - - // ------------------ clean exit on CTR-C signal ------------------------ - if (signal (SIGINT, signalQuit) == SIG_ERR || signal (SIGABRT, signalQuit) == SIG_ERR) { - fprintf (stderr, "ERR: main fail to install Signal handler\n"); + if (afb_sig_handler_init() < 0) { + ERROR("main fail to initialise signal handlers"); return 1; } @@ -534,20 +612,19 @@ int main(int argc, char *argv[]) { // let's not take the risk to run as ROOT //if (getuid() == 0) goto errorNoRoot; - if (verbosity) fprintf (stderr, "AFB: notice Init config done\n"); + DEBUG("Init config done"); // --------- run ----------- if (config->background) { // --------- in background mode ----------- - if (verbosity) fprintf (stderr, "AFB: Entering background mode\n"); + INFO("entering background mode"); daemonize(config); } else { // ---- in foreground mode -------------------- - if (verbosity) fprintf (stderr,"AFB: notice Foreground mode\n"); - + INFO("entering foreground mode"); } - hsrv = start (config); + hsrv = start_http_server(config); if (hsrv == NULL) exit(1); @@ -558,69 +635,12 @@ int main(int argc, char *argv[]) { } // infinite loop + eventloop = afb_common_get_event_loop(); for(;;) - upoll_wait(30000); + sd_event_run(eventloop, 30000000); - if (verbosity) - fprintf (stderr, "hoops returned from infinite loop [report bug]\n"); + WARNING("hoops returned from infinite loop [report bug]"); return 0; } -static int init(struct afb_hsrv *hsrv, struct afb_config * config) -{ - int idx; - - if (!afb_hsrv_add_handler(hsrv, config->rootapi, afb_hswitch_websocket_switch, NULL, 20)) - return 0; - - if (!afb_hsrv_add_handler(hsrv, config->rootapi, afb_hswitch_apis, NULL, 10)) - return 0; - - for (idx = 0; idx < config->aliascount; idx++) - if (!afb_hsrv_add_alias (hsrv, config->aliasdir[idx].url, config->aliasdir[idx].path, 0)) - return 0; - - if (!afb_hsrv_add_alias(hsrv, "", config->rootdir, -10)) - return 0; - - if (!afb_hsrv_add_handler(hsrv, config->rootbase, afb_hswitch_one_page_api_redirect, NULL, -20)) - return 0; - - return 1; -} - -static struct afb_hsrv *start(struct afb_config * config) -{ - int rc; - struct afb_hsrv *hsrv; - - hsrv = afb_hsrv_create(); - if (hsrv == NULL) { - fprintf(stderr, "memory allocation failure\n"); - return NULL; - } - - if (!afb_hsrv_set_cache_timeout(hsrv, config->cacheTimeout) - || !init(hsrv, config)) { - fprintf (stderr, "Error: initialisation of httpd failed"); - afb_hsrv_put(hsrv); - return NULL; - } - - if (verbosity) { - fprintf (stderr, "AFB:notice Waiting port=%d rootdir=%s\n", config->httpdPort, config->rootdir); - fprintf (stderr, "AFB:notice Browser URL= http:/*localhost:%d\n", config->httpdPort); - } - - rc = afb_hsrv_start(hsrv, (uint16_t) config->httpdPort, 15); - if (!rc) { - fprintf (stderr, "Error: starting of httpd failed"); - afb_hsrv_put(hsrv); - return NULL; - } - - return hsrv; -} - -