summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2016-04-05 15:25:28 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2016-04-05 15:25:28 +0200
commit13549775092afa9215de8468e34f6d194c2fd8db (patch)
tree46a54c5b1cc8fe05771f81ed89ce6decb8b64491
parentefe18167d6ce59b263c179a6e2d01aa875c05cf8 (diff)
new main loop in place
Change-Id: If297e0a76e74422d456447be52cca460c9e237b3 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--include/afb-plugin.h2
-rw-r--r--include/afb-poll-itf.h4
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/afb-apis.c8
-rw-r--r--src/afb-hsrv.c (renamed from src/http-svc.c)81
-rw-r--r--src/local-def.h23
-rw-r--r--src/main.c109
-rw-r--r--src/proto-def.h30
-rw-r--r--src/utils-upoll.c49
-rw-r--r--src/utils-upoll.h7
-rw-r--r--src/verbose.h2
11 files changed, 142 insertions, 175 deletions
diff --git a/include/afb-plugin.h b/include/afb-plugin.h
index ba86e181..4064f9e9 100644
--- a/include/afb-plugin.h
+++ b/include/afb-plugin.h
@@ -67,7 +67,7 @@ struct AFB_interface
{
int verbosity;
enum AFB_Mode mode;
- struct afb_poll (*poll_open)(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure);
+ struct afb_poll (*poll_open)(int fd, void *closure);
};
extern const struct AFB_plugin *pluginRegister (const struct AFB_interface *interface);
diff --git a/include/afb-poll-itf.h b/include/afb-poll-itf.h
index 4ce1fa48..2c8889b6 100644
--- a/include/afb-poll-itf.h
+++ b/include/afb-poll-itf.h
@@ -17,7 +17,9 @@
struct afb_poll_itf
{
- int (*update)(void *data, uint32_t events);
+ int (*on_readable)(void *, void (*cb)(void *));
+ int (*on_writable)(void *, void (*cb)(void *));
+ int (*on_hangup)(void *, void (*cb)(void *));
void (*close)(void *data);
};
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d8bddcf0..3f8b84c6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,7 +2,7 @@
ADD_LIBRARY(src OBJECT
main.c
session.c
- http-svc.c
+ afb-hsrv.c
afb-apis.c
afb-method.c
afb-hreq.c
diff --git a/src/afb-apis.c b/src/afb-apis.c
index 55e68c93..9dcb1809 100644
--- a/src/afb-apis.c
+++ b/src/afb-apis.c
@@ -63,7 +63,9 @@ static int apis_count = 0;
static const char plugin_register_function[] = "pluginRegister";
static const struct afb_poll_itf upoll_itf = {
- .update = (void*)upoll_update,
+ .on_readable = (void*)upoll_on_readable,
+ .on_writable = (void*)upoll_on_writable,
+ .on_hangup = (void*)upoll_on_hangup,
.close = (void*)upoll_close
};
@@ -85,10 +87,10 @@ void afb_apis_free_context(int apiidx, void *context)
free(context);
}
-static struct afb_poll itf_poll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure)
+static struct afb_poll itf_poll_open(int fd, void *closure)
{
struct afb_poll result;
- result.data = upoll_open(fd, events, process, closure);
+ result.data = upoll_open(fd, closure);
result.itf = result.data ? &upoll_itf : NULL;
return result;
}
diff --git a/src/http-svc.c b/src/afb-hsrv.c
index b36d5f7e..a358cbd7 100644
--- a/src/http-svc.c
+++ b/src/afb-hsrv.c
@@ -33,6 +33,7 @@
#include "afb-apis.h"
#include "afb-req-itf.h"
#include "verbose.h"
+#include "utils-upoll.h"
#define JSON_CONTENT "application/json"
#define FORM_CONTENT MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA
@@ -54,6 +55,8 @@ struct afb_diralias {
int dirfd;
};
+static struct upoll *upoll = NULL;
+
int afb_hreq_one_page_api_redirect(
struct afb_hreq *hreq,
void *data)
@@ -422,27 +425,36 @@ static int my_default_init(AFB_session * session)
if (!afb_hsrv_add_handler(session, session->config->rootbase, afb_hreq_one_page_api_redirect, NULL, -20))
return 0;
+#if defined(USE_MAGIC_MIME_TYPE)
+ /*TBD open libmagic cache [fail to pass EFENCE check (allocating 0 bytes)] */
+ init_lib_magic (session);
+#endif
+
return 1;
}
-AFB_error httpdStart(AFB_session * session)
+/* infinite loop */
+static void hsrv_handle_event(struct MHD_Daemon *httpd)
{
+ MHD_run(httpd);
+}
+
+int afb_hsrv_start(AFB_session * session)
+{
+ struct MHD_Daemon *httpd;
+ const union MHD_DaemonInfo *info;
+
if (!my_default_init(session)) {
printf("Error: initialisation of httpd failed");
- return AFB_FATAL;
+ return 0;
}
-#if defined(USE_MAGIC_MIME_TYPE)
- /*TBD open libmagic cache [fail to pass EFENCE check (allocating 0 bytes)] */
- init_lib_magic (session);
-#endif
-
if (verbosity) {
printf("AFB:notice Waiting port=%d rootdir=%s\n", session->config->httpdPort, session->config->rootdir);
printf("AFB:notice Browser URL= http:/*localhost:%d\n", session->config->httpdPort);
}
- session->httpd = MHD_start_daemon(
+ httpd = MHD_start_daemon(
MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_TCP_FASTOPEN | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME,
(uint16_t) session->config->httpdPort, /* port */
new_client_handler, NULL, /* Tcp Accept call back + extra attribute */
@@ -451,48 +463,37 @@ AFB_error httpdStart(AFB_session * session)
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int)15, /* 15 seconds */
MHD_OPTION_END); /* options-end */
- if (session->httpd == NULL) {
+ if (httpd == NULL) {
printf("Error: httpStart invalid httpd port: %d", session->config->httpdPort);
- return AFB_FATAL;
+ return 0;
}
- return AFB_SUCCESS;
-}
-/* infinite loop */
-AFB_error httpdLoop(AFB_session * session)
-{
- int count = 0;
- const union MHD_DaemonInfo *info;
- struct pollfd pfd;
-
- info = MHD_get_daemon_info(session->httpd, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
+ info = MHD_get_daemon_info(httpd, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
if (info == NULL) {
- printf("Error: httpLoop no pollfd");
- goto error;
+ MHD_stop_daemon(httpd);
+ fprintf(stderr, "Error: httpStart no pollfd");
+ return 0;
}
- pfd.fd = info->listen_fd;
- pfd.events = POLLIN;
- if (verbosity)
- fprintf(stderr, "AFB:notice entering httpd waiting loop\n");
- while (TRUE) {
- if (verbosity)
- fprintf(stderr, "AFB:notice httpd alive [%d]\n", count++);
- poll(&pfd, 1, 15000); /* 15 seconds (as above timeout when starting) */
- MHD_run(session->httpd);
+ upoll = upoll_open(info->listen_fd, httpd);
+ if (upoll == NULL) {
+ MHD_stop_daemon(httpd);
+ fprintf(stderr, "Error: connection to upoll of httpd failed");
+ return 0;
}
+ upoll_on_readable(upoll, (void*)hsrv_handle_event);
- error:
- /* should never return from here */
- return AFB_FATAL;
+ session->httpd = httpd;
+ return 1;
}
-int httpdStatus(AFB_session * session)
+void afb_hsrv_stop(AFB_session * session)
{
- return MHD_run(session->httpd);
+ if (upoll)
+ upoll_close(upoll);
+ upoll = NULL;
+ if (session->httpd != NULL)
+ MHD_stop_daemon(session->httpd);
+ session->httpd = NULL;
}
-void httpdStop(AFB_session * session)
-{
- MHD_stop_daemon(session->httpd);
-}
diff --git a/src/local-def.h b/src/local-def.h
index 3298322e..c21918cd 100644
--- a/src/local-def.h
+++ b/src/local-def.h
@@ -40,22 +40,6 @@
#define DEFLT_HTTP_TIMEOUT 15 // Max MibMicroHttp timeout
#define AFB_MAX_PLUGINS 20 // Max number of plugins for a given binder
-#ifndef FALSE
- #define FALSE 0
-#endif
-#ifndef TRUE
- #define TRUE 1
-#endif
-
-#define PUBLIC
-#define STATIC static
-#define FAILED -1
-
-#define AUDIO_BUFFER "/tmp/buf"
-
-// prebuild json error are constructed in helper-api.c
-typedef enum { AFB_FALSE, AFB_TRUE, AFB_FATAL, AFB_FAIL, AFB_WARNING, AFB_EMPTY, AFB_SUCCESS, AFB_DONE, AFB_UNAUTH} AFB_error;
-
#define MAX_POST_SIZE 4096 // maximum size for POST data
#define CTX_NBCLIENTS 10 // allow a default of 10 authenticated clients
@@ -63,11 +47,6 @@ typedef enum { AFB_FALSE, AFB_TRUE, AFB_FATAL, AFB_FAIL, AFB_WARNING, AFB_EMPTY
-
-
-
-
-
enum AFB_Mode;
@@ -133,6 +112,4 @@ struct AFB_session
typedef struct AFB_config AFB_config;
typedef struct AFB_session AFB_session;
-#include "proto-def.h"
-
#endif /* LOCAL_DEF_H */
diff --git a/src/main.c b/src/main.c
index 15f84b18..41296e2c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,8 +32,10 @@
#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"
@@ -126,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");
@@ -157,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) {
@@ -186,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;
}
@@ -406,20 +408,11 @@ 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);
}
@@ -439,6 +432,10 @@ static void signalError(int 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()
@@ -454,30 +451,6 @@ static void install_error_handlers()
}
/*----------------------------------------------------------
- | 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
+--------------------------------------------------------- */
@@ -530,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
@@ -560,7 +534,8 @@ int main(int argc, char *argv[]) {
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) {
@@ -568,7 +543,6 @@ int main(int argc, char *argv[]) {
return 1;
}
-
// let's run this program with a low priority
nice (20);
@@ -576,13 +550,6 @@ 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 (verbosity) fprintf (stderr, "AFB: notice Init config done\n");
// ---- run in foreground mode --------------------
@@ -606,10 +573,26 @@ int main(int argc, char *argv[]) {
} // end background-foreground
- listenLoop(session);
- if (verbosity) 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;
}
diff --git a/src/proto-def.h b/src/proto-def.h
deleted file mode 100644
index b549a62e..00000000
--- a/src/proto-def.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- proto-def.h -- provide a REST/HTTP interface
-
- Copyright (C) 2015, Fulup Ar Foll
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-
-// Httpd server
-extern AFB_error httpdStart (AFB_session *session);
-extern AFB_error httpdLoop (AFB_session *session);
-extern void httpdStop (AFB_session *session);
-
-
-
-
diff --git a/src/utils-upoll.c b/src/utils-upoll.c
index af4a6161..eb0e9674 100644
--- a/src/utils-upoll.c
+++ b/src/utils-upoll.c
@@ -28,7 +28,9 @@
struct upoll
{
int fd;
- void (*process)(void *closure, int fd, uint32_t events);
+ void (*read)(void *);
+ void (*write)(void *);
+ void (*hangup)(void *);
void *closure;
struct upoll *next;
};
@@ -48,7 +50,7 @@ int upoll_is_valid(struct upoll *upoll)
return 0;
}
-struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure)
+struct upoll *upoll_open(int fd, void *closure)
{
struct epoll_event e;
struct upoll *result;
@@ -68,13 +70,12 @@ struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure,
}
/* allocates */
- result = malloc(sizeof *result);
+ result = calloc(1, sizeof *result);
if (result == NULL)
return NULL;
/* init */
result->fd = fd;
- result->process = process;
result->closure = closure;
pthread_mutex_lock(&mutex);
result->next = head;
@@ -82,7 +83,7 @@ struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure,
pthread_mutex_unlock(&mutex);
/* records */
- e.events = events;
+ e.events = 0;
e.data.ptr = result;
rc = epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, &e);
if (rc == 0)
@@ -95,16 +96,39 @@ struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure,
return NULL;
}
-int upoll_update(struct upoll *upoll, uint32_t events)
+static int update(struct upoll *upoll)
{
struct epoll_event e;
+ e.events = (upoll->read != NULL ? EPOLLIN : 0 )
+ | (upoll->write != NULL ? EPOLLOUT : 0);
+ e.data.ptr = upoll;
+ return epoll_ctl(pollfd, EPOLL_CTL_MOD, upoll->fd, &e);
+}
+int upoll_on_readable(struct upoll *upoll, void (*process)(void *))
+{
assert(pollfd != 0);
assert(upoll_is_valid(upoll));
- e.events = events;
- e.data.ptr = upoll;
- return epoll_ctl(pollfd, EPOLL_CTL_MOD, upoll->fd, &e);
+ upoll->read = process;
+ return update(upoll);
+}
+
+int upoll_on_writable(struct upoll *upoll, void (*process)(void *))
+{
+ assert(pollfd != 0);
+ assert(upoll_is_valid(upoll));
+
+ upoll->write = process;
+ return update(upoll);
+}
+
+void upoll_on_hangup(struct upoll *upoll, void (*process)(void *))
+{
+ assert(pollfd != 0);
+ assert(upoll_is_valid(upoll));
+
+ upoll->hangup = process;
}
void upoll_close(struct upoll *upoll)
@@ -136,7 +160,12 @@ void upoll_wait(int timeout)
rc = epoll_wait(pollfd, &e, 1, timeout);
if (rc == 1) {
upoll = e.data.ptr;
- upoll->process(upoll->closure, upoll->fd, e.events);
+ if ((e.events & EPOLLIN) && upoll->read)
+ upoll->read(upoll->closure);
+ if ((e.events & EPOLLOUT) && upoll->write)
+ upoll->write(upoll->closure);
+ if ((e.events & EPOLLHUP) && upoll->hangup)
+ upoll->hangup(upoll->closure);
}
}
diff --git a/src/utils-upoll.h b/src/utils-upoll.h
index 24aaf41a..705fbc36 100644
--- a/src/utils-upoll.h
+++ b/src/utils-upoll.h
@@ -19,9 +19,12 @@ struct upoll;
extern int upoll_is_valid(struct upoll *upoll);
-extern struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure);
+extern struct upoll *upoll_open(int fd, void *closure);
-extern int upoll_update(struct upoll *upoll, uint32_t events);
+extern int upoll_on_readable(struct upoll *upoll, void (*process)(void *closure));
+extern int upoll_on_writable(struct upoll *upoll, void (*process)(void *closure));
+
+extern void upoll_on_hangup(struct upoll *upoll, void (*process)(void *closure));
extern void upoll_close(struct upoll *upoll);
diff --git a/src/verbose.h b/src/verbose.h
index 7b32a663..09254b22 100644
--- a/src/verbose.h
+++ b/src/verbose.h
@@ -1,5 +1,5 @@
/*
- Copyright 2015 IoT.bzh
+ Copyright 2016 IoT.bzh
author: José Bollo <jose.bollo@iot.bzh>