* Inspect the "Connection:" request header field and act accordingly.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sat, 26 Oct 2019 18:44:13 +0000 (20:44 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sat, 26 Oct 2019 18:44:13 +0000 (20:44 +0200)
* Improved request handling and header parsing.

telehttpd.c

index a219c8433ae53f9f875d2ba0116500152432863b..ec0cacdda4bb64b85de81ed04cb726ddec17a1fe 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdbool.h>
 #include <inttypes.h>
 #include <string.h>
+#include <strings.h>
 #include <errno.h>
 #include <signal.h>
 
@@ -98,11 +99,19 @@ static int check_shm( bool retry ) {
     return 0;
 }
 
+static char *strcasestr( const char *haystack, const char *needle ) {
+    size_t l = strlen( needle );
+    for ( char *p = (char *)haystack; *p; ++p )
+        if ( strncasecmp( p, needle, l ) == 0 )
+            return p;
+    return NULL;
+}
+
 static size_t copy_field_val( char *buf, size_t bufsz, const char *needle, const char *haystack, const char *def ) {
     const char *s;
     size_t l;
 
-    if ( NULL != ( s = strstr( haystack, needle ) ) ) {
+    if ( NULL != ( s = strcasestr( haystack, needle ) ) ) {
         const char *e;
         s += strlen( needle );
         if ( NULL != ( e = strstr( s, "\r\n" ) ) )
@@ -138,6 +147,7 @@ static int respond( int sock, const char *req ) {
     char hdr[512];
     char origin[256];
     char host[256];
+    char conn[32];
     enum respond_code {
         r_index,
         r_json,
@@ -152,6 +162,7 @@ static int respond( int sock, const char *req ) {
         code = r_none;
 
     copy_field_val( host, sizeof host, "Host: ", req, cfg.host );
+    copy_field_val( conn, sizeof conn, "Connection: ", req, "keep-alive" );
 
     switch (code) {
     case r_json: {
@@ -170,11 +181,12 @@ static int respond( int sock, const char *req ) {
                 "Host: %s\r\n"
                 "Access-Control-Allow-Origin: %s\r\n"
                 "Content-type: text/json\r\n"
-                "Connection: keep-alive\r\n"
+                "Connection: %s\r\n"
                 "Content-Length: %zu\r\n"
                 "\r\n",
                 host,
                 origin,
+                conn,
                 jsz
             );
         if ( 0 < n && (size_t)n < sizeof hdr && n == sockwrite( sock, hdr, n ) )
@@ -189,16 +201,17 @@ static int respond( int sock, const char *req ) {
             goto SEND_404;
         if ( 0 > fstat(fi, &st) ) {
             close( fi );
-            goto SEND_404;
+            goto SEND_500;
         }
         n = snprintf( hdr, sizeof hdr,
                 "HTTP/1.1 200 OK\r\n"
                 "Host: %s\r\n"
                 "Content-type: text/html\r\n"
-                "Connection: keep-alive\r\n"
+                "Connection: %s\r\n"
                 "Content-Length: %jd\r\n"
                 "\r\n",
                 host,
+                conn,
                 (intmax_t)st.st_size
             );
         if ( 0 < n && (size_t)n < sizeof hdr && n == sockwrite( sock, hdr, n ) ) {
@@ -236,11 +249,14 @@ static int respond( int sock, const char *req ) {
             sockwrite( sock, hdr, n );
         break;
     }
+    if ( 0 < ret && 0 != strcasecmp( conn, "keep-alive" ) )
+        ret = 0;
     return ret;
 }
 
 static int rcv_request(int sock, char *buf, size_t size, int timeout) {
     int res = -1;
+    char junk, *eohdr;
     size_t total = 0;
     ssize_t bread = 0;
     --size;
@@ -259,11 +275,16 @@ static int rcv_request(int sock, char *buf, size_t size, int timeout) {
             break;
         }
         total += bread;
-        timeout = 5;
+        timeout = 1;
     }
+    while ( 1 == read_tm( sock, &junk, 1, 0 ) )
+        ;
     buf[total] = 0;
-    if ( strstr( buf, "\r\n\r\n" ) )
+    eohdr = strstr( buf, "\r\n\r\n" );
+    if ( NULL != eohdr ) {
+        eohdr[4] = '\0';
         res = 0;
+    }
     return res;
 }
 
@@ -275,7 +296,7 @@ static void *handle_conn( void *p ) {
     DPRINT( "sock: %d\n", td->sock );
     while ( 0 == rcv_request(td->sock, req, sizeof req, 5000) ) {
         DPRINT( "request:\n%s", req);
-        if ( 0 > respond( td->sock, req ) )
+        if ( 0 >= respond( td->sock, req ) )
             break;
     }
     net_close( td->sock );