Add http_[header|body]_timeout.

If the HTTP request headers or the HTTP body have not arrived before
these timeouts expire, Kore will send a 408 back to the client.
This commit is contained in:
Joris Vink 2019-04-11 20:51:49 +02:00
parent a191445f76
commit aa49e181b6
6 changed files with 80 additions and 5 deletions

View File

@ -108,10 +108,17 @@ workers 4
# HTTP specific settings.
# http_header_max Maximum size of HTTP headers (in bytes).
#
# http_header_timeout Timeout in seconds for receiving the
# HTTP headers before the connection is closed.
#
# http_body_max Maximum size of an HTTP body (in bytes).
# If set to 0 disallows requests with a body
# all together.
#
# http_body_timeout Timeout in seconds for receiving the
# HTTP body in full before the connection
# is closed with an 408.
#
# http_body_disk_offload Number of bytes after which Kore will use
# a temporary file to hold the HTTP body
# instead of holding it in memory. If set to
@ -136,7 +143,9 @@ workers 4
# spend inside the HTTP processing loop.
#
#http_header_max 4096
#http_header_timeout 10
#http_body_max 1024000
#http_body_timeout 60
#http_keepalive_time 0
#http_hsts_enable 31536000
#http_request_limit 1000

View File

@ -51,6 +51,8 @@ extern "C" {
#define HTTP_BODY_DISK_OFFLOAD 0
#define HTTP_BODY_PATH_MAX 256
#define HTTP_BOUNDARY_MAX 80
#define HTTP_HEADER_TIMEOUT 10
#define HTTP_BODY_TIMEOUT 60
#define HTTP_ARG_TYPE_RAW 0
#define HTTP_ARG_TYPE_BYTE 1
@ -279,7 +281,9 @@ struct http_media_type {
};
extern size_t http_body_max;
extern u_int16_t http_body_timeout;
extern u_int16_t http_header_max;
extern u_int16_t http_header_timeout;
extern u_int32_t http_request_ms;
extern u_int64_t http_hsts_enable;
extern u_int16_t http_keepalive_time;
@ -304,6 +308,7 @@ void http_request_wakeup(struct http_request *);
void http_process_request(struct http_request *);
int http_body_rewind(struct http_request *);
int http_media_register(const char *, const char *);
int http_check_timeout(struct connection *, u_int64_t);
ssize_t http_body_read(struct http_request *, void *, size_t);
int http_body_digest(struct http_request *, char *, size_t);
void http_response(struct http_request *, int, const void *, size_t);

View File

@ -243,6 +243,8 @@ struct connection {
struct netbuf *rnb;
#if !defined(KORE_NO_HTTP)
u_int64_t http_start;
u_int64_t http_timeout;
struct kore_runtime_call *ws_connect;
struct kore_runtime_call *ws_message;
struct kore_runtime_call *ws_disconnect;

View File

@ -91,7 +91,9 @@ static int configure_static_handler(char *);
static int configure_dynamic_handler(char *);
static int configure_accesslog(char *);
static int configure_http_header_max(char *);
static int configure_http_header_timeout(char *);
static int configure_http_body_max(char *);
static int configure_http_body_timeout(char *);
static int configure_filemap_ext(char *);
static int configure_filemap_index(char *);
static int configure_http_media_type(char *);
@ -176,7 +178,9 @@ static struct {
{ "restrict", configure_restrict },
{ "http_media_type", configure_http_media_type },
{ "http_header_max", configure_http_header_max },
{ "http_header_timeout", configure_http_header_timeout },
{ "http_body_max", configure_http_body_max },
{ "http_body_timeout", configure_http_body_timeout },
{ "http_hsts_enable", configure_http_hsts_enable },
{ "http_keepalive_time", configure_http_keepalive_time },
{ "http_request_ms", configure_http_request_ms },
@ -872,6 +876,20 @@ configure_http_header_max(char *option)
return (KORE_RESULT_OK);
}
static int
configure_http_header_timeout(char *option)
{
int err;
http_header_timeout = kore_strtonum(option, 10, 1, 65535, &err);
if (err != KORE_RESULT_OK) {
printf("bad http_header_timeout value: %s\n", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_body_max(char *option)
{
@ -886,6 +904,20 @@ configure_http_body_max(char *option)
return (KORE_RESULT_OK);
}
static int
configure_http_body_timeout(char *option)
{
int err;
http_body_timeout = kore_strtonum(option, 10, 1, 65535, &err);
if (err != KORE_RESULT_OK) {
printf("bad http_body_timeout value: %s\n", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_body_disk_offload(char *option)
{

View File

@ -84,6 +84,8 @@ kore_connection_new(void *owner)
c->ws_connect = NULL;
c->ws_message = NULL;
c->ws_disconnect = NULL;
c->http_start = kore_time_ms();
c->http_timeout = http_header_timeout * 1000;
TAILQ_INIT(&(c->http_requests));
#endif
@ -182,13 +184,14 @@ kore_connection_check_timeout(u_int64_t now)
next = TAILQ_NEXT(c, list);
if (c->proto == CONN_PROTO_MSG)
continue;
if (!(c->flags & CONN_IDLE_TIMER_ACT))
continue;
#if !defined(KORE_NO_HTTP)
if (!http_check_timeout(c, now))
continue;
if (!TAILQ_EMPTY(&c->http_requests))
continue;
#endif
kore_connection_check_idletimer(now, c);
if (c->flags & CONN_IDLE_TIMER_ACT)
kore_connection_check_idletimer(now, c);
}
}
@ -418,7 +421,7 @@ kore_connection_check_idletimer(u_int64_t now, struct connection *c)
d = 0;
if (d >= c->idle_timer.length) {
kore_debug("%p idle for %" PRIu64 " ms, expiring", c, d);
printf("%p idle for %" PRIu64 " ms, expiring\n", (void *)c, d);
kore_connection_disconnect(c);
}
}

View File

@ -150,13 +150,16 @@ static struct kore_pool http_body_path;
u_int32_t http_request_count = 0;
u_int32_t http_request_ms = HTTP_REQUEST_MS;
u_int16_t http_body_timeout = HTTP_BODY_TIMEOUT;
u_int32_t http_request_limit = HTTP_REQUEST_LIMIT;
u_int64_t http_hsts_enable = HTTP_HSTS_ENABLE;
u_int16_t http_header_max = HTTP_HEADER_MAX_LEN;
u_int16_t http_keepalive_time = HTTP_KEEPALIVE_TIME;
u_int16_t http_header_timeout = HTTP_HEADER_TIMEOUT;
size_t http_body_max = HTTP_BODY_MAX_LEN;
u_int64_t http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
char *http_body_disk_path = HTTP_BODY_DISK_PATH;
u_int64_t http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
void
http_parent_init(void)
@ -233,6 +236,21 @@ http_server_version(const char *version)
http_version_len = l;
}
int
http_check_timeout(struct connection *c, u_int64_t now)
{
if (c->http_timeout == 0)
return (KORE_RESULT_OK);
if ((now - c->http_start) >= c->http_timeout) {
http_error_response(c, 408);
kore_connection_disconnect(c);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
void
http_request_sleep(struct http_request *req)
{
@ -834,7 +852,9 @@ http_header_recv(struct netbuf *nb)
c->rnb->extra = req;
http_request_sleep(req);
req->content_length = bytes_left;
c->http_timeout = http_body_timeout * 1000;
} else {
c->http_timeout = 0;
req->flags |= HTTP_REQUEST_COMPLETE;
req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
SHA256_Final(req->http_body_digest, &req->hashctx);
@ -844,6 +864,8 @@ http_header_recv(struct netbuf *nb)
return (KORE_RESULT_OK);
}
}
} else {
c->http_timeout = 0;
}
return (KORE_RESULT_OK);
@ -1919,6 +1941,8 @@ http_response_normal(struct http_request *req, struct connection *c,
net_send_queue(c, d, len);
if (!(c->flags & CONN_CLOSE_EMPTY)) {
c->http_start = kore_time_ms();
c->http_timeout = http_header_timeout * 1000;
net_recv_reset(c, http_header_max, http_header_recv);
(void)net_recv_flush(c);
}