- 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.
This commit is contained in:
Joris Vink 2013-07-01 12:08:51 +02:00
parent a2392e645f
commit 0c08b57d3e
5 changed files with 69 additions and 0 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);