commit 8566c32da814effb344349f65b4b6b9b9b00bb49
parent c9d4f70298eba78795adc299f880a9b15ac95ee6
Author: Joris Vink <joris@coders.se>
Date: Mon, 9 Sep 2013 11:24:15 +0200
Properly send WINDOW_UPDATE messages to the client when our window is full.
Fixes uploads > 64kb when using SPDY
Diffstat:
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/includes/spdy.h b/includes/spdy.h
@@ -52,7 +52,8 @@ struct spdy_stream {
u_int32_t stream_id;
u_int8_t flags;
u_int8_t prio;
- int32_t wsize;
+ int32_t recv_wsize;
+ int32_t send_wsize;
void *httpreq;
struct spdy_header_block *hblock;
diff --git a/src/spdy.c b/src/spdy.c
@@ -37,6 +37,7 @@ static int spdy_zlib_deflate(struct connection *, u_int8_t *,
size_t, u_int8_t **, u_int32_t *);
u_int64_t spdy_idle_time = 120000;
+int32_t spdy_recv_wsize = 65536;
int
spdy_frame_recv(struct netbuf *nb)
@@ -130,7 +131,7 @@ spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags,
u_int32_t len, struct spdy_stream *s, u_int32_t misc)
{
struct netbuf *nnb;
- u_int8_t nb[12];
+ u_int8_t nb[16];
u_int32_t length;
kore_debug("spdy_frame_send(%p, %d, %d, %d, %p, %d)",
@@ -165,6 +166,16 @@ spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags,
nb[4] = flags;
length = 8;
break;
+ case SPDY_CTRL_FRAME_WINDOW:
+ net_write16(&nb[0], 3);
+ nb[0] |= (1 << 7);
+ net_write16(&nb[2], type);
+ net_write32(&nb[4], len);
+ nb[4] = flags;
+ net_write32(&nb[8], s->stream_id);
+ net_write32(&nb[12], misc);
+ length = 16;
+ break;
case SPDY_DATA_FRAME:
net_write32(&nb[0], s->stream_id);
nb[0] &= ~(1 << 7);
@@ -399,7 +410,8 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
s->httpreq = NULL;
s->prio = syn.prio;
s->flags = ctrl.flags;
- s->wsize = c->wsize_initial;
+ s->recv_wsize = spdy_recv_wsize;
+ s->send_wsize = c->wsize_initial;
s->stream_id = syn.stream_id;
s->hblock = spdy_header_block_create(SPDY_HBLOCK_DELAYED_ALLOC);
@@ -564,15 +576,15 @@ spdy_ctrl_frame_window(struct netbuf *nb)
}
kore_debug("SPDY_WINDOW_UPDATE: %d:%d", stream_id, window_size);
- s->wsize += window_size;
- if (s->wsize > 0 && c->flags & CONN_WRITE_BLOCK) {
+ s->send_wsize += window_size;
+ if (s->send_wsize > 0 && c->flags & CONN_WRITE_BLOCK) {
c->flags &= ~CONN_WRITE_BLOCK;
c->flags |= CONN_WRITE_POSSIBLE;
kore_connection_stop_idletimer(c);
c->idle_timer.length = spdy_idle_time;
- kore_debug("can now send again (%d wsize)", s->wsize);
+ kore_debug("can now send again (%d wsize)", s->send_wsize);
return (net_send_flush(c));
}
@@ -616,6 +628,14 @@ spdy_data_frame_recv(struct netbuf *nb)
req->flags |= HTTP_REQUEST_COMPLETE;
}
+ s->recv_wsize -= data.length;
+ if (s->recv_wsize < (spdy_recv_wsize / 2)) {
+ spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW,
+ 0, 8, s, spdy_recv_wsize - s->recv_wsize);
+
+ s->recv_wsize += (spdy_recv_wsize - s->recv_wsize);
+ }
+
return (KORE_RESULT_OK);
}
@@ -667,11 +687,11 @@ spdy_goaway_send_done(struct netbuf *nb)
static void
spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
{
- s->wsize -= len;
+ s->send_wsize -= len;
kore_debug("spdy_update_wsize(): stream %d, window size %d",
- s->stream_id, s->wsize);
+ s->stream_id, s->send_wsize);
- if (s->wsize <= 0) {
+ if (s->send_wsize <= 0) {
kore_debug("window size <= 0 for stream %d", s->stream_id);
c->flags &= ~CONN_WRITE_POSSIBLE;
c->flags |= CONN_WRITE_BLOCK;