POST https://www.gnu.org/software/libmicrohttpd/manual/html_node/microhttpd_002dpost.html#microhttpd_002dpost
*/
+#define _GNU_SOURCE
#include <microhttpd.h>
+#include <poll.h>
#include <sys/stat.h>
#include "../include/local-def.h"
// let's compute fixed URL length only once
-static apiUrlLen=0;
-static baseUrlLen=0;
-
-// proto missing from GCC
-char *strcasestr(const char *haystack, const char *needle);
-
-static int rqtcount = 0; // dummy request rqtcount to make each message be different
-static int postcount = 0;
+static size_t apiUrlLen=0;
+static size_t baseUrlLen=0;
+static size_t rootUrlLen=0;
// try to open libmagic to handle mime types
static AFB_error initLibMagic (AFB_session *session) {
// Because of POST call multiple time requestApi we need to free POST handle here
static void endRequest (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) {
- AFB_HttpPost *posthandle = *con_cls;
+ AFB_PostHandle *posthandle = *con_cls;
// if post handle was used let's free everything
- if (posthandle) {
- if (verbose) fprintf (stderr, "End Post Request UID=%d\n", posthandle->uid);
- free (posthandle->data);
- free (posthandle);
- }
+ if (posthandle != NULL) endPostRequest (posthandle);
}
// Create check etag value
-STATIC void computeEtag(char *etag, int maxlen, struct stat *sbuf) {
- int time;
+STATIC void computeEtag(char *etag, size_t maxlen, struct stat *sbuf) {
+ long time;
time = sbuf->st_mtim.tv_sec;
- snprintf(etag, maxlen, "%d", time);
+ snprintf(etag, maxlen, "%ld", time);
}
STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, const char *url, AFB_staticfile *staticfile) {
const char *etagCache, *mimetype;
char etagValue[15];
- struct MHD_Response *response;
+ struct MHD_Response *response = NULL;
struct stat sbuf;
- int ret;
if (fstat (staticfile->fd, &sbuf) != 0) {
fprintf(stderr, "Fail to stat file: [%s] error:%s\n", staticfile->path, strerror(errno));
goto abortRequest;
}
-
- if (! S_ISREG (sbuf.st_mode)) { // only standard file any other one including symbolic links are refused.
- close (staticfile->fd); // nothing useful to do with this file
- fprintf (stderr, "Fail file: [%s] is not a regular file\n", staticfile->path);
- const char *errorstr = "<html><body>Alsa-Json-Gateway Invalid file type</body></html>";
- response = MHD_create_response_from_buffer (strlen (errorstr),
- (void *) errorstr, MHD_RESPMEM_PERSISTENT);
- MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
- goto sendRequest;
- }
-
+
// if url is a directory let's add index.html and redirect client
if (S_ISDIR (sbuf.st_mode)) {
close (staticfile->fd); // close directory check for Index
// No trailing '/'. Let's add one and redirect for relative paths to work
if (url [strlen (url) -1] != '/') {
response = MHD_create_response_from_buffer(0,"", MHD_RESPMEM_PERSISTENT);
+ strncpy(staticfile->path, url, sizeof (staticfile->path));
strncat(staticfile->path, "/", sizeof (staticfile->path));
MHD_add_response_header (response, "Location", staticfile->path);
MHD_queue_response (connection, MHD_HTTP_MOVED_PERMANENTLY, response);
if (-1 == (staticfile->fd = open(staticfile->path, O_RDONLY)) || (fstat (staticfile->fd, &sbuf) != 0)) {
fprintf(stderr, "No Index.html in direcory [%s]\n", staticfile->path);
goto abortRequest;
- }
- }
+ }
+ } else if (! S_ISREG (sbuf.st_mode)) { // only standard file any other one including symbolic links are refused.
+ close (staticfile->fd); // nothing useful to do with this file
+ fprintf (stderr, "Fail file: [%s] is not a regular file\n", staticfile->path);
+ const char *errorstr = "<html><body>Application Framework Binder Invalid file type</body></html>";
+ response = MHD_create_response_from_buffer (strlen (errorstr),
+ (void *) errorstr, MHD_RESPMEM_PERSISTENT);
+ MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
+ goto sendRequest;
+ }
// https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=fr
// ftp://ftp.heanet.ie/disk1/www.gnu.org/software/libmicrohttpd/doxygen/dc/d0c/microhttpd_8h.html
if (session->magic) {
mimetype= magic_descriptor(session->magic, staticfile->fd);
if (mimetype != NULL) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, mimetype);
- } else mimetype="Unknown";
+ } else mimetype="application/unknown";
if (verbose) fprintf(stderr, "Serving: [%s] mime=%s\n", staticfile->path, mimetype);
response = MHD_create_response_from_fd(sbuf.st_size, staticfile->fd);
// this function return either Index.htlm or a redirect to /#!route to make angular happy
STATIC int redirectHTML5(struct MHD_Connection *connection, AFB_session *session, const char* url) {
- int fd;
- int ret;
struct MHD_Response *response;
AFB_staticfile staticfile;
// minimal httpd file server for static HTML,JS,CSS,etc...
STATIC int requestFile(struct MHD_Connection *connection, AFB_session *session, const char* url) {
- int fd;
- int ret;
+ int ret, idx;
AFB_staticfile staticfile;
-
+ char *requestdir, *requesturl;
+
+ // default search for file is rootdir base
+ requestdir= session->config->rootdir;
+ requesturl=(char*)url;
+
+ // Check for optional aliases
+ for (idx=0; session->config->aliasdir[idx].url != NULL; idx++) {
+ if (0 == strncmp(url, session->config->aliasdir[idx].url, session->config->aliasdir[idx].len)) {
+ requestdir = session->config->aliasdir[idx].path;
+ requesturl=(char*)&url[session->config->aliasdir[idx].len];
+ break;
+ }
+ }
+
// build full path from rootdir + url
-
-
- strncpy(staticfile.path, session->config->rootdir, sizeof (staticfile.path));
- strncat(staticfile.path, url, sizeof (staticfile.path));
+ strncpy(staticfile.path, requestdir, sizeof (staticfile.path));
+ strncat(staticfile.path, requesturl, sizeof (staticfile.path));
// try to open file and get its size
if (-1 == (staticfile.fd = open(staticfile.path, O_RDONLY))) {
}
// Nothing respond to this request Files, API, Angular Base
- const char *errorstr = "<html><body>Alsa-Json-Gateway Unknown or Not readable file</body></html>";
+ const char *errorstr = "<html><body>AFB-Daemon File Not Find file</body></html>";
response = MHD_create_response_from_buffer(strlen(errorstr), (void*)errorstr, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
return (MHD_YES);
PUBLIC AFB_error httpdStart(AFB_session *session) {
-
+
// compute fixed URL length at startup time
apiUrlLen = strlen (session->config->rootapi);
baseUrlLen= strlen (session->config->rootbase);
+ rootUrlLen= strlen (session->config->rootdir);
- // open libmagic cache
- // initLibMagic (session);
+ // Initialise Client Session Hash Table
+ ctxStoreInit (CTX_NBCLIENTS);
+
+ //TBD open libmagic cache [fail to pass EFENCE check (allocating 0 bytes)]
+ //initLibMagic (session);
if (verbose) {
}
session->httpd = (void*) MHD_start_daemon(
- MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, // use request and not threads
- session->config->httpdPort, // port
+ MHD_USE_EPOLL_LINUX_ONLY
+ | MHD_USE_TCP_FASTOPEN
+ | MHD_USE_DEBUG
+ ,
+ (uint16_t)session->config->httpdPort, // port
&newClient, NULL, // Tcp Accept call back + extra attribute
&newRequest, session, // Http Request Call back + extra attribute
MHD_OPTION_NOTIFY_COMPLETED, &endRequest, NULL,
- MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15, MHD_OPTION_END); // 15s + options-end
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15, // 15 seconds
+ MHD_OPTION_END); // options-end
// TBD: MHD_OPTION_SOCK_ADDR
if (session->httpd == NULL) {
// infinite loop
PUBLIC AFB_error httpdLoop(AFB_session *session) {
- static int count = 0;
+ 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);
+ if (info == NULL) {
+ printf("Error: httpLoop no pollfd");
+ goto error;
+ }
+ pfd.fd = info->listen_fd;
+ pfd.events = POLLIN;
if (verbose) fprintf(stderr, "AFB:notice entering httpd waiting loop\n");
- if (session->foreground) {
-
- while (TRUE) {
- fprintf(stderr, "AFB:notice Use Ctrl-C to quit\n");
- (void) getc(stdin);
- }
- } else {
- while (TRUE) {
- sleep(3600);
- if (verbose) fprintf(stderr, "AFB:notice httpd alive [%d]\n", count++);
- }
+ while (TRUE) {
+ if (verbose) fprintf(stderr, "AFB:notice httpd alive [%d]\n", count++);
+ poll(&pfd, 1, 15000); // 15 seconds (as above timeout when starting)
+ MHD_run(session->httpd);
}
+error:
// should never return from here
return AFB_FATAL;
}