Implement some great SPDY improvements.

* Bump spdy announcement to the correct draft version
* When receiving a RST, clean out the netbuf chain of that stream
This commit is contained in:
Joris Vink 2014-08-07 10:22:54 +02:00
parent 966ed3d20d
commit e3ae1b4e2d
4 changed files with 47 additions and 20 deletions

View File

@ -74,6 +74,7 @@ extern int daemon(int, int);
#define NETBUF_CALL_CB_ALWAYS 0x01
#define NETBUF_FORCE_REMOVE 0x02
#define NETBUF_MUST_RESEND 0x04
#define X509_GET_CN(c, o, l) \
X509_NAME_get_text_by_NID(X509_get_subject_name(c), \
@ -171,8 +172,8 @@ struct connection {
z_stream z_deflate;
u_int32_t wsize_initial;
TAILQ_HEAD(, netbuf) send_queue;
TAILQ_HEAD(, netbuf) recv_queue;
struct netbuf_head send_queue;
struct netbuf_head recv_queue;
u_int32_t client_stream_id;
TAILQ_HEAD(, spdy_stream) spdy_streams;
@ -445,6 +446,7 @@ int net_recv(struct connection *);
int net_send(struct connection *);
int net_send_flush(struct connection *);
int net_recv_flush(struct connection *);
void net_remove_netbuf(struct netbuf_head *, struct netbuf *);
void net_recv_queue(struct connection *, size_t, int,
struct netbuf **, int (*cb)(struct netbuf *));
int net_recv_expand(struct connection *c, struct netbuf *, size_t,

View File

@ -66,7 +66,7 @@ struct spdy_stream {
extern const unsigned char SPDY_dictionary_txt[];
#define KORE_SSL_PROTO_STRING "\x06spdy/3\x08http/1.1"
#define KORE_SSL_PROTO_STRING "\x08spdy/3.2\x08http/1.1"
#define SPDY_CONTROL_FRAME(x) ((x & (1 << 31)))
#define SPDY_FRAME_SIZE 8

View File

@ -136,6 +136,7 @@ net_send(struct connection *c)
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
nb->flags |= NETBUF_MUST_RESEND;
c->flags &= ~CONN_WRITE_POSSIBLE;
return (KORE_RESULT_OK);
default:
@ -158,20 +159,17 @@ net_send(struct connection *c)
}
}
#endif
kore_debug("net_send(%d/%d bytes), progress with %d",
nb->s_off, nb->b_len, r);
kore_debug("net_send(%p/%d/%d bytes), progress with %d",
nb, nb->s_off, nb->b_len, r);
nb->s_off += (size_t)r;
nb->flags &= ~NETBUF_MUST_RESEND;
if (nb->stream != NULL)
spdy_update_wsize(c, nb->stream, r);
}
if (nb->s_off == nb->b_len) {
TAILQ_REMOVE(&(c->send_queue), nb, list);
kore_mem_free(nb->buf);
kore_pool_put(&nb_pool, nb);
}
if (nb->s_off == nb->b_len)
net_remove_netbuf(&(c->send_queue), nb);
}
return (KORE_RESULT_OK);
@ -245,10 +243,7 @@ net_recv(struct connection *c)
r = nb->cb(nb);
if (nb->s_off == nb->b_len ||
(nb->flags & NETBUF_FORCE_REMOVE)) {
TAILQ_REMOVE(&(c->recv_queue), nb, list);
kore_mem_free(nb->buf);
kore_pool_put(&nb_pool, nb);
net_remove_netbuf(&(c->recv_queue), nb);
}
if (r != KORE_RESULT_OK)
@ -273,6 +268,20 @@ net_recv_flush(struct connection *c)
return (KORE_RESULT_OK);
}
void
net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb)
{
nb->stream = NULL;
if (nb->flags & NETBUF_MUST_RESEND) {
kore_debug("retaining %p (MUST_RESEND)", nb);
return;
}
TAILQ_REMOVE(list, nb, list);
kore_mem_free(nb->buf);
kore_pool_put(&nb_pool, nb);
}
u_int16_t
net_read16(u_int8_t *b)
{

View File

@ -20,6 +20,9 @@
#include "kore.h"
#include "http.h"
#define SPDY_KEEP_NETBUFS 0
#define SPDY_REMOVE_NETBUFS 1
static int spdy_ctrl_frame_syn_stream(struct netbuf *);
static int spdy_ctrl_frame_rst_stream(struct netbuf *);
static int spdy_ctrl_frame_settings(struct netbuf *);
@ -28,7 +31,7 @@ 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 *);
struct spdy_stream *, int);
static int spdy_zlib_inflate(struct connection *, u_int8_t *,
size_t, u_int8_t **, u_int32_t *);
static int spdy_zlib_deflate(struct connection *, u_int8_t *,
@ -365,7 +368,7 @@ spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
if (s->send_size == 0) {
if (s->flags & (SPDY_KORE_FIN | FLAG_FIN)) {
spdy_stream_close(c, s);
spdy_stream_close(c, s, SPDY_KEEP_NETBUFS);
return;
}
@ -522,10 +525,13 @@ static int
spdy_ctrl_frame_rst_stream(struct netbuf *nb)
{
struct spdy_stream *s;
u_int32_t stream_id;
u_int32_t stream_id, status;
struct connection *c = (struct connection *)nb->owner;
stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE);
status = net_read32(nb->buf + SPDY_FRAME_SIZE + sizeof(u_int32_t));
printf("RST STATUS IS %d\n", status);
if ((stream_id % 2) == 0) {
kore_debug("received RST for non-client stream %u", stream_id);
return (KORE_RESULT_ERROR);
@ -536,7 +542,7 @@ spdy_ctrl_frame_rst_stream(struct netbuf *nb)
return (KORE_RESULT_ERROR);
}
spdy_stream_close(c, s);
spdy_stream_close(c, s, SPDY_REMOVE_NETBUFS);
return (KORE_RESULT_OK);
}
@ -735,12 +741,21 @@ spdy_data_frame_recv(struct netbuf *nb)
}
static void
spdy_stream_close(struct connection *c, struct spdy_stream *s)
spdy_stream_close(struct connection *c, struct spdy_stream *s, int rb)
{
struct http_request *req;
struct netbuf *nb, *nt;
kore_debug("spdy_stream_close(%p, %p) <%d>", c, s, s->stream_id);
if (rb) {
for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = nt) {
nt = TAILQ_NEXT(nb, list);
if (nb->stream == s)
net_remove_netbuf(&(c->send_queue), nb);
}
}
TAILQ_REMOVE(&(c->spdy_streams), s, list);
if (s->hblock != NULL) {
if (s->hblock->header_block != NULL)
@ -750,6 +765,7 @@ spdy_stream_close(struct connection *c, struct spdy_stream *s)
if (s->httpreq != NULL) {
req = s->httpreq;
req->stream = NULL;
req->flags |= HTTP_REQUEST_DELETE;
}