mirror of https://git.kore.io/kore.git
Add spdy_session_teardown() which can properly teardown a SPDY session.
Use this throughout the spdy code to propagate session errors (if any) occur. At the same time fix BSD's missing CONN_WRITE_BLOCK
This commit is contained in:
parent
777cfda791
commit
f59e94a7b6
|
@ -92,6 +92,7 @@ struct listener {
|
|||
#define CONN_WRITE_POSSIBLE 0x02
|
||||
#define CONN_WRITE_BLOCK 0x04
|
||||
#define CONN_IDLE_TIMER_ACT 0x10
|
||||
#define CONN_READ_BLOCK 0x20
|
||||
|
||||
#define KORE_IDLE_TIMER_MAX 20000
|
||||
|
||||
|
@ -299,6 +300,7 @@ int spdy_stream_get_header(struct spdy_header_block *,
|
|||
char *, char **);
|
||||
|
||||
int spdy_frame_recv(struct netbuf *);
|
||||
void spdy_session_teardown(struct connection *c, u_int8_t);
|
||||
void spdy_frame_send(struct connection *, u_int16_t,
|
||||
u_int8_t, u_int32_t, struct spdy_stream *, u_int32_t);
|
||||
void spdy_header_block_add(struct spdy_header_block *,
|
||||
|
|
|
@ -76,9 +76,15 @@ extern const unsigned char SPDY_dictionary_txt[];
|
|||
#define SPDY_CTRL_FRAME_SYN_REPLY 2
|
||||
#define SPDY_CTRL_FRAME_SETTINGS 4
|
||||
#define SPDY_CTRL_FRAME_PING 6
|
||||
#define SPDY_CTRL_FRAME_GOAWAY 7
|
||||
#define SPDY_CTRL_FRAME_WINDOW 9
|
||||
#define SPDY_DATA_FRAME 99
|
||||
|
||||
/* session error codes */
|
||||
#define SPDY_SESSION_ERROR_OK 0
|
||||
#define SPDY_SESSION_ERROR_PROTOCOL 1
|
||||
#define SPDY_SESSION_ERROR_INTERNAL 2
|
||||
|
||||
/* flags */
|
||||
#define FLAG_FIN 0x01
|
||||
#define FLAG_UNIDIRECTIONAL 0x02
|
||||
|
|
|
@ -55,6 +55,7 @@ domain 10.211.55.3 {
|
|||
static / serve_index
|
||||
static /intro.jpg serve_intro
|
||||
static /b64test serve_b64test
|
||||
static /spdy-reset serve_spdyreset
|
||||
}
|
||||
|
||||
#domain domain.com {
|
||||
|
|
|
@ -23,6 +23,8 @@ int serve_style_css(struct http_request *);
|
|||
int serve_index(struct http_request *);
|
||||
int serve_intro(struct http_request *);
|
||||
int serve_b64test(struct http_request *);
|
||||
int serve_spdyreset(struct http_request *);
|
||||
|
||||
void test_base64(u_int8_t *, u_int32_t, struct kore_buf *);
|
||||
|
||||
char *b64tests[] = {
|
||||
|
@ -111,6 +113,13 @@ serve_b64test(struct http_request *req)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
serve_spdyreset(struct http_request *req)
|
||||
{
|
||||
spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
void
|
||||
test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res)
|
||||
{
|
||||
|
|
|
@ -98,9 +98,11 @@ kore_platform_event_wait(void)
|
|||
}
|
||||
} else {
|
||||
c = (struct connection *)events[i].udata;
|
||||
if (events[i].filter == EVFILT_READ)
|
||||
if (events[i].filter == EVFILT_READ &&
|
||||
!(c->flags & CONN_READ_BLOCK))
|
||||
c->flags |= CONN_READ_POSSIBLE;
|
||||
if (events[i].filter == EVFILT_WRITE)
|
||||
if (events[i].filter == EVFILT_WRITE &&
|
||||
!(c->flags & CONN_WRITE_BLOCK))
|
||||
c->flags |= CONN_WRITE_POSSIBLE;
|
||||
|
||||
if (!kore_connection_handle(c)) {
|
||||
|
|
|
@ -222,8 +222,11 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len)
|
|||
spdy_header_block_add(hblock, hdr->header, hdr->value);
|
||||
|
||||
htext = spdy_header_block_release(req->owner, hblock, &hlen);
|
||||
if (htext == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
if (htext == NULL) {
|
||||
spdy_session_teardown(req->owner,
|
||||
SPDY_SESSION_ERROR_INTERNAL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
spdy_frame_send(req->owner, SPDY_CTRL_FRAME_SYN_REPLY,
|
||||
0, hlen, req->stream, 0);
|
||||
|
|
|
@ -104,7 +104,8 @@ kore_platform_event_wait(void)
|
|||
}
|
||||
} else {
|
||||
c = (struct connection *)events[i].data.ptr;
|
||||
if (events[i].events & EPOLLIN)
|
||||
if (events[i].events & EPOLLIN &&
|
||||
!(c->flags & CONN_READ_BLOCK))
|
||||
c->flags |= CONN_READ_POSSIBLE;
|
||||
if (events[i].events & EPOLLOUT &&
|
||||
!(c->flags & CONN_WRITE_BLOCK))
|
||||
|
|
92
src/spdy.c
92
src/spdy.c
|
@ -24,11 +24,12 @@ 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 int spdy_frame_send_done(struct netbuf *);
|
||||
static int spdy_goaway_send_done(struct netbuf *);
|
||||
|
||||
static void spdy_update_wsize(struct connection *,
|
||||
struct spdy_stream *, u_int32_t);
|
||||
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 *);
|
||||
static int spdy_zlib_deflate(struct connection *, u_int8_t *,
|
||||
|
@ -61,7 +62,9 @@ spdy_frame_recv(struct netbuf *nb)
|
|||
if (ctrl.version != 3) {
|
||||
kore_debug("protocol mismatch (recv version %d)",
|
||||
ctrl.version);
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
switch (ctrl.type) {
|
||||
|
@ -108,6 +111,9 @@ spdy_frame_recv(struct netbuf *nb)
|
|||
if (r == KORE_RESULT_OK) {
|
||||
net_recv_queue(c, SPDY_FRAME_SIZE,
|
||||
0, NULL, spdy_frame_recv);
|
||||
} else {
|
||||
r = KORE_RESULT_OK;
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
}
|
||||
|
||||
return (r);
|
||||
|
@ -145,6 +151,14 @@ spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags,
|
|||
|
||||
length = 12;
|
||||
break;
|
||||
case SPDY_CTRL_FRAME_GOAWAY:
|
||||
net_write16(&nb[0], 3);
|
||||
nb[0] |= (1 << 7);
|
||||
net_write16(&nb[2], type);
|
||||
net_write32(&nb[4], len);
|
||||
nb[4] = flags;
|
||||
length = 8;
|
||||
break;
|
||||
case SPDY_DATA_FRAME:
|
||||
net_write32(&nb[0], s->stream_id);
|
||||
nb[0] &= ~(1 << 7);
|
||||
|
@ -309,6 +323,26 @@ spdy_frame_data_done(struct netbuf *nb)
|
|||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
void
|
||||
spdy_session_teardown(struct connection *c, u_int8_t err)
|
||||
{
|
||||
u_int8_t d[8];
|
||||
|
||||
kore_debug("spdy_session_teardown(%p, %d)", c, err);
|
||||
|
||||
net_write32((u_int8_t *)&d[0], c->client_stream_id);
|
||||
net_write32((u_int8_t *)&d[4], err);
|
||||
|
||||
spdy_frame_send(c, SPDY_CTRL_FRAME_GOAWAY, 0, 8, NULL, 0);
|
||||
net_send_queue(c, d, sizeof(d), 0, NULL, spdy_goaway_send_done);
|
||||
|
||||
c->flags &= ~CONN_READ_POSSIBLE;
|
||||
c->flags |= CONN_READ_BLOCK;
|
||||
|
||||
c->idle_timer.length = 5;
|
||||
kore_connection_start_idletimer(c);
|
||||
}
|
||||
|
||||
static int
|
||||
spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
||||
{
|
||||
|
@ -337,19 +371,22 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
|||
if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) {
|
||||
kore_debug("client sent incorrect id for SPDY_SYN_STREAM (%d)",
|
||||
syn.stream_id);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
/* XXX need to send protocol error. */
|
||||
if (syn.stream_id < c->client_stream_id) {
|
||||
kore_debug("client sent incorrect id SPDY_SYN_STREAM (%d < %d)",
|
||||
syn.stream_id, c->client_stream_id);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if ((s = spdy_stream_lookup(c, syn.stream_id)) != NULL) {
|
||||
kore_debug("duplicate SPDY_SYN_STREAM (%d)", syn.stream_id);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
s = (struct spdy_stream *)kore_malloc(sizeof(*s));
|
||||
|
@ -366,7 +403,8 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
|||
kore_mem_free(s->hblock->header_block);
|
||||
kore_mem_free(s->hblock);
|
||||
kore_mem_free(s);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
s->hblock->header_pairs = net_read32(s->hblock->header_block);
|
||||
|
@ -376,19 +414,20 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
|||
host = NULL;
|
||||
method = NULL;
|
||||
|
||||
#define GET_HEADER(n, r) \
|
||||
if (!spdy_stream_get_header(s->hblock, n, r)) { \
|
||||
#define GET_HEADER(n, r) \
|
||||
if (!spdy_stream_get_header(s->hblock, n, r)) { \
|
||||
kore_mem_free(s->hblock->header_block); \
|
||||
kore_mem_free(s->hblock); \
|
||||
kore_mem_free(s); \
|
||||
kore_debug("no such header: %s", n); \
|
||||
if (path != NULL) \
|
||||
kore_debug("no such header: %s", n); \
|
||||
if (path != NULL) \
|
||||
kore_mem_free(path); \
|
||||
if (host != NULL) \
|
||||
if (host != NULL) \
|
||||
kore_mem_free(host); \
|
||||
if (method != NULL) \
|
||||
if (method != NULL) \
|
||||
kore_mem_free(method); \
|
||||
return (KORE_RESULT_ERROR); \
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); \
|
||||
return (KORE_RESULT_OK); \
|
||||
}
|
||||
|
||||
GET_HEADER(":path", &path);
|
||||
|
@ -403,7 +442,8 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
|||
kore_mem_free(s->hblock->header_block);
|
||||
kore_mem_free(s->hblock);
|
||||
kore_mem_free(s);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
kore_mem_free(path);
|
||||
|
@ -432,7 +472,8 @@ spdy_ctrl_frame_settings(struct netbuf *nb)
|
|||
if (length != ((ecount * 8) + 4)) {
|
||||
kore_debug("ecount is not correct (%d != %d)", length,
|
||||
(ecount * 8) + 4);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
buf = nb->buf + SPDY_FRAME_SIZE + 4;
|
||||
|
@ -469,7 +510,8 @@ spdy_ctrl_frame_ping(struct netbuf *nb)
|
|||
/* XXX todo - check if we sent the ping. */
|
||||
if ((id % 2) == 0) {
|
||||
kore_debug("received malformed client PING (%d)", id);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, NULL, id);
|
||||
|
@ -489,7 +531,8 @@ spdy_ctrl_frame_window(struct netbuf *nb)
|
|||
if ((s = spdy_stream_lookup(c, stream_id)) == NULL) {
|
||||
kore_debug("received WINDOW_UPDATE for nonexistant stream");
|
||||
kore_debug("stream_id: %d", stream_id);
|
||||
return (KORE_RESULT_ERROR);
|
||||
spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
kore_debug("SPDY_WINDOW_UPDATE: %d:%d", stream_id, window_size);
|
||||
|
@ -521,13 +564,15 @@ spdy_data_frame_recv(struct netbuf *nb)
|
|||
data.flags, data.length);
|
||||
|
||||
if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) {
|
||||
kore_debug("session data for incorrect stream");
|
||||
return (KORE_RESULT_OK);
|
||||
kore_debug("session data for non-existant stream");
|
||||
/* stream error */
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
req = (struct http_request *)s->httpreq;
|
||||
if (req->method != HTTP_METHOD_POST) {
|
||||
kore_debug("data frame for non post received");
|
||||
/* stream error */
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
|
@ -573,6 +618,15 @@ spdy_frame_send_done(struct netbuf *nb)
|
|||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
spdy_goaway_send_done(struct netbuf *nb)
|
||||
{
|
||||
struct connection *c = (struct connection *)nb->owner;
|
||||
|
||||
kore_connection_disconnect(c);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
|
||||
{
|
||||
|
|
|
@ -231,7 +231,8 @@ kore_worker_entry(struct kore_worker *kw)
|
|||
idle_check = now;
|
||||
TAILQ_FOREACH(c, &worker_clients, list) {
|
||||
if (c->proto == CONN_PROTO_SPDY &&
|
||||
!(c->flags & CONN_WRITE_BLOCK))
|
||||
!(c->flags & CONN_WRITE_BLOCK) &&
|
||||
!(c->flags & CONN_READ_BLOCK))
|
||||
continue;
|
||||
if (!(c->flags & CONN_IDLE_TIMER_ACT))
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue