|
@@ -826,8 +826,8 @@ struct mg_connection {
|
|
SSL *ssl; /* SSL descriptor */
|
|
SSL *ssl; /* SSL descriptor */
|
|
SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
|
|
SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
|
|
struct socket client; /* Connected client */
|
|
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 num_bytes_sent; /* Total bytes sent to client */
|
|
int64_t content_len; /* Content-Length header value */
|
|
int64_t content_len; /* Content-Length header value */
|
|
int64_t consumed_content; /* How many bytes of content have been read */
|
|
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)
|
|
static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
|
|
{
|
|
{
|
|
int nread;
|
|
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
|
|
#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
|
|
#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;
|
|
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) &&
|
|
while ((conn->ctx->stop_flag == 0) &&
|
|
(*nread < bufsiz) &&
|
|
(*nread < bufsiz) &&
|
|
(request_len == 0) &&
|
|
(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)
|
|
((n = pull(fp, conn, buf + *nread, bufsiz - *nread)) > 0)
|
|
) {
|
|
) {
|
|
*nread += n;
|
|
*nread += n;
|
|
@@ -6624,7 +6644,7 @@ static void log_access(const struct mg_connection *conn)
|
|
if (fp == NULL && conn->ctx->callbacks.log_message == NULL)
|
|
if (fp == NULL && conn->ctx->callbacks.log_message == NULL)
|
|
return;
|
|
return;
|
|
|
|
|
|
- tm = localtime(&conn->birth_time);
|
|
|
|
|
|
+ tm = localtime(&conn->conn_birth_time);
|
|
if (tm != NULL) {
|
|
if (tm != NULL) {
|
|
strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
|
|
strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
|
|
} else {
|
|
} else {
|
|
@@ -7178,8 +7198,8 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *
|
|
conn->content_len = 0;
|
|
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;
|
|
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
|
|
signal sq_empty condvar to wake up the master waiting in
|
|
produce_socket() */
|
|
produce_socket() */
|
|
while (consume_socket(ctx, &conn->client)) {
|
|
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,
|
|
/* Fill in IP, port info early so even if SSL setup below fails,
|
|
error handler would have the corresponding info.
|
|
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,
|
|
/* Set socket timeout to the given value, but not more than 10 seconds,
|
|
so the server can exit after 10 seconds if required. */
|
|
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. */
|
|
For values like 24 s a socket timeout of 8 or 12 s would be better. */
|
|
if ((timeout>0) && (timeout<10000)) {
|
|
if ((timeout>0) && (timeout<10000)) {
|
|
set_sock_timeout(so.sock, timeout);
|
|
set_sock_timeout(so.sock, timeout);
|