kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit e7feaaba76142d86895288a09ed81bf02e552681
parent 4ed4f76e44a39cb4cbd7803364f9d9f9c8cb4e4d
Author: Joris Vink <joris@coders.se>
Date:   Thu,  2 May 2013 17:30:06 +0200

properly close a spdy stream once both sides have FLAG_FIN.

Diffstat:
includes/kore.h | 2+-
src/http.c | 6+++---
src/spdy.c | 42+++++++++++++++++++++++++++++++++---------
3 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -155,7 +155,7 @@ int spdy_stream_get_header(struct spdy_header_block *, int spdy_frame_recv(struct netbuf *); void spdy_frame_send(struct connection *, u_int16_t, - u_int8_t, u_int32_t, u_int32_t); + u_int8_t, u_int32_t, struct spdy_stream *, u_int32_t); void spdy_header_block_add(struct spdy_header_block *, char *, char *); u_int8_t *spdy_header_block_release(struct connection *, diff --git a/src/http.c b/src/http.c @@ -153,18 +153,18 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len) return (KORE_RESULT_ERROR); spdy_frame_send(req->owner, SPDY_CTRL_FRAME_SYN_REPLY, - 0, hlen, req->stream->stream_id); + 0, hlen, req->stream, 0); net_send_queue(req->owner, htext, hlen, 0, NULL, NULL); free(htext); if (len > 0) { spdy_frame_send(req->owner, SPDY_DATA_FRAME, - 0, len, req->stream->stream_id); + 0, len, req->stream, 0); net_send_queue(req->owner, d, len, 0, NULL, NULL); } spdy_frame_send(req->owner, SPDY_DATA_FRAME, - FLAG_FIN, 0, req->stream->stream_id); + FLAG_FIN, 0, req->stream, 0); } else { buf = kore_buf_create(KORE_BUF_INITIAL); diff --git a/src/spdy.c b/src/spdy.c @@ -42,6 +42,8 @@ static int spdy_ctrl_frame_settings(struct netbuf *); static int spdy_ctrl_frame_ping(struct netbuf *); static int spdy_ctrl_frame_window(struct netbuf *); static int spdy_data_frame_recv(struct netbuf *); +static void spdy_stream_close(struct connection *, + struct spdy_stream *); static int spdy_zlib_inflate(struct connection *, u_int8_t *, size_t, u_int8_t **, u_int32_t *); @@ -129,13 +131,13 @@ spdy_frame_recv(struct netbuf *nb) void spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags, - u_int32_t len, u_int32_t stream_id) + u_int32_t len, struct spdy_stream *s, u_int32_t misc) { u_int8_t nb[12]; u_int32_t length; - kore_log("spdy_frame_send(%p, %d, %d, %d, %d)", c, type, flags, - len, stream_id); + kore_log("spdy_frame_send(%p, %d, %d, %d, %p, %d)", + c, type, flags, len, s, misc); length = 0; memset(nb, 0, sizeof(nb)); @@ -146,17 +148,20 @@ spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags, nb[0] |= (1 << 7); net_write16(&nb[2], type); - if (type != SPDY_CTRL_FRAME_PING) + if (type != SPDY_CTRL_FRAME_PING) { net_write32(&nb[4], len + 4); - else + nb[4] = flags; + net_write32(&nb[8], s->stream_id); + } else { net_write32(&nb[4], len); + nb[4] = flags; + net_write32(&nb[8], misc); + } - nb[4] = flags; - net_write32(&nb[8], stream_id); length = 12; break; case SPDY_DATA_FRAME: - net_write32(&nb[0], stream_id); + net_write32(&nb[0], s->stream_id); nb[0] &= ~(1 << 7); net_write32(&nb[4], len); nb[4] = flags; @@ -165,6 +170,9 @@ spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags, } net_send_queue(c, nb, length, 0, NULL, NULL); + + if ((flags & FLAG_FIN) && (s->flags & FLAG_FIN)) + spdy_stream_close(c, s); } struct spdy_stream * @@ -434,7 +442,7 @@ spdy_ctrl_frame_ping(struct netbuf *nb) return (KORE_RESULT_ERROR); } - spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, id); + spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, NULL, id); return (KORE_RESULT_OK); } @@ -481,6 +489,7 @@ spdy_data_frame_recv(struct netbuf *nb) data.length); if (data.flags & FLAG_FIN) { + s->flags |= FLAG_FIN; req->flags |= HTTP_REQUEST_COMPLETE; kore_log("POST request completed"); } @@ -488,6 +497,21 @@ spdy_data_frame_recv(struct netbuf *nb) return (KORE_RESULT_OK); } +static void +spdy_stream_close(struct connection *c, struct spdy_stream *s) +{ + kore_log("spdy_stream_close(%p, %p) <%d>", c, s, s->stream_id); + + TAILQ_REMOVE(&(c->spdy_streams), s, list); + if (s->hblock != NULL) { + if (s->hblock->header_block != NULL) + free(s->hblock->header_block); + free(s->hblock); + } + + free(s); +} + static int spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen)