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 bb3b8042225205c1b7fec7581dfbfbf6db1021a1
parent 071fc4100d9fb8d052377afc26b83fafead3dfad
Author: Joris Vink <joris@coders.se>
Date:   Mon, 29 Apr 2013 23:35:36 +0200

add beginnings of zlib inflation, not really working. nap time.

Diffstat:
includes/kore.h | 5++++-
includes/spdy.h | 12++++++++++++
src/kore.c | 1+
src/spdy.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 116 insertions(+), 8 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -64,6 +64,8 @@ struct connection { TAILQ_HEAD(, netbuf) send_queue; TAILQ_HEAD(, netbuf) recv_queue; + + TAILQ_HEAD(, spdy_stream) spdy_streams; }; void *kore_malloc(size_t); @@ -83,6 +85,7 @@ int net_recv_expand(struct connection *c, struct netbuf *, size_t, int net_send_queue(struct connection *, u_int8_t *, size_t, int (*cb)(struct netbuf *)); -int spdy_frame_recv(struct netbuf *); +int spdy_frame_recv(struct netbuf *); +struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t); #endif /* !__H_KORE_H */ diff --git a/includes/spdy.h b/includes/spdy.h @@ -47,8 +47,20 @@ struct spdy_syn_stream { int prio:3; }; +struct spdy_stream { + u_int32_t stream_id; + u_int8_t flags; + u_int8_t prio; + + u_int8_t *header_block; + u_int32_t header_block_len; + + TAILQ_ENTRY(spdy_stream) list; +}; + #define SPDY_CONTROL_FRAME(x) ((x->frame_1 & (1 << 31))) #define SPDY_FRAME_SIZE 8 +#define SPDY_ZLIB_CHUNK 16348 /* control frames. */ #define SPDY_CTRL_FRAME_SYN_STREAM 1 diff --git a/src/kore.c b/src/kore.c @@ -203,6 +203,7 @@ kore_server_accept(struct listener *l) TAILQ_INIT(&(c->send_queue)); TAILQ_INIT(&(c->recv_queue)); + TAILQ_INIT(&(c->spdy_streams));; kore_event(c->fd, EPOLLIN | EPOLLET, c); kore_log("new connection from %s", inet_ntoa(c->sin.sin_addr)); diff --git a/src/spdy.c b/src/spdy.c @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "spdy.h" #include "kore.h" @@ -83,12 +84,31 @@ spdy_frame_recv(struct netbuf *nb) return (r); } +struct spdy_stream * +spdy_stream_lookup(struct connection *c, u_int32_t id) +{ + struct spdy_stream *s; + + TAILQ_FOREACH(s, &(c->spdy_streams), list) { + if (s->stream_id == id) + return (s); + } + + return (NULL); +} + static int spdy_ctrl_frame_syn_stream(struct netbuf *nb) { u_int16_t *b; - struct spdy_ctrl_frame *ctrl; + struct spdy_stream *s; + z_stream zlib; struct spdy_syn_stream *syn; + size_t have; + struct spdy_ctrl_frame *ctrl; + int r, len; + u_char inflate_buffer[SPDY_ZLIB_CHUNK]; + struct connection *c = (struct connection *)nb->owner; ctrl = (struct spdy_ctrl_frame *)nb->buf; syn = (struct spdy_syn_stream *)(nb->buf + SPDY_FRAME_SIZE); @@ -98,12 +118,84 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb) b = (u_int16_t *)&(syn->slot); *b = ntohl(*b); - kore_log("stream id is %d", syn->stream_id); - kore_log("assoc stream id is %d", syn->assoc_stream_id); - kore_log("slot is %d", syn->slot); - kore_log("priority is %d", syn->prio); + if ((syn->stream_id % 2) == 0 || syn->stream_id == 0) { + kore_log("client sent incorrect id for SPDY_SYN_STREAM (%d)", + syn->stream_id); + return (KORE_RESULT_ERROR); + } + + if ((s = spdy_stream_lookup(c, syn->stream_id)) != NULL) { + kore_log("duplicate SPDY_SYN_STREAM (%d)", syn->stream_id); + return (KORE_RESULT_ERROR); + } + + kore_log("compressed headers are %d bytes long", ctrl->length - 10); + zlib.avail_in = 0; + zlib.next_in = Z_NULL; + zlib.zalloc = Z_NULL; + zlib.zfree = Z_NULL; + if ((r = inflateInit(&zlib)) != Z_OK) { + kore_log("inflateInit() failed: %d", r); + return (KORE_RESULT_ERROR); + } + + s = (struct spdy_stream *)kore_malloc(sizeof(*s)); + s->prio = syn->prio; + s->flags = ctrl->flags; + s->stream_id = syn->stream_id; + s->header_block_len = ctrl->length; + s->header_block = (u_int8_t *)kore_malloc(ctrl->length); + + have = 0; + len = ctrl->length - 10; + do { + if (len > SPDY_ZLIB_CHUNK) { + zlib.avail_in = SPDY_ZLIB_CHUNK; + len -= SPDY_ZLIB_CHUNK; + } else { + zlib.avail_in = len; + len = 0; + } + + if (zlib.avail_in == 0) + break; - kore_log("-- SPDY_SYN_STREAM"); + zlib.next_in = (u_char *)(syn + sizeof(struct spdy_syn_stream)); + do { + zlib.avail_out = SPDY_ZLIB_CHUNK; + zlib.next_out = inflate_buffer; + + r = inflate(&zlib, Z_SYNC_FLUSH); + switch (r) { + case Z_NEED_DICT: + kore_log("I need a dict"); + break; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&zlib); + free(s->header_block); + free(s); + kore_log("inflate(): %d", r); + return (KORE_RESULT_ERROR); + } + + have += SPDY_ZLIB_CHUNK - zlib.avail_out; + if (have > s->header_block_len) { + s->header_block_len += ctrl->length; + s->header_block = + (u_int8_t *)kore_realloc(s->header_block, + s->header_block_len); + } + + memcpy((s->header_block + have), inflate_buffer, + SPDY_ZLIB_CHUNK - zlib.avail_out); + } while (zlib.avail_out == 0); + } while (r != Z_STREAM_END); + + inflateEnd(&zlib); + TAILQ_INSERT_TAIL(&(c->spdy_streams), s, list); + + kore_log("SPDY_SYN_STREAM: %d:%d:%d", s->stream_id, s->flags, s->prio); return (KORE_RESULT_OK); } @@ -113,7 +205,7 @@ spdy_ctrl_frame_settings(struct netbuf *nb) int r; struct connection *c = (struct connection *)nb->owner; - kore_log("-- SPDY_SETTINGS"); + kore_log("SPDY_SETTINGS"); r = net_recv_queue(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (r);