diff options
-rw-r--r-- | src/afb-hreq.c | 2 | ||||
-rw-r--r-- | src/afb-hreq.h | 2 | ||||
-rw-r--r-- | src/afb-hsrv.c | 179 | ||||
-rw-r--r-- | src/afb-hsrv.h | 8 | ||||
-rw-r--r-- | src/local-def.h | 7 | ||||
-rw-r--r-- | src/main.c | 46 |
6 files changed, 137 insertions, 107 deletions
diff --git a/src/afb-hreq.c b/src/afb-hreq.c index badddd1e..3f95c532 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -380,7 +380,7 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f } /* fills the value and send */ - MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, hreq->session->cacheTimeout); + MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, hreq->cacheTimeout); MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag); MHD_queue_response(hreq->connection, status, response); MHD_destroy_response(response); diff --git a/src/afb-hreq.h b/src/afb-hreq.h index c317a7a5..752d06ce 100644 --- a/src/afb-hreq.h +++ b/src/afb-hreq.h @@ -19,7 +19,7 @@ struct AFB_session; struct AFB_clientCtx; struct afb_hreq { - struct AFB_session *session; + const char *cacheTimeout; struct MHD_Connection *connection; enum afb_method method; const char *version; diff --git a/src/afb-hsrv.c b/src/afb-hsrv.c index 334b8b3b..61366552 100644 --- a/src/afb-hsrv.c +++ b/src/afb-hsrv.c @@ -57,12 +57,14 @@ struct afb_diralias { }; struct afb_hsrv { - struct MHD_Daemon *httpd; + unsigned refcount; struct afb_hsrv_handler *handlers; + struct MHD_Daemon *httpd; struct upoll *upoll; + char *cache_to; }; -static struct upoll *upoll = NULL; + static struct afb_hsrv_handler *new_handler( struct afb_hsrv_handler *head, @@ -106,7 +108,7 @@ static struct afb_hsrv_handler *new_handler( } int afb_hsrv_add_handler( - AFB_session * session, + struct afb_hsrv *hsrv, const char *prefix, int (*handler) (struct afb_hreq *, void *), void *data, @@ -114,10 +116,10 @@ int afb_hsrv_add_handler( { struct afb_hsrv_handler *head; - head = new_handler(session->handlers, prefix, handler, data, priority); + head = new_handler(hsrv->handlers, prefix, handler, data, priority); if (head == NULL) return 0; - session->handlers = head; + hsrv->handlers = head; return 1; } @@ -200,7 +202,7 @@ static int handle_alias(struct afb_hreq *hreq, void *data) return afb_hreq_reply_file(hreq, da->dirfd, &hreq->tail[1]); } -int afb_hsrv_add_alias(AFB_session * session, const char *prefix, const char *alias, int priority) +int afb_hsrv_add_alias(struct afb_hsrv *hsrv, const char *prefix, const char *alias, int priority) { struct afb_diralias *da; int dirfd; @@ -216,7 +218,7 @@ int afb_hsrv_add_alias(AFB_session * session, const char *prefix, const char *al da->directory = alias; da->lendir = strlen(da->directory); da->dirfd = dirfd; - if (afb_hsrv_add_handler(session, prefix, handle_alias, da, priority)) + if (afb_hsrv_add_handler(hsrv, prefix, handle_alias, da, priority)) return 1; free(da); } @@ -224,7 +226,7 @@ int afb_hsrv_add_alias(AFB_session * session, const char *prefix, const char *al return 0; } -void afb_hsrv_reply_error(struct MHD_Connection *connection, unsigned int status) +static void reply_error(struct MHD_Connection *connection, unsigned int status) { char *buffer; int length; @@ -272,11 +274,11 @@ static int access_handler( int rc; struct afb_hreq *hreq; enum afb_method method; - AFB_session *session; + struct afb_hsrv *hsrv; struct afb_hsrv_handler *iter; const char *type; - session = cls; + hsrv = cls; hreq = *recordreq; if (hreq == NULL) { /* create the request */ @@ -292,7 +294,7 @@ static int access_handler( goto bad_request; /* init the request */ - hreq->session = cls; + hreq->cacheTimeout = hsrv->cache_to; hreq->connection = connection; hreq->method = method; hreq->version = version; @@ -311,7 +313,7 @@ static int access_handler( goto internal_error; return MHD_YES; } else if (strcasestr(type, JSON_CONTENT) == NULL) { - afb_hsrv_reply_error(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE); + reply_error(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE); return MHD_YES; } } @@ -339,7 +341,7 @@ static int access_handler( } /* search an handler for the request */ - iter = session->handlers; + iter = hsrv->handlers; while (iter) { if (afb_hreq_unprefix(hreq, iter->prefix, iter->length)) { if (iter->handler(hreq, iter->data)) @@ -355,11 +357,11 @@ static int access_handler( return MHD_YES; bad_request: - afb_hsrv_reply_error(connection, MHD_HTTP_BAD_REQUEST); + reply_error(connection, MHD_HTTP_BAD_REQUEST); return MHD_YES; internal_error: - afb_hsrv_reply_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); + reply_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); return MHD_YES; } @@ -380,61 +382,43 @@ static int new_client_handler(void *cls, const struct sockaddr *addr, socklen_t return MHD_YES; } -static int my_default_init(AFB_session * session) +/* infinite loop */ +static void hsrv_handle_event(struct MHD_Daemon *httpd) { - int idx; - - if (!afb_hsrv_add_handler(session, session->config->rootapi, afb_hreq_websocket_switch, NULL, 20)) - return 0; - - if (!afb_hsrv_add_handler(session, session->config->rootapi, afb_hreq_rest_api, NULL, 10)) - return 0; - - for (idx = 0; session->config->aliasdir[idx].url != NULL; idx++) - if (!afb_hsrv_add_alias (session, session->config->aliasdir[idx].url, session->config->aliasdir[idx].path, 0)) - return 0; + MHD_run(httpd); +} - if (!afb_hsrv_add_alias(session, "", session->config->rootdir, -10)) - return 0; +int afb_hsrv_set_cache_timeout(struct afb_hsrv *hsrv, int duration) +{ + int rc; + char *dur; - if (!afb_hsrv_add_handler(session, session->config->rootbase, afb_hreq_one_page_api_redirect, NULL, -20)) + rc = asprintf(&dur, "%d", duration); + if (rc < 0) return 0; + free(hsrv->cache_to); + hsrv->cache_to = dur; return 1; } -/* infinite loop */ -static void hsrv_handle_event(struct MHD_Daemon *httpd) -{ - MHD_run(httpd); -} - -int afb_hsrv_start(AFB_session * session) +int _afb_hsrv_start(struct afb_hsrv *hsrv, uint16_t port, unsigned int connection_timeout) { + struct upoll *upoll; struct MHD_Daemon *httpd; const union MHD_DaemonInfo *info; - if (!my_default_init(session)) { - printf("Error: initialisation of httpd failed"); - return 0; - } - - 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); - } - 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 */ + port, /* port */ new_client_handler, NULL, /* Tcp Accept call back + extra attribute */ - access_handler, session, /* Http Request Call back + extra attribute */ - MHD_OPTION_NOTIFY_COMPLETED, end_handler, session, - MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int)15, /* 15 seconds */ + access_handler, hsrv, /* Http Request Call back + extra attribute */ + MHD_OPTION_NOTIFY_COMPLETED, end_handler, hsrv, + MHD_OPTION_CONNECTION_TIMEOUT, connection_timeout, MHD_OPTION_END); /* options-end */ if (httpd == NULL) { - printf("Error: httpStart invalid httpd port: %d", session->config->httpdPort); + printf("Error: httpStart invalid httpd port: %d", (int)port); return 0; } @@ -453,17 +437,94 @@ int afb_hsrv_start(AFB_session * session) } upoll_on_readable(upoll, (void*)hsrv_handle_event); - session->httpd = httpd; + hsrv->httpd = httpd; + hsrv->upoll = upoll; + return 1; +} + +void _afb_hsrv_stop(struct afb_hsrv *hsrv) +{ + if (hsrv->upoll) + upoll_close(hsrv->upoll); + hsrv->upoll = NULL; + if (hsrv->httpd != NULL) + MHD_stop_daemon(hsrv->httpd); + hsrv->httpd = NULL; +} + +struct afb_hsrv *afb_hsrv_create() +{ + struct afb_hsrv *result = calloc(1, sizeof(struct afb_hsrv)); + if (result != NULL) + result->refcount = 1; + return result; +} + +void afb_hsrv_put(struct afb_hsrv *hsrv) +{ + assert(hsrv->refcount != 0); + if (!--hsrv->refcount) { + _afb_hsrv_stop(hsrv); + free(hsrv); + } +} + +static int my_default_init(struct afb_hsrv *hsrv, AFB_session * session) +{ + int idx; + + if (!afb_hsrv_add_handler(hsrv, session->config->rootapi, afb_hreq_websocket_switch, NULL, 20)) + return 0; + + if (!afb_hsrv_add_handler(hsrv, session->config->rootapi, afb_hreq_rest_api, NULL, 10)) + return 0; + + for (idx = 0; session->config->aliasdir[idx].url != NULL; idx++) + if (!afb_hsrv_add_alias (hsrv, session->config->aliasdir[idx].url, session->config->aliasdir[idx].path, 0)) + return 0; + + if (!afb_hsrv_add_alias(hsrv, "", session->config->rootdir, -10)) + return 0; + + if (!afb_hsrv_add_handler(hsrv, session->config->rootbase, afb_hreq_one_page_api_redirect, NULL, -20)) + return 0; + + return 1; +} + +int afb_hsrv_start(AFB_session * session) +{ + int rc; + struct afb_hsrv *hsrv; + + hsrv = afb_hsrv_create(); + if (hsrv == NULL) { + fprintf(stderr, "memory allocation failure\n"); + return 0; + } + + if (!afb_hsrv_set_cache_timeout(hsrv, session->config->cacheTimeout) + || !my_default_init(hsrv, session)) { + printf("Error: initialisation of httpd failed"); + afb_hsrv_put(hsrv); + return 0; + } + + 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); + } + + rc = _afb_hsrv_start(hsrv, (uint16_t) session->config->httpdPort, 15); + if (!rc) + return 0; + + session->hsrv = hsrv; return 1; } void afb_hsrv_stop(AFB_session * session) { - if (upoll) - upoll_close(upoll); - upoll = NULL; - if (session->httpd != NULL) - MHD_stop_daemon(session->httpd); - session->httpd = NULL; + _afb_hsrv_stop(session->hsrv); } diff --git a/src/afb-hsrv.h b/src/afb-hsrv.h index da4fe09a..93b845c1 100644 --- a/src/afb-hsrv.h +++ b/src/afb-hsrv.h @@ -16,5 +16,9 @@ limitations under the License. */ -int afb_hsrv_start(AFB_session * session); -void afb_hsrv_stop(AFB_session * session); +struct afb_hsrv; + +extern struct afb_hsrv *afb_hsrv_create(); + +extern int afb_hsrv_start(AFB_session * session); +extern void afb_hsrv_stop(AFB_session * session); diff --git a/src/local-def.h b/src/local-def.h index fcab6adb..1992b510 100644 --- a/src/local-def.h +++ b/src/local-def.h @@ -63,6 +63,7 @@ struct AFB_config AFB_aliasdir *aliasdir; // alias mapping for icons,apps,... }; +struct afb_hsrv; struct afb_hsrv_handler; struct MHD_Daemon; @@ -71,12 +72,8 @@ struct AFB_session struct AFB_config *config; // pointer to current config // List of commands to execute int background; // run in backround mode - int foreground; // run in forground mode - char *cacheTimeout; // http require timeout to be a string - struct MHD_Daemon *httpd; // structure for httpd handler - int fakemod; // respond to GET/POST request without interacting with sndboard int readyfd; // a #fd to signal when ready to serve - struct afb_hsrv_handler *handlers; + struct afb_hsrv *hsrv; }; @@ -46,7 +46,6 @@ #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 @@ -129,8 +128,6 @@ static void printVersion (void) // load config from disk and merge with CLI option static void config_set_default (AFB_session * session) { - static char cacheTimeout [10]; - // default HTTP port if (session->config->httpdPort == 0) session->config->httpdPort = 1234; @@ -185,10 +182,6 @@ static void config_set_default (AFB_session * session) strncpy (session->config->console, session->config->sessiondir, 512); strncat (session->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 } @@ -331,14 +324,9 @@ static void parse_arguments(int argc, char *argv[], AFB_session *session) if (!sscanf (optarg, "%d", &session->config->cacheTimeout)) goto notAnInteger; break; - case SET_FAKE_MOD: - if (optarg != 0) goto noValueForOption; - session->fakemod = 1; - break; - case SET_FORGROUND: if (optarg != 0) goto noValueForOption; - session->foreground = 1; + session->background = 0; break; case SET_BACKGROUND: @@ -516,10 +504,6 @@ int main(int argc, char *argv[]) { parse_arguments(argc, argv, session); // ------------------ 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"); exit (1); @@ -532,10 +516,6 @@ int main(int argc, char *argv[]) { install_error_handlers(); - // ------------------ Some useful default values ------------------------- - 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) { fprintf (stderr, "ERR: main fail to install Signal handler\n"); @@ -551,28 +531,16 @@ int main(int argc, char *argv[]) { if (verbosity) fprintf (stderr, "AFB: notice Init config done\n"); - // ---- run in foreground mode -------------------- - if (session->foreground) { - - if (verbosity) fprintf (stderr,"AFB: notice Foreground mode\n"); - - } // end foreground - - // --------- run in background mode ----------- + // --------- run ----------- if (session->background) { - + // --------- in background mode ----------- if (verbosity) printf ("AFB: Entering background mode\n"); - daemonize(session); + } else { + // ---- in foreground mode -------------------- + if (verbosity) fprintf (stderr,"AFB: notice Foreground mode\n"); - // if everything look OK then look forever - syslog (LOG_ERR, "AFB: Entering infinite loop in background mode"); - - - } // end background-foreground - - - // ------ Start httpd server + } rc = afb_hsrv_start (session); if (!rc) |