commit 0c08b57d3e82c11dafbb4bdaf86629cc2709b027
parent a2392e645f9f9d51ab716e1f0f4d5756a83a4cbc
Author: Joris Vink <joris@coders.se>
Date: Mon, 1 Jul 2013 12:08:51 +0200
- add idle timer for normal connections (ie: !SPDY), max 20 seconds.
- use idle timer to make sure we don't block SPDY connections indefinately
when our window size has reached 0.
Diffstat:
5 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/includes/kore.h b/includes/kore.h
@@ -75,6 +75,9 @@ struct listener {
#define CONN_READ_POSSIBLE 0x01
#define CONN_WRITE_POSSIBLE 0x02
#define CONN_WRITE_BLOCK 0x04
+#define CONN_IDLE_TIMER_ACT 0x10
+
+#define KORE_IDLE_TIMER_MAX 20000
struct connection {
int fd;
@@ -85,6 +88,11 @@ struct connection {
SSL *ssl;
u_int8_t flags;
+ struct {
+ u_int64_t length;
+ u_int64_t start;
+ } idle_timer;
+
u_int8_t inflate_started;
z_stream z_inflate;
u_int8_t deflate_started;
@@ -203,6 +211,9 @@ int kore_connection_nonblock(int);
int kore_connection_handle(struct connection *);
void kore_connection_remove(struct connection *);
void kore_connection_disconnect(struct connection *);
+void kore_connection_start_idletimer(struct connection *);
+void kore_connection_stop_idletimer(struct connection *);
+void kore_connection_check_idletimer(u_int64_t, struct connection *);
int kore_connection_accept(struct listener *, struct connection **);
u_int64_t kore_time_ms(void);
diff --git a/src/connection.c b/src/connection.c
@@ -77,11 +77,15 @@ kore_connection_accept(struct listener *l, struct connection **out)
c->proto = CONN_PROTO_UNKNOWN;
c->state = CONN_STATE_SSL_SHAKE;
c->wsize_initial = SPDY_INIT_WSIZE;
+ c->idle_timer.start = 0;
+ c->idle_timer.length = KORE_IDLE_TIMER_MAX;
TAILQ_INIT(&(c->send_queue));
TAILQ_INIT(&(c->recv_queue));
TAILQ_INIT(&(c->spdy_streams));
+
kore_worker_connection_add(c);
+ kore_connection_start_idletimer(c);
*out = c;
return (KORE_RESULT_OK);
@@ -106,6 +110,9 @@ kore_connection_handle(struct connection *c)
kore_debug("kore_connection_handle(%p)", c);
+ if (c->proto != CONN_PROTO_SPDY)
+ kore_connection_stop_idletimer(c);
+
switch (c->state) {
case CONN_STATE_SSL_SHAKE:
if (c->ssl == NULL) {
@@ -173,6 +180,9 @@ kore_connection_handle(struct connection *c)
break;
}
+ if (c->proto != CONN_PROTO_SPDY)
+ kore_connection_start_idletimer(c);
+
return (KORE_RESULT_OK);
}
@@ -225,6 +235,36 @@ kore_connection_remove(struct connection *c)
kore_mem_free(c);
}
+void
+kore_connection_check_idletimer(u_int64_t now, struct connection *c)
+{
+ u_int64_t d;
+
+ d = now - c->idle_timer.start;
+ if (d >= c->idle_timer.length) {
+ kore_debug("%p idle for %d ms, expiring", c, d);
+ kore_connection_disconnect(c);
+ }
+}
+
+void
+kore_connection_start_idletimer(struct connection *c)
+{
+ kore_debug("kore_connection_start_idletimer(%p)", c);
+
+ c->flags |= CONN_IDLE_TIMER_ACT;
+ c->idle_timer.start = kore_time_ms();
+}
+
+void
+kore_connection_stop_idletimer(struct connection *c)
+{
+ kore_debug("kore_connection_stop_idletimer(%p)", c);
+
+ c->flags &= ~CONN_IDLE_TIMER_ACT;
+ c->idle_timer.start = 0;
+}
+
int
kore_connection_nonblock(int fd)
{
diff --git a/src/http.c b/src/http.c
@@ -259,6 +259,7 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len)
kore_buf_appendf(buf, "HTTP/1.1 %d\r\n", status);
kore_buf_appendf(buf, "Content-length: %d\r\n", len);
kore_buf_appendf(buf, "Connection: keep-alive\r\n");
+ kore_buf_appendf(buf, "Keep-Alive: timeout=20\r\n");
kore_buf_appendf(buf, "Server: %s\r\n", kore_version_string);
TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
diff --git a/src/spdy.c b/src/spdy.c
@@ -520,6 +520,7 @@ spdy_ctrl_frame_window(struct netbuf *nb)
if (s->wsize > 0) {
c->flags &= ~CONN_WRITE_BLOCK;
c->flags |= CONN_WRITE_POSSIBLE;
+ kore_connection_stop_idletimer(c);
kore_debug("can now send again (%d wsize)", s->wsize);
return (net_send_flush(c));
@@ -606,6 +607,7 @@ spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
kore_debug("window size <= 0 for stream %d", s->stream_id);
c->flags &= ~CONN_WRITE_POSSIBLE;
c->flags |= CONN_WRITE_BLOCK;
+ kore_connection_start_idletimer(c);
}
}
diff --git a/src/worker.c b/src/worker.c
@@ -189,6 +189,7 @@ kore_worker_entry(struct kore_worker *kw)
int quit;
char buf[16];
struct connection *c, *cnext;
+ u_int64_t now, idle_check;
worker = kw;
@@ -216,6 +217,7 @@ kore_worker_entry(struct kore_worker *kw)
TAILQ_INIT(&worker_clients);
quit = 0;
+ now = idle_check = 0;
kore_platform_event_init();
kore_accesslog_worker_init();
@@ -244,6 +246,19 @@ kore_worker_entry(struct kore_worker *kw)
http_process();
+ now = kore_time_ms();
+ if ((now - idle_check) >= 10000) {
+ idle_check = now;
+ TAILQ_FOREACH(c, &worker_clients, list) {
+ if (c->proto == CONN_PROTO_SPDY &&
+ !(c->flags & CONN_WRITE_BLOCK))
+ continue;
+ if (!(c->flags & CONN_IDLE_TIMER_ACT))
+ continue;
+ kore_connection_check_idletimer(now, c);
+ }
+ }
+
for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) {
cnext = TAILQ_NEXT(c, list);
TAILQ_REMOVE(&disconnected, c, list);