bindings: adds ability to use data of applications
[src/app-framework-binder.git] / src / main.c
index e11a3a1..ff7daaf 100644 (file)
@@ -1,5 +1,5 @@
-/* 
- * Copyright (C) 2015 "IoT.bzh"
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
  * Author "Fulup Ar Foll"
  * Author José Bollo <jose.bollo@iot.bzh>
  *
  * limitations under the License.
  */
 
-#include <syslog.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <pthread.h>
+#define _GNU_SOURCE
+#define NO_BINDING_VERBOSE_MACRO
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
+#include <getopt.h>
 
-#include "local-def.h"
+#include <systemd/sd-event.h>
+
+#include "afb-config.h"
+#include "afb-hswitch.h"
 #include "afb-apis.h"
+#include "afb-api-so.h"
+#include "afb-api-dbus.h"
+#include "afb-api-ws.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/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.1"
+#define AFB_VERSION    "0.5"
 
 // Define command line option
 #define SET_VERBOSE        1
 #define SET_BACKGROUND     2
 #define SET_FORGROUND      3
-#define SET_FAKE_MOD       4
 
 #define SET_TCP_PORT       5
 #define SET_ROOT_DIR       6
 #define SET_MODE           18
 #define SET_READYFD        19
 
+#define DBUS_CLIENT        20
+#define DBUS_SERVICE       21
+#define SO_BINDING         22
+
+#define SET_SESSIONMAX     23
+
+#define WS_CLIENT          24
+#define WS_SERVICE         25
+
 // Command line structure hold cli --command + help text
 typedef struct {
   int  val;        // command number within application
@@ -82,139 +106,156 @@ static  AFB_options cliOptions [] = {
   {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"           , "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"},
   {DISPLAY_HELP     ,0,"help"            , "Display this help"},
 
   {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}
- };
 
-static AFB_aliasdir aliasdir[MAX_ALIAS];
-static int aliascount = 0;
+  {DBUS_CLIENT      ,1,"dbus-client"     , "bind to an afb service through dbus"},
+  {DBUS_SERVICE     ,1,"dbus-server"     , "provides an afb service through dbus"},
+  {WS_CLIENT        ,1,"ws-client"       , "bind to an afb service through websocket"},
+  {WS_SERVICE       ,1,"ws-server"       , "provides an afb service through websockets"},
+  {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
  |   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/bindings:/usr/lib64/agl/bindings\n", name);
+}
+
 // load config from disk and merge with CLI option
-static AFB_error config_set_default (AFB_session * session)
+static void config_set_default (struct afb_config * config)
 {
-   static char cacheTimeout [10];
-   
    // default HTTP port
-   if (session->config->httpdPort == 0) session->config->httpdPort=1234;
-   
-   // default Plugin API timeout
-   if (session->config->apiTimeout == 0) session->config->apiTimeout=DEFLT_API_TIMEOUT;
-   
+   if (config->httpdPort == 0)
+       config->httpdPort = 1234;
+
+   // default binding API timeout
+   if (config->apiTimeout == 0)
+       config->apiTimeout = DEFLT_API_TIMEOUT;
+
    // default AUTH_TOKEN
-   if (session->config->token == NULL) session->config->token= DEFLT_AUTH_TOKEN;
+   if (config->token == NULL)
+               config->token = DEFLT_AUTH_TOKEN;
 
    // cache timeout default one hour
-   if (session->config->cacheTimeout == 0) session->config->cacheTimeout=DEFLT_CACHE_TIMEOUT;
+   if (config->cacheTimeout == 0)
+               config->cacheTimeout = DEFLT_CACHE_TIMEOUT;
 
    // cache timeout default one hour
-   if (session->config->cntxTimeout == 0) session->config->cntxTimeout=DEFLT_CNTX_TIMEOUT;
-
-   if (session->config->rootdir == NULL) {
-       session->config->rootdir = getenv("AFBDIR");
-       if (session->config->rootdir == NULL) {
-           session->config->rootdir = malloc (512);
-           strncpy  (session->config->rootdir, getenv("HOME"),512);
-           strncat (session->config->rootdir, "/.AFB",512);
+   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->rootdir = malloc (512);
+           strncpy (config->rootdir, getenv("HOME"),512);
+           strncat (config->rootdir, "/.AFB",512);
        }
        // if directory does not exist createit
-       mkdir (session->config->rootdir,  O_RDWR | S_IRWXU | S_IRGRP);
+       mkdir (config->rootdir,  O_RDWR | S_IRWXU | S_IRGRP);
    }
-   
+
    // if no Angular/HTML5 rootbase let's try '/' as default
-   if  (session->config->rootbase == NULL) {
-       session->config->rootbase = "/opa";
-   }
-   
-   if  (session->config->rootapi == NULL) {
-       session->config->rootapi = "/api";
-   }
+   if  (config->rootbase == NULL)
+       config->rootbase = "/opa";
 
-   if  (session->config->ldpaths == NULL) {
-       session->config->ldpaths = PLUGIN_INSTALL_DIR;
-   }
+   if  (config->rootapi == NULL)
+       config->rootapi = "/api";
+
+   if  (config->ldpaths == NULL)
+       config->ldpaths = BINDING_INSTALL_DIR;
 
    // if no session dir create a default path from rootdir
-   if  (session->config->sessiondir == NULL) {
-       session->config->sessiondir = malloc (512);
-       strncpy (session->config->sessiondir, session->config->rootdir, 512);
-       strncat (session->config->sessiondir, "/sessions",512);
+   if  (config->sessiondir == NULL) {
+       config->sessiondir = malloc (512);
+       strncpy (config->sessiondir, config->rootdir, 512);
+       strncat (config->sessiondir, "/sessions",512);
    }
 
    // if no config dir create a default path from sessiondir
-   if  (session->config->console == NULL) {
-       session->config->console = malloc (512);
-       strncpy (session->config->console, session->config->sessiondir, 512);
-       strncat (session->config->console, "/AFB-console.out",512);
+   if  (config->console == NULL) {
+       config->console = malloc (512);
+       strncpy (config->console, config->sessiondir, 512);
+       strncat (config->console, "/AFB-console.out",512);
    }
-
-   // cacheTimeout is an integer but HTTPd wants it as a string
-   snprintf (cacheTimeout, sizeof (cacheTimeout),"%d", session->config->cacheTimeout);
-   session->cacheTimeout = cacheTimeout; // httpd uses cacheTimeout string version
-
-   return AFB_SUCCESS;
 }
 
 
-/*----------------------------------------------------------
- | 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 parse_arguments(int argc, char *argv[], AFB_session *session)
+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];
   int            optionIndex = 0;
@@ -222,15 +263,11 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session)
   int            nbcmd;
   struct option *gnuOptions;
 
-  // ------------- Build session handler & init config -------
-  memset(&aliasdir  ,0,sizeof(aliasdir));
-  session->config->aliasdir = aliasdir;
-
   // ------------------ Process Command Line -----------------------
 
   // if no argument print help and return
   if (argc < 2) {
-       printHelp(programName);
+       printHelp(stderr, programName);
        exit(1);
   }
 
@@ -251,141 +288,149 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session)
     switch (optc)
     {
      case SET_VERBOSE:
-       verbose = 1;
+       verbosity++;
        break;
 
     case SET_TCP_PORT:
        if (optarg == 0) goto needValueForOption;
-       if (!sscanf (optarg, "%d", &session->config->httpdPort)) goto notAnInteger;
+       if (!sscanf (optarg, "%d", &config->httpdPort)) goto notAnInteger;
        break;
-       
+
     case SET_APITIMEOUT:
        if (optarg == 0) goto needValueForOption;
-       if (!sscanf (optarg, "%d", &session->config->apiTimeout)) goto notAnInteger;
+       if (!sscanf (optarg, "%d", &config->apiTimeout)) goto notAnInteger;
        break;
 
     case SET_CNTXTIMEOUT:
        if (optarg == 0) goto needValueForOption;
-       if (!sscanf (optarg, "%d", &session->config->cntxTimeout)) goto notAnInteger;
+       if (!sscanf (optarg, "%d", &config->cntxTimeout)) goto notAnInteger;
        break;
 
     case SET_ROOT_DIR:
        if (optarg == 0) goto needValueForOption;
-       session->config->rootdir   = optarg;
-       if (verbose) fprintf(stderr, "Forcing Rootdir=%s\n",session->config->rootdir);
-       break;       
-       
+       config->rootdir   = optarg;
+       INFO("Forcing Rootdir=%s",config->rootdir);
+       break;
+
     case SET_ROOT_BASE:
        if (optarg == 0) goto needValueForOption;
-       session->config->rootbase   = optarg;
-       if (verbose) fprintf(stderr, "Forcing Rootbase=%s\n",session->config->rootbase);
+       config->rootbase   = optarg;
+       INFO("Forcing Rootbase=%s",config->rootbase);
        break;
 
     case SET_ROOT_API:
        if (optarg == 0) goto needValueForOption;
-       session->config->rootapi   = optarg;
-       if (verbose) fprintf(stderr, "Forcing Rootapi=%s\n",session->config->rootapi);
+       config->rootapi   = optarg;
+       INFO("Forcing Rootapi=%s",config->rootapi);
        break;
-       
+
     case SET_ALIAS:
        if (optarg == 0) goto needValueForOption;
-       if (aliascount < MAX_ALIAS) {
-            aliasdir[aliascount].url  = strsep(&optarg,":");
+       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", aliasdir[aliascount].url);
+              ERROR("missing ':' in alias %s, ignored", config->aliasdir[config->aliascount].url);
             } else {
-              aliasdir[aliascount].path = optarg;
-              aliasdir[aliascount].len  = strlen(aliasdir[aliascount].url);
-              if (verbose) fprintf(stderr, "Alias url=%s path=%s\n", aliasdir[aliascount].url, aliasdir[aliascount].path);
-              aliascount++;
+              config->aliasdir[config->aliascount].path = optarg;
+              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;
-       
+
     case SET_AUTH_TOKEN:
        if (optarg == 0) goto needValueForOption;
-       session->config->token   = optarg;
+       config->token   = optarg;
        break;
 
     case SET_LDPATH:
        if (optarg == 0) goto needValueForOption;
-       session->config->ldpaths = optarg;
+       config->ldpaths = optarg;
        break;
 
     case SET_SESSION_DIR:
        if (optarg == 0) goto needValueForOption;
-       session->config->sessiondir   = optarg;
+       config->sessiondir   = optarg;
        break;
 
     case  SET_CACHE_TIMEOUT:
        if (optarg == 0) goto needValueForOption;
-       if (!sscanf (optarg, "%d", &session->config->cacheTimeout)) goto notAnInteger;
+       if (!sscanf (optarg, "%d", &config->cacheTimeout)) goto notAnInteger;
        break;
 
-    case SET_FAKE_MOD:
-       if (optarg != 0) goto noValueForOption;
-       session->fakemod  = 1;
+    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;
-       session->foreground  = 1;
+       config->background  = 0;
        break;
 
     case SET_BACKGROUND:
        if (optarg != 0) goto noValueForOption;
-       session->background  = 1;
+       config->background  = 1;
        break;
 
     case SET_MODE:
        if (optarg == 0) goto needValueForOption;
-       if (!strcmp(optarg, "local")) session->config->mode = AFB_MODE_LOCAL;
-       else if (!strcmp(optarg, "remote")) session->config->mode = AFB_MODE_REMOTE;
-       else if (!strcmp(optarg, "global")) session->config->mode = AFB_MODE_GLOBAL;
+       if (!strcmp(optarg, "local")) config->mode = AFB_MODE_LOCAL;
+       else if (!strcmp(optarg, "remote")) config->mode = AFB_MODE_REMOTE;
+       else if (!strcmp(optarg, "global")) config->mode = AFB_MODE_GLOBAL;
        else goto badMode;
        break;
 
     case SET_READYFD:
        if (optarg == 0) goto needValueForOption;
-       if (!sscanf (optarg, "%u", &session->readyfd)) goto notAnInteger;
+       if (!sscanf (optarg, "%u", &config->readyfd)) goto notAnInteger;
+       break;
+
+    case DBUS_CLIENT:
+    case DBUS_SERVICE:
+    case WS_CLIENT:
+    case WS_SERVICE:
+    case SO_BINDING:
+       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);
     }
   }
   free(gnuOptions);
-  config_set_default  (session);
+
+  config_set_default  (config);
   return;
 
 
 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,95 +440,22 @@ badMode:
  |   try to close everything before leaving
  +--------------------------------------------------------- */
 static void closeSession (int status, void *data) {
-       /* AFB_session *session = data; */
+       /* struct afb_config *config = data; */
 }
 
-/*----------------------------------------------------------
- | timeout signalQuit
- |
- +--------------------------------------------------------- */
-void signalQuit (int signum) {
-
-  sigset_t sigset;
-
-  // unlock timeout signal to allow a new signal to come
-  sigemptyset (&sigset);
-  sigaddset   (&sigset, SIGABRT);
-  sigprocmask (SIG_UNBLOCK, &sigset, 0);
-
-  fprintf (stderr, "ERR: Received signal quit\n");
-  syslog (LOG_ERR, "Daemon got kill3 & quit [please report bug]");
-  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
-       sigemptyset(&sigset);
-       sigaddset(&sigset, signum);
-       sigprocmask(SIG_UNBLOCK, &sigset, 0);
-       if (error_handler != NULL) {
-               longjmp(*error_handler, signum);
-       }
-}
-
-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);
-               }
-       }
-}
-
-/*----------------------------------------------------------
- | listenLoop
- |   Main listening HTTP loop
- +--------------------------------------------------------- */
-static void listenLoop (AFB_session *session) {
-  AFB_error  err;
-
-  // ------ Start httpd server
-
-   err = httpdStart (session);
-   if (err != AFB_SUCCESS) return;
-
-       if (session->readyfd != 0) {
-               static const char readystr[] = "READY=1";
-               write(session->readyfd, readystr, sizeof(readystr) - 1);
-               close(session->readyfd);
-       }
-
-   // infinite loop
-   httpdLoop(session);
-
-   fprintf (stderr, "hoops returned from infinite loop [report bug]\n");
-}
-  
 /*----------------------------------------------------------
  | daemonize
  |   set the process in background
  +--------------------------------------------------------- */
-static void daemonize(AFB_session *session)
+static void daemonize(struct afb_config *config)
 {
   int            consoleFD;
   int            pid;
 
       // open /dev/console to redirect output messAFBes
-      consoleFD = open(session->config->console, O_WRONLY | O_APPEND | O_CREAT , 0640);
+      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);
       }
 
@@ -492,7 +464,7 @@ static void daemonize(AFB_session *session)
 
       // 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);
        }
 
@@ -500,7 +472,7 @@ static void daemonize(AFB_session *session)
       if (pid != 0) _exit (0);
 
       // son process get all data in standalone mode
-     printf ("\nAFB: background mode [pid:%d console:%s]\n", getpid(),session->config->console);
+     NOTICE("background mode [pid:%d console:%s]", getpid(),config->console);
 
       // redirect default I/O on console
       close (2); dup(consoleFD);  // redirect stderr
@@ -512,10 +484,114 @@ static void daemonize(AFB_session *session)
         setsid();   // allow father process to fully exit
      sleep (2);  // allow main to leave and release port
 #endif
+}
+
+/*---------------------------------------------------------
+ | 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, 0))
+                       return 0;
+
+       if (!afb_hsrv_add_alias(hsrv, "", config->rootdir, -10, 1))
+               return 0;
 
-         fprintf (stderr, "----------------------------\n");
-         fprintf (stderr, "INF: main background pid=%d\n", getpid());
-         fflush  (stderr);
+       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 WS_CLIENT:
+      if (afb_api_ws_add_client(item->value) < 0) {
+        ERROR("can't start the afb-websocket client of path %s",item->value);
+       exit(1);
+      }
+      break;
+    case WS_SERVICE:
+      if (afb_api_ws_add_server(item->value) < 0) {
+        ERROR("can't start the afb-websocket 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);
+  }
 }
 
 /*---------------------------------------------------------
@@ -524,44 +600,50 @@ static void daemonize(AFB_session *session)
  +--------------------------------------------------------- */
 
 int main(int argc, char *argv[])  {
-  AFB_session    *session;
+  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 -------
-  session = calloc (1, sizeof (AFB_session));
-  session->config = calloc (1, sizeof (AFB_config));
+  config = calloc (1, sizeof (struct afb_config));
 
-  on_exit(closeSession, session);
-  parse_arguments(argc, argv, session);
+  on_exit(closeSession, config);
+  parse_arguments(argc, argv, config);
 
   // ------------------ sanity check ----------------------------------------
-  if  ((session->background) && (session->foreground)) {
-    fprintf (stderr, "ERR: cannot select foreground & background at the same time\n");
-     exit (1);
-  }
-  if (session->config->httpdPort <= 0) {
-    fprintf (stderr, "ERR: no port is defined\n");
+  if (config->httpdPort <= 0) {
+     ERROR("no port is defined");
      exit (1);
   }
 
-  if (session->config->ldpaths) 
-    afb_apis_add_pathset(session->config->ldpaths);
-
-  ctxStoreInit(CTX_NBCLIENTS, session->config->cntxTimeout, afb_apis_count());
+  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);
+    }
+  }
 
-  install_error_handlers();
+  start_items(config->items);
+  config->items = NULL;
 
-  // ------------------ Some useful default values -------------------------
-  if  ((session->background == 0) && (session->foreground == 0)) session->foreground=1;
+  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);
+  }
 
-  // ------------------ 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;
   }
 
+  if (afb_common_rootdir_set(config->rootdir) < 0) {
+     ERROR("main fail to set common root directory");
+     return 1;
+  }
 
   // let's run this program with a low priority
   nice (20);
@@ -570,40 +652,40 @@ int main(int argc, char *argv[])  {
   // let's not take the risk to run as ROOT
   //if (getuid() == 0)  goto errorNoRoot;
 
-#if defined(ALLOWS_SESSION_FILES)
-  // check session dir and create if it does not exist
-  if (sessionCheckdir (session) != AFB_SUCCESS) {
-       fprintf (stderr,"\nERR: AFB-daemon cannot read/write session dir\n\n");
-       exit (1);
-  }
-#endif
-  if (verbose) fprintf (stderr, "AFB: notice Init config done\n");
-
-  // ---- run in foreground mode --------------------
-  if (session->foreground) {
-
-        if (verbose) fprintf (stderr,"AFB: notice Foreground mode\n");
-
-  } // end foreground
-
-  // --------- run in background mode -----------
-  if (session->background) {
-
-      if (verbose) printf ("AFB: Entering background mode\n");
+  DEBUG("Init config done");
 
-      daemonize(session);
+  // --------- run -----------
+  if (config->background) {
+      // --------- in background mode -----------
+      INFO("entering background mode");
+      daemonize(config);
+  } else {
+      // ---- in foreground mode --------------------
+      INFO("entering foreground mode");
+  }
 
-         // if everything look OK then look forever
-         syslog (LOG_ERR, "AFB: Entering infinite loop in background mode");
+   /* start the HTTP server */
+   hsrv = start_http_server(config);
+   if (hsrv == NULL)
+       exit(1);
 
+   /* start the services */
+   if (afb_apis_start_all_services(1) < 0)
+       exit(1);
 
-  } // end background-foreground
+   if (config->readyfd != 0) {
+               static const char readystr[] = "READY=1";
+               write(config->readyfd, readystr, sizeof(readystr) - 1);
+               close(config->readyfd);
+  }
 
+   // infinite loop
+  eventloop = afb_common_get_event_loop();
+  for(;;)
+    sd_event_run(eventloop, 30000000);
 
-  listenLoop(session);
-  if (verbose) printf ("\n---- Application Framework Binder Normal End ------\n");
-  exit(0);
+  WARNING("hoops returned from infinite loop [report bug]");
 
+  return 0;
 }
 
-