/*
- * Copyright (C) 2015 "IoT.bzh"
+ * Copyright (C) 2015, 2016 "IoT.bzh"
* Author "Fulup Ar Foll"
* Author José Bollo <jose.bollo@iot.bzh>
*
*/
#define _GNU_SOURCE
+#define NO_BINDING_VERBOSE_MACRO
#include <stdlib.h>
#include <stdio.h>
-#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
-#include <sys/types.h>
-
#include <getopt.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <syslog.h>
#include <systemd/sd-event.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 "afb-common.h"
-#include "afb-plugin.h"
+#include <afb/afb-binding.h>
-#if !defined(PLUGIN_INSTALL_DIR)
-#error "you should define PLUGIN_INSTALL_DIR"
+#if !defined(BINDING_INSTALL_DIR)
+#error "you should define BINDING_INSTALL_DIR"
#endif
-#define AFB_VERSION "0.4"
+#define AFB_VERSION "0.5"
// Define command line option
#define SET_VERBOSE 1
#define SET_MODE 18
#define SET_READYFD 19
+#define DBUS_CLIENT 20
+#define DBUS_SERVICE 21
+#define SO_BINDING 22
+
+#define SET_SESSIONMAX 23
+
// Command line structure hold cli --command + help text
typedef struct {
int val; // command number within application
{SET_ROOT_API ,1,"rootapi" , "HTML Root API URL [default /api]"},
{SET_ALIAS ,1,"alias" , "Muliple url map outside of rootdir [eg: --alias=/icons:/usr/share/icons]"},
- {SET_APITIMEOUT ,1,"apitimeout" , "Plugin API timeout in seconds [default 10]"},
+ {SET_APITIMEOUT ,1,"apitimeout" , "Binding API timeout in seconds [default 10]"},
{SET_CNTXTIMEOUT ,1,"cntxtimeout" , "Client Session Context Timeout [default 900]"},
- {SET_CACHE_TIMEOUT,1,"cache-eol" , "Client cache end of live [default 3600s]"},
+ {SET_CACHE_TIMEOUT,1,"cache-eol" , "Client cache end of live [default 3600]"},
{SET_SESSION_DIR ,1,"sessiondir" , "Sessions file path [default rootdir/sessions]"},
- {SET_LDPATH ,1,"ldpaths" , "Load Plugins from dir1:dir2:... [default = PLUGIN_INSTALL_DIR"},
+ {SET_LDPATH ,1,"ldpaths" , "Load bindingss from dir1:dir2:... [default = "BINDING_INSTALL_DIR"]"},
{SET_AUTH_TOKEN ,1,"token" , "Initial Secret [default=no-session, --token="" for session without authentication]"},
{DISPLAY_VERSION ,0,"version" , "Display version and copyright"},
{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_BINDING ,1,"binding" , "load the binding of path"},
+
+ {SET_SESSIONMAX ,1,"session-max" , "max count of session simultaneously [default 10]"},
+ {0, 0, NULL, NULL}
+ };
/*----------------------------------------------------------
| printversion
fprintf(file, "\n----------------------------------------- \n");
fprintf(file, " AFB [Application Framework Binder] version=%s |\n", AFB_VERSION);
fprintf(file, " \n");
- fprintf(file, " Copyright(C) 2016 /IoT.bzh [fulup -at- iot.bzh]\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);
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);
+ fprintf (file, "Example:\n %s\\\n --verbose --port=1234 --token='azerty' --ldpaths=build/bindings:/usr/lib64/agl/bindings\n", name);
}
// load config from disk and merge with CLI option
if (config->httpdPort == 0)
config->httpdPort = 1234;
- // default Plugin API timeout
+ // default binding API timeout
if (config->apiTimeout == 0)
config->apiTimeout = DEFLT_API_TIMEOUT;
if (config->cntxTimeout == 0)
config->cntxTimeout = DEFLT_CNTX_TIMEOUT;
+ // max count of sessions
+ if (config->nbSessionMax == 0)
+ config->nbSessionMax = CTX_NBCLIENTS;
+
if (config->rootdir == NULL) {
config->rootdir = getenv("AFBDIR");
if (config->rootdir == NULL) {
config->rootapi = "/api";
if (config->ldpaths == NULL)
- config->ldpaths = PLUGIN_INSTALL_DIR;
+ config->ldpaths = BINDING_INSTALL_DIR;
// if no session dir create a default path from rootdir
if (config->sessiondir == NULL) {
| 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];
if (!sscanf (optarg, "%d", &config->cacheTimeout)) goto notAnInteger;
break;
+ case SET_SESSIONMAX:
+ if (optarg == 0) goto needValueForOption;
+ if (!sscanf (optarg, "%d", &config->nbSessionMax)) goto notAnInteger;
+ break;
+
case SET_FORGROUND:
if (optarg != 0) goto noValueForOption;
config->background = 0;
if (!sscanf (optarg, "%u", &config->readyfd)) goto notAnInteger;
break;
+ case DBUS_CLIENT:
+ case DBUS_SERVICE:
+ case SO_BINDING:
+ if (optarg == 0) goto needValueForOption;
+ add_item(config, optc, optarg);
+ break;
+
case DISPLAY_VERSION:
if (optarg != 0) goto noValueForOption;
printVersion(stdout);
/* struct afb_config *config = data; */
}
-/*----------------------------------------------------------
- | timeout signalQuit
- +--------------------------------------------------------- */
-void signalQuit (int signum)
-{
- ERROR("Terminating signal received %s", 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;
- ERROR("Unmonitored signal received %s", 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) {
- ERROR("Signal handler error");
- exit(1);
- }
- }
-}
-
/*----------------------------------------------------------
| daemonize
| set the process in background
return 0;
for (idx = 0; idx < config->aliascount; idx++)
- if (!afb_hsrv_add_alias (hsrv, config->aliasdir[idx].url, config->aliasdir[idx].path, 0))
+ if (!afb_hsrv_add_alias (hsrv, config->aliasdir[idx].url, config->aliasdir[idx].path, 0, 0))
return 0;
- if (!afb_hsrv_add_alias(hsrv, "", config->rootdir, -10))
+ if (!afb_hsrv_add_alias(hsrv, "", config->rootdir, -10, 1))
return 0;
if (!afb_hsrv_add_handler(hsrv, config->rootbase, afb_hswitch_one_page_api_redirect, NULL, -20))
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_BINDING:
+ if (afb_api_so_add_binding(item->value) < 0) {
+ ERROR("can't start the binding of path %s",item->value);
+ exit(1);
+ }
+ break;
+ default:
+ ERROR("unexpected internal error");
+ exit(1);
+ }
+ /* frre the item */
+ free(item);
+ }
+}
/*---------------------------------------------------------
| main
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));
exit (1);
}
- if (config->ldpaths)
- afb_api_so_add_pathset(config->ldpaths);
+ afb_api_so_set_timeout(config->apiTimeout);
+ if (config->ldpaths) {
+ if (afb_api_so_add_pathset(config->ldpaths) < 0) {
+ ERROR("initialisation of bindings within %s failed", config->ldpaths);
+ exit(1);
+ }
+ }
+
+ start_items(config->items);
+ config->items = NULL;
- ctxStoreInit(CTX_NBCLIENTS, config->cntxTimeout, config->token, afb_apis_count());
+ ctxStoreInit(config->nbSessionMax, config->cntxTimeout, config->token, afb_apis_count());
if (!afb_hreq_init_cookie(config->httpdPort, config->rootapi, DEFLT_CNTX_TIMEOUT)) {
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) {
- ERROR("main fail to install Signal handler");
+ if (afb_sig_handler_init() < 0) {
+ ERROR("main fail to initialise signal handlers");
return 1;
}
if (hsrv == NULL)
exit(1);
+ /* start the services */
+ if (afb_apis_start_all_services(1) < 0)
+ exit(1);
+
if (config->readyfd != 0) {
static const char readystr[] = "READY=1";
write(config->readyfd, readystr, sizeof(readystr) - 1);