bel 10 лет назад
Родитель
Сommit
86ac7a404f
1 измененных файлов с 39 добавлено и 19 удалено
  1. 39 19
      src/civetweb.c

+ 39 - 19
src/civetweb.c

@@ -826,8 +826,8 @@ struct mg_connection {
     SSL *ssl;                       /* SSL descriptor */
     SSL_CTX *client_ssl_ctx;        /* SSL context for client connections */
     struct socket client;           /* Connected client */
-    time_t birth_time;              /* Time (wall clock) when connection was established */
-    struct timespec req_begin;      /* Time (since system start) when the request was received */
+    time_t conn_birth_time;         /* Time (wall clock) when connection was established */
+    struct timespec req_time;       /* Time (since system start) when the request was received */
     int64_t num_bytes_sent;         /* Total bytes sent to client */
     int64_t content_len;            /* Content-Length header value */
     int64_t consumed_content;       /* How many bytes of content have been read */
@@ -2447,20 +2447,40 @@ static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t le
 static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
 {
     int nread;
+    double timeout = -1;
+    struct timespec start, now;
 
-    if (fp != NULL) {
-        /* Use read() instead of fread(), because if we're reading from the
-           CGI pipe, fread() may block until IO buffer is filled up. We cannot
-           afford to block and must pass all read bytes immediately to the
-           client. */
-        nread = read(fileno(fp), buf, (size_t) len);
+    if (conn->ctx->config[REQUEST_TIMEOUT]) {
+        timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
+    }
+    if (timeout>0) {
+        clock_gettime(CLOCK_MONOTONIC, &start);
+    }
+
+    do {
+        if (fp != NULL) {
+            /* Use read() instead of fread(), because if we're reading from the
+            CGI pipe, fread() may block until IO buffer is filled up. We cannot
+            afford to block and must pass all read bytes immediately to the
+            client. */
+            nread = read(fileno(fp), buf, (size_t) len);
 #ifndef NO_SSL
-    } else if (conn->ssl != NULL) {
-        nread = SSL_read(conn->ssl, buf, len);
+        } else if (conn->ssl != NULL) {
+            nread = SSL_read(conn->ssl, buf, len);
 #endif
-    } else {
-        nread = recv(conn->client.sock, buf, (size_t) len, 0);
-    }
+        } else {
+            nread = recv(conn->client.sock, buf, (size_t) len, 0);
+        }
+        if (conn->ctx->stop_flag) {
+            return -1;
+        }
+        if (nread >= 0) {
+            return nread;
+        }
+        if (timeout>0) {
+            clock_gettime(CLOCK_MONOTONIC, &now);
+        }
+    } while ((timeout<=0) || (difftime(now.tv_sec,start.tv_sec)<=timeout));
 
     return conn->ctx->stop_flag ? -1 : nread;
 }
@@ -4314,7 +4334,7 @@ static int read_request(FILE *fp, struct mg_connection *conn,
     while ((conn->ctx->stop_flag == 0) &&
            (*nread < bufsiz) &&
            (request_len == 0) &&
-           ((difftime(last_action_time.tv_sec, conn->birth_time) <= request_timout) || (request_timout < 0)) &&
+           ((difftime(last_action_time.tv_sec, conn->req_time.tv_sec) <= request_timout) || (request_timout < 0)) &&
            ((n = pull(fp, conn, buf + *nread, bufsiz - *nread)) > 0)
           ) {
         *nread += n;
@@ -6624,7 +6644,7 @@ static void log_access(const struct mg_connection *conn)
     if (fp == NULL && conn->ctx->callbacks.log_message == NULL)
         return;
 
-    tm = localtime(&conn->birth_time);
+    tm = localtime(&conn->conn_birth_time);
     if (tm != NULL) {
         strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
     } else {
@@ -7178,8 +7198,8 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *
             conn->content_len = 0;
         }
 
-        /* Here we do not set the socket_birth time but the request begin */
-        clock_gettime(CLOCK_MONOTONIC, &(conn->req_begin));
+        /* Set the time the request was received. This value should be used for timeouts. */
+        clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
     }
     return 1;
 }
@@ -7471,7 +7491,7 @@ static void *worker_thread_run(void *thread_func_param)
            signal sq_empty condvar to wake up the master waiting in
            produce_socket() */
         while (consume_socket(ctx, &conn->client)) {
-            conn->birth_time = time(NULL);
+            conn->conn_birth_time = time(NULL);
 
             /* Fill in IP, port info early so even if SSL setup below fails,
                error handler would have the corresponding info.
@@ -7600,7 +7620,7 @@ static void accept_new_connection(const struct socket *listener,
 
         /* Set socket timeout to the given value, but not more than 10 seconds,
            so the server can exit after 10 seconds if required. */
-        /* TODO: Currently values > 10 s are round up to the next 10 s. 
+        /* TODO: Currently values > 10 s are round up to the next 10 s.
                  For values like 24 s a socket timeout of 8 or 12 s would be better. */
         if ((timeout>0) && (timeout<10000)) {
             set_sock_timeout(so.sock, timeout);