new main loop in place
[src/app-framework-binder.git] / src / main.c
index fdf8a34..41296e2 100644 (file)
  * limitations under the License.
  */
 
-#include <syslog.h>
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
 #include <setjmp.h>
 #include <signal.h>
-#include <getopt.h>
-#include <pwd.h>
+#include <syslog.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <stdint.h>
+
+#include "afb-plugin.h"
 
 #include "local-def.h"
+#include "afb-apis.h"
+#include "afb-hsrv.h"
+#include "session.h"
+#include "verbose.h"
+#include "utils-upoll.h"
 
 #if !defined(PLUGIN_INSTALL_DIR)
 #error "you should define PLUGIN_INSTALL_DIR"
@@ -117,24 +128,29 @@ static void printVersion (void)
 }
 
 // load config from disk and merge with CLI option
-static AFB_error config_set_default (AFB_session * session)
+static void config_set_default (AFB_session * session)
 {
    static char cacheTimeout [10];
    
    // default HTTP port
-   if (session->config->httpdPort == 0) session->config->httpdPort=1234;
+   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 (session->config->apiTimeout == 0)
+       session->config->apiTimeout = DEFLT_API_TIMEOUT;
    
    // default AUTH_TOKEN
-   if (session->config->token == NULL) session->config->token= DEFLT_AUTH_TOKEN;
+   if (session->config->token == NULL)
+               session->config->token = DEFLT_AUTH_TOKEN;
 
    // cache timeout default one hour
-   if (session->config->cacheTimeout == 0) session->config->cacheTimeout=DEFLT_CACHE_TIMEOUT;
+   if (session->config->cacheTimeout == 0)
+               session->config->cacheTimeout = DEFLT_CACHE_TIMEOUT;
 
    // cache timeout default one hour
-   if (session->config->cntxTimeout == 0) session->config->cntxTimeout=DEFLT_CNTX_TIMEOUT;
+   if (session->config->cntxTimeout == 0)
+               session->config->cntxTimeout = DEFLT_CNTX_TIMEOUT;
 
    if (session->config->rootdir == NULL) {
        session->config->rootdir = getenv("AFBDIR");
@@ -148,17 +164,14 @@ static AFB_error config_set_default (AFB_session * session)
    }
    
    // if no Angular/HTML5 rootbase let's try '/' as default
-   if  (session->config->rootbase == NULL) {
+   if  (session->config->rootbase == NULL)
        session->config->rootbase = "/opa";
-   }
    
-   if  (session->config->rootapi == NULL) {
+   if  (session->config->rootapi == NULL)
        session->config->rootapi = "/api";
-   }
 
-   if  (session->config->ldpaths == NULL) {
+   if  (session->config->ldpaths == NULL)
        session->config->ldpaths = PLUGIN_INSTALL_DIR;
-   }
 
    // if no session dir create a default path from rootdir
    if  (session->config->sessiondir == NULL) {
@@ -177,8 +190,6 @@ static AFB_error config_set_default (AFB_session * session)
    // 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;
 }
 
 
@@ -248,7 +259,7 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session)
     switch (optc)
     {
      case SET_VERBOSE:
-       verbose = 1;
+       verbosity++;
        break;
 
     case SET_TCP_PORT:
@@ -269,19 +280,19 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session)
     case SET_ROOT_DIR:
        if (optarg == 0) goto needValueForOption;
        session->config->rootdir   = optarg;
-       if (verbose) fprintf(stderr, "Forcing Rootdir=%s\n",session->config->rootdir);
+       if (verbosity) fprintf(stderr, "Forcing Rootdir=%s\n",session->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);
+       if (verbosity) fprintf(stderr, "Forcing Rootbase=%s\n",session->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);
+       if (verbosity) fprintf(stderr, "Forcing Rootapi=%s\n",session->config->rootapi);
        break;
        
     case SET_ALIAS:
@@ -293,7 +304,7 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session)
             } 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);
+              if (verbosity) fprintf(stderr, "Alias url=%s path=%s\n", aliasdir[aliascount].url, aliasdir[aliascount].path);
               aliascount++;
             }
        } else {
@@ -397,47 +408,48 @@ static void closeSession (int status, void *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);
+void signalQuit (int signum)
+{
+       fprintf(stderr, "Terminating signal received %s\n", strsignal(signum));
+       exit(1);
 }
 
 
 /*----------------------------------------------------------
- | listenLoop
- |   Main listening HTTP loop
+ | Error signals
+ |
  +--------------------------------------------------------- */
-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);
+__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);
+}
 
-   // infinite loop
-   httpdLoop(session);
+static void install_error_handlers()
+{
+       int i, signals[] = { SIGALRM, SIGSEGV, SIGFPE, 0 };
 
-   fprintf (stderr, "hoops returned from infinite loop [report bug]\n");
+       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
@@ -491,6 +503,7 @@ static void daemonize(AFB_session *session)
  +--------------------------------------------------------- */
 
 int main(int argc, char *argv[])  {
+  int rc;
   AFB_session    *session;
 
   // open syslog if ever needed
@@ -503,8 +516,6 @@ int main(int argc, char *argv[])  {
   on_exit(closeSession, session);
   parse_arguments(argc, argv, session);
 
-  initPlugins(session);
-
   // ------------------ sanity check ----------------------------------------
   if  ((session->background) && (session->foreground)) {
     fprintf (stderr, "ERR: cannot select foreground & background at the same time\n");
@@ -515,8 +526,16 @@ int main(int argc, char *argv[])  {
      exit (1);
   }
 
+  if (session->config->ldpaths) 
+    afb_apis_add_pathset(session->config->ldpaths);
+
+  ctxStoreInit(CTX_NBCLIENTS, session->config->cntxTimeout, afb_apis_count(), session->config->token);
+
+  install_error_handlers();
+
   // ------------------ Some useful default values -------------------------
-  if  ((session->background == 0) && (session->foreground == 0)) session->foreground=1;
+  if  ((session->background == 0) && (session->foreground == 0))
+       session->foreground = 1;
 
   // ------------------ clean exit on CTR-C signal ------------------------
   if (signal (SIGINT, signalQuit) == SIG_ERR || signal (SIGABRT, signalQuit) == SIG_ERR) {
@@ -524,7 +543,6 @@ int main(int argc, char *argv[])  {
      return 1;
   }
 
-
   // let's run this program with a low priority
   nice (20);
 
@@ -532,24 +550,19 @@ int main(int argc, char *argv[])  {
   // let's not take the risk to run as ROOT
   //if (getuid() == 0)  goto errorNoRoot;
 
-  // 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);
-  }
-  if (verbose) fprintf (stderr, "AFB: notice Init config done\n");
+  if (verbosity) fprintf (stderr, "AFB: notice Init config done\n");
 
   // ---- run in foreground mode --------------------
   if (session->foreground) {
 
-        if (verbose) fprintf (stderr,"AFB: notice Foreground mode\n");
+        if (verbosity) fprintf (stderr,"AFB: notice Foreground mode\n");
 
   } // end foreground
 
   // --------- run in background mode -----------
   if (session->background) {
 
-      if (verbose) printf ("AFB: Entering background mode\n");
+      if (verbosity) printf ("AFB: Entering background mode\n");
 
       daemonize(session);
 
@@ -560,10 +573,26 @@ int main(int argc, char *argv[])  {
   } // end background-foreground
 
 
-  listenLoop(session);
-  if (verbose) printf ("\n---- Application Framework Binder Normal End ------\n");
-  exit(0);
+  // ------ Start httpd server
+
+   rc = afb_hsrv_start (session);
+   if (!rc)
+       exit(1);
+
+   if (session->readyfd != 0) {
+               static const char readystr[] = "READY=1";
+               write(session->readyfd, readystr, sizeof(readystr) - 1);
+               close(session->readyfd);
+  }
+
+   // infinite loop
+  for(;;)
+   upoll_wait(30000); 
+
+   if (verbosity)
+       fprintf (stderr, "hoops returned from infinite loop [report bug]\n");
 
+  return 0;
 }