X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fhttp-svc.c;h=71e0a08f95c4823f4485c359552ebbdb6cb69e83;hb=c2560bd51498fb38e645b60ae638e2e888c74b65;hp=cd488961db1c665f77e30368d8fe164d2310b316;hpb=b55efc33fb8df8b0518570b2584b6da9abb3221b;p=src%2Fapp-framework-binder.git diff --git a/src/http-svc.c b/src/http-svc.c index cd488961..71e0a08f 100644 --- a/src/http-svc.c +++ b/src/http-svc.c @@ -29,21 +29,18 @@ POST https://www.gnu.org/software/libmicrohttpd/manual/html_node/microhttpd_002dpost.html#microhttpd_002dpost */ +#define _GNU_SOURCE #include +#include #include #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) { @@ -69,46 +66,31 @@ 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 = "Alsa-Json-Gateway Invalid file type"; - 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 @@ -116,6 +98,7 @@ STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, co // 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); @@ -127,8 +110,16 @@ STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, co 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 = "Application Framework Binder Invalid file type"; + 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 @@ -150,7 +141,7 @@ STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, co 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); @@ -171,8 +162,6 @@ abortRequest: // 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; @@ -190,15 +179,26 @@ STATIC int redirectHTML5(struct MHD_Connection *connection, AFB_session *session // 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))) { @@ -242,7 +242,7 @@ STATIC int newRequest(void *cls, } // Nothing respond to this request Files, API, Angular Base - const char *errorstr = "Alsa-Json-Gateway Unknown or Not readable file"; + const char *errorstr = "AFB-Daemon File Not Find file"; 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); @@ -255,13 +255,17 @@ STATIC int newClient(void *cls, const struct sockaddr * addr, socklen_t addrlen) 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) { @@ -270,12 +274,16 @@ PUBLIC AFB_error httpdStart(AFB_session *session) { } 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) { @@ -287,22 +295,27 @@ PUBLIC AFB_error httpdStart(AFB_session *session) { // 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; }