]> git.seodisparate.com - c_simple_http/commitdiff
Add timeout to incoming connections
authorStephen Seo <seo.disparate@gmail.com>
Sun, 3 Nov 2024 09:11:50 +0000 (18:11 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 3 Nov 2024 09:11:50 +0000 (18:11 +0900)
src/constants.h
src/main.c

index b8d1ebf7045f1275ed97773c0ac0c74b7aa89a7e..8b09a0108b994663fec58c25b34707fac69bb3fc 100644 (file)
@@ -18,6 +18,8 @@
 #define SEODISPARATE_COM_C_SIMPLE_HTTP_CONSTANTS_H_
 
 #define C_SIMPLE_HTTP_SLEEP_NANOS 1000000
+#define C_SIMPLE_HTTP_NONBLOCK_SLEEP_NANOS 1000000
+#define C_SIMPLE_HTTP_MAX_NONBLOCK_WAIT_NANOS 3500000000
 #define C_SIMPLE_HTTP_TRY_CONFIG_RELOAD_NANOS 4000000000
 #define C_SIMPLE_HTTP_TRY_CONFIG_RELOAD_TICKS \
     (C_SIMPLE_HTTP_TRY_CONFIG_RELOAD_NANOS / C_SIMPLE_HTTP_SLEEP_NANOS)
index edeb6f01f2cb89beff1ba275ca6defcbf437d01a..2aa14655226e6fe730a3a84539dbf5ad0e954c7b 100644 (file)
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <sys/inotify.h>
 #include <linux/limits.h>
+#include <fcntl.h>
 
 // Third party includes.
 #include <SimpleArchiver/src/helpers.h>
@@ -352,14 +353,49 @@ int main(int argc, char **argv) {
         printf("Peer connected.\n");
       }
       int connection_fd = ret;
-      read_ret = read(connection_fd, recv_buf, C_SIMPLE_HTTP_RECV_BUF_SIZE);
-      if (read_ret < 0) {
+
+      // Set non-blocking.
+      ret = fcntl(connection_fd, F_SETFL, O_NONBLOCK);
+      if (ret < 0) {
+        fprintf(stderr, "ERROR Failed to set non-blocking on connection fd!\n");
         close(connection_fd);
-        fprintf(
-          stderr,
-          "WARNING Failed to read from new connection, closing...\n");
         continue;
       }
+
+      {
+        const struct timespec non_block_wait_time =
+          (struct timespec){.tv_sec = 0,
+                            .tv_nsec = C_SIMPLE_HTTP_NONBLOCK_SLEEP_NANOS};
+        uint64_t nanoseconds_waited = 0;
+        int_fast8_t continue_after = 0;
+        while (1) {
+          read_ret = read(connection_fd, recv_buf, C_SIMPLE_HTTP_RECV_BUF_SIZE);
+          if (read_ret < 0) {
+            if (errno == EAGAIN || errno == EWOULDBLOCK) {
+              nanosleep(&non_block_wait_time, NULL);
+              nanoseconds_waited += (uint64_t)non_block_wait_time.tv_nsec;
+              if (nanoseconds_waited >= C_SIMPLE_HTTP_MAX_NONBLOCK_WAIT_NANOS) {
+                fprintf(stderr, "WARNING Connection timed out!\n");
+                close(connection_fd);
+                continue_after = 1;
+                break;
+              }
+              continue;
+            }
+            close(connection_fd);
+            fprintf(
+              stderr,
+              "WARNING Failed to read from new connection, closing...\n");
+            continue_after = 1;
+            break;
+          } else {
+            break;
+          }
+        }
+        if (continue_after) {
+          continue;
+        }
+      }
 #ifndef NDEBUG
       // DEBUG print received buf.
       for (uint32_t idx = 0;