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 d59847c4481c91c4ae04b32d8b2daed7458277f0
parent 848704f74bff8b5ea9c20a45be85e0c7453434d2
Author: Joris Vink <joris@coders.se>
Date:   Wed,  1 May 2013 12:23:21 +0200

SPDY works, we can serve content. Now for dynamic modules so we can
get stuff on the road.

TODO: add plain HTTP support if SPDY isnt working in the browser.

Diffstat:
includes/kore.h | 15+++++++++++++--
includes/spdy.h | 6+-----
src/http.c | 45++++++++++++++++++++++++++++++++++-----------
src/kore.c | 2++
src/net.c | 34++++++++++++++++++++--------------
src/spdy.c | 199++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
src/utils.c | 1+
7 files changed, 197 insertions(+), 105 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -62,6 +62,11 @@ struct connection { void *owner; SSL *ssl; + u_int8_t inflate_started; + z_stream z_inflate; + u_int8_t deflate_started; + z_stream z_deflate; + TAILQ_HEAD(, netbuf) send_queue; TAILQ_HEAD(, netbuf) recv_queue; @@ -92,9 +97,15 @@ 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 *)); +struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t); +struct spdy_header_block *spdy_header_block_create(int); + int spdy_frame_recv(struct netbuf *); int spdy_frame_send(struct connection *, u_int16_t, - u_int8_t, u_int32_t, u_int32_t, u_int8_t *); -struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t); + u_int8_t, u_int32_t, u_int32_t); +void spdy_header_block_add(struct spdy_header_block *, + char *, char *); +u_int8_t *spdy_header_block_release(struct connection *, + struct spdy_header_block *, u_int32_t *); #endif /* !__H_KORE_H */ diff --git a/includes/spdy.h b/includes/spdy.h @@ -68,7 +68,7 @@ extern const unsigned char SPDY_dictionary_txt[]; #define SPDY_CTRL_FRAME_SYN_STREAM 1 #define SPDY_CTRL_FRAME_SYN_REPLY 2 #define SPDY_CTRL_FRAME_SETTINGS 4 - +#define SPDY_CTRL_FRAME_PING 6 #define SPDY_DATA_FRAME 99 /* flags */ @@ -78,8 +78,4 @@ extern const unsigned char SPDY_dictionary_txt[]; #define SPDY_HBLOCK_NORMAL 0 #define SPDY_HBLOCK_DELAYED_ALLOC 1 -struct spdy_header_block *spdy_header_block_create(int); -void spdy_header_block_add(struct spdy_header_block *, char *, char *); -u_int8_t *spdy_header_block_release(struct spdy_header_block *, u_int32_t *); - #endif /* !__H_SPDY_H */ diff --git a/src/http.c b/src/http.c @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "spdy.h" #include "kore.h" @@ -39,6 +40,7 @@ TAILQ_HEAD(, http_request) http_requests; static int http_generic_cb(struct http_request *); +static int http_generic_404(struct http_request *); void http_init(void) @@ -80,32 +82,39 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len) { u_int32_t hlen; u_int8_t *htext; + char sbuf[4]; struct spdy_header_block *hblock; kore_log("http_response(%p, %d, %p, %d)", req, status, d, len); if (req->stream != NULL) { + snprintf(sbuf, sizeof(sbuf), "%d", status); hblock = spdy_header_block_create(SPDY_HBLOCK_NORMAL); - spdy_header_block_add(hblock, ":status", "200"); + spdy_header_block_add(hblock, ":status", sbuf); spdy_header_block_add(hblock, ":version", "HTTP/1.1"); spdy_header_block_add(hblock, "content-type", "text/plain"); - if ((htext = spdy_header_block_release(hblock, &hlen)) == NULL) + htext = spdy_header_block_release(req->owner, hblock, &hlen); + if (htext == NULL) return (KORE_RESULT_ERROR); - kore_log("deflated is %d bytes", hlen); - if (!spdy_frame_send(req->owner, SPDY_CTRL_FRAME_SYN_REPLY, - 0, hlen, req->stream->stream_id, NULL)) + 0, hlen, req->stream->stream_id)) return (KORE_RESULT_ERROR); if (!net_send_queue(req->owner, htext, hlen, NULL)) return (KORE_RESULT_ERROR); -#if 0 - if (!spdy_frame_send(req->owner, SPDY_DATA_FRAME, 0, len, - req->stream->stream_id, d)) + if (len > 0) { + if (!spdy_frame_send(req->owner, SPDY_DATA_FRAME, + 0, len, req->stream->stream_id)) + return (KORE_RESULT_ERROR); + if (!net_send_queue(req->owner, d, len, NULL)) + return (KORE_RESULT_ERROR); + } + + if (!spdy_frame_send(req->owner, SPDY_DATA_FRAME, + FLAG_FIN, 0, req->stream->stream_id)) return (KORE_RESULT_ERROR); -#endif } else { kore_log("normal http not functional yet"); } @@ -126,8 +135,13 @@ http_process(void) next = TAILQ_NEXT(req, list); /* XXX - add module hooks here */ - if (!http_generic_cb(req)) - kore_server_disconnect(req->owner); + if (!strcmp(req->path, "/favicon.ico")) { + if (!http_generic_404(req)) + kore_server_disconnect(req->owner); + } else { + if (!http_generic_cb(req)) + kore_server_disconnect(req->owner); + } TAILQ_REMOVE(&http_requests, req, list); http_request_free(req); @@ -145,3 +159,12 @@ http_generic_cb(struct http_request *req) len = strlen("<p>Hello world</p>"); return (http_response(req, 200, (u_int8_t *)"<p>Hello world</p>", len)); } + +static int +http_generic_404(struct http_request *req) +{ + kore_log("http_generic_404(%s, %s, %s)", + req->host, req->method, req->path); + + return (http_response(req, 404, NULL, 0)); +} diff --git a/src/kore.c b/src/kore.c @@ -32,6 +32,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <zlib.h> #include "spdy.h" #include "kore.h" @@ -89,6 +90,7 @@ main(int argc, char *argv[]) if (*fd == server.fd) fatal("error on server socket"); + kore_log("client EPOLLERR | EPOLLHUP"); c = (struct connection *)events[i].data.ptr; kore_server_disconnect(c); continue; diff --git a/src/net.c b/src/net.c @@ -32,6 +32,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "spdy.h" #include "kore.h" @@ -42,7 +43,7 @@ net_send_queue(struct connection *c, u_int8_t *data, size_t len, { struct netbuf *nb; - kore_log("net_send_queue(%p, %p, %d, %p)", c, data, len, cb); + //kore_log("net_send_queue(%p, %p, %d, %p)", c, data, len, cb); nb = (struct netbuf *)kore_malloc(sizeof(*nb)); nb->cb = cb; @@ -63,7 +64,7 @@ net_recv_queue(struct connection *c, size_t len, int (*cb)(struct netbuf *)) { struct netbuf *nb; - kore_log("net_recv_queue(%p, %d, %p)", c, len, cb); + //kore_log("net_recv_queue(%p, %d, %p)", c, len, cb); nb = (struct netbuf *)kore_malloc(sizeof(*nb)); nb->cb = cb; @@ -82,7 +83,7 @@ int net_recv_expand(struct connection *c, struct netbuf *nb, size_t len, int (*cb)(struct netbuf *)) { - kore_log("net_recv_expand(%p, %p, %d, %p)", c, nb, len, cb); + //kore_log("net_recv_expand(%p, %p, %d, %p)", c, nb, len, cb); if (nb->type != NETBUF_RECV) { kore_log("net_recv_expand(): wrong netbuf type"); @@ -103,15 +104,15 @@ net_send(struct connection *c) int r; struct netbuf *nb; - kore_log("net_send(%p)", c); - if (TAILQ_EMPTY(&(c->send_queue))) return (KORE_RESULT_OK); nb = TAILQ_FIRST(&(c->send_queue)); - kore_log("nb is %p (%d/%d bytes)", nb, nb->offset, nb->len); r = SSL_write(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset)); - kore_log("SSL_write(): %d bytes", r); + + //kore_log("net_send(%ld/%ld bytes), progress with %d", + // nb->offset, nb->len, r); + if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { @@ -151,15 +152,15 @@ net_recv(struct connection *c) int r; struct netbuf *nb; - kore_log("net_recv(%p)", c); - if (TAILQ_EMPTY(&(c->recv_queue))) return (KORE_RESULT_ERROR); nb = TAILQ_FIRST(&(c->recv_queue)); - kore_log("nb is %p (%d/%d bytes)", nb, nb->offset, nb->len); r = SSL_read(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset)); - kore_log("SSL_read(): %d bytes", r); + + //kore_log("net_recv(%ld/%ld bytes), progress with %d", + // nb->offset, nb->len, r); + if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { @@ -176,7 +177,6 @@ net_recv(struct connection *c) } nb->offset += (size_t)r; - kore_log("read %d out of %d bytes", nb->offset, nb->len); if (nb->offset == nb->len) { if (nb->cb == NULL) { kore_log("kore_read_client(): nb->cb == NULL"); @@ -220,11 +220,17 @@ net_read32(u_int8_t *b) void net_write16(u_int8_t *p, u_int16_t n) { - *p = htons(n); + u_int16_t r; + + r = htons(n); + memcpy(p, &r, sizeof(r)); } void net_write32(u_int8_t *p, u_int32_t n) { - *p = htonl(n); + u_int32_t r; + + r = htonl(n); + memcpy(p, &r, sizeof(r)); } diff --git a/src/spdy.c b/src/spdy.c @@ -39,13 +39,14 @@ static int spdy_ctrl_frame_syn_stream(struct netbuf *); static int spdy_ctrl_frame_settings(struct netbuf *); +static int spdy_ctrl_frame_ping(struct netbuf *); static int spdy_stream_get_header(struct spdy_header_block *, char *, char **); -static int spdy_zlib_inflate(u_int8_t *, size_t, - u_int8_t **, u_int32_t *); -static int spdy_zlib_deflate(u_int8_t *, size_t, - u_int8_t **, u_int32_t *); +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 *, + size_t, u_int8_t **, u_int32_t *); int spdy_frame_recv(struct netbuf *nb) @@ -54,6 +55,8 @@ spdy_frame_recv(struct netbuf *nb) int (*cb)(struct netbuf *), r; struct connection *c = (struct connection *)nb->owner; + kore_log("spdy_frame_recv(%p)", nb); + if (SPDY_CONTROL_FRAME(net_read32(nb->buf))) { kore_log("received control frame"); @@ -67,6 +70,12 @@ spdy_frame_recv(struct netbuf *nb) kore_log("length is %d", ctrl.length); kore_log("flags are %d", ctrl.flags); + if (ctrl.version != 3) { + kore_log("protocol mismatch (recv version %d)", + ctrl.version); + return (KORE_RESULT_ERROR); + } + switch (ctrl.type) { case SPDY_CTRL_FRAME_SYN_STREAM: cb = spdy_ctrl_frame_syn_stream; @@ -74,6 +83,9 @@ spdy_frame_recv(struct netbuf *nb) case SPDY_CTRL_FRAME_SETTINGS: cb = spdy_ctrl_frame_settings; break; + case SPDY_CTRL_FRAME_PING: + cb = spdy_ctrl_frame_ping; + break; default: cb = NULL; break; @@ -86,36 +98,51 @@ spdy_frame_recv(struct netbuf *nb) r = KORE_RESULT_ERROR; } } else { - r = KORE_RESULT_OK; - kore_log("received data frame"); + r = KORE_RESULT_ERROR; + kore_log("received data frame, can't handle that yet."); } + if (r == KORE_RESULT_OK) + r = net_recv_queue(c, SPDY_FRAME_SIZE, spdy_frame_recv); + return (r); } int spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags, - u_int32_t len, u_int32_t stream_id, u_int8_t *data) + u_int32_t len, u_int32_t stream_id) { u_int8_t nb[12]; u_int32_t length; - kore_log("spdy_frame_send(%p, %d, %d, %d, %d, %p)", c, type, flags, - len, stream_id, data); + kore_log("spdy_frame_send(%p, %d, %d, %d, %d)", c, type, flags, + len, stream_id); length = 0; memset(nb, 0, sizeof(nb)); switch (type) { + case SPDY_CTRL_FRAME_PING: case SPDY_CTRL_FRAME_SYN_REPLY: net_write16(&nb[0], 3); nb[0] |= (1 << 7); net_write16(&nb[2], type); - net_write32(&nb[4], len + 4); + + if (type != SPDY_CTRL_FRAME_PING) + net_write32(&nb[4], len + 4); + else + net_write32(&nb[4], len); + nb[4] = flags; net_write32(&nb[8], stream_id); length = 12; break; + break; case SPDY_DATA_FRAME: + net_write32(&nb[0], stream_id); + nb[0] &= ~(1 << 7); + net_write32(&nb[4], len); + nb[4] = flags; + length = 8; break; } @@ -146,13 +173,14 @@ spdy_header_block_create(int delayed_alloc) if (delayed_alloc == SPDY_HBLOCK_NORMAL) { hblock->header_block = (u_int8_t *)kore_malloc(128); hblock->header_block_len = 128; + hblock->header_offset = 4; } else { hblock->header_block = NULL; hblock->header_block_len = 0; + hblock->header_offset = 0; } hblock->header_pairs = 0; - hblock->header_offset = 0; return (hblock); } @@ -161,7 +189,6 @@ void spdy_header_block_add(struct spdy_header_block *hblock, char *name, char *value) { u_int8_t *p; - char *out; u_int32_t nlen, vlen; kore_log("spdy_header_block_add(%p, %s, %s)", hblock, name, value); @@ -186,23 +213,18 @@ spdy_header_block_add(struct spdy_header_block *hblock, char *name, char *value) hblock->header_offset += 4 + vlen; hblock->header_pairs++; - - if (!spdy_stream_get_header(hblock, name, &out)) { - kore_log("cannot find newly inserted header %s", name); - } else { - kore_log("found header (%s, %s) as %s", name, value, out); - free(out); - } } u_int8_t * -spdy_header_block_release(struct spdy_header_block *hblock, u_int32_t *len) +spdy_header_block_release(struct connection *c, + struct spdy_header_block *hblock, u_int32_t *len) { u_int8_t *deflated; kore_log("spdy_header_block_release(%p, %p)", hblock, len); - if (!spdy_zlib_deflate(hblock->header_block, hblock->header_offset, + net_write32(hblock->header_block, hblock->header_pairs); + if (!spdy_zlib_deflate(c, hblock->header_block, hblock->header_offset, &deflated, len)) { free(hblock->header_block); free(hblock); @@ -235,6 +257,10 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb) syn.prio = net_read16(nb->buf + 16) & 0xe000; syn.slot = net_read16(nb->buf + 16) & 0x7; + kore_log("spdy_ctrl_frame_syn_stream()"); + kore_log("stream_id: %d", syn.stream_id); + kore_log("length : %d", ctrl.length); + /* XXX need to send protocol error. */ if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) { kore_log("client sent incorrect id for SPDY_SYN_STREAM (%d)", @@ -262,7 +288,7 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb) src = (nb->buf + SPDY_FRAME_SIZE + SPDY_SYNFRAME_SIZE); kore_log("compressed headers are %d bytes long", ctrl.length - 10); - if (!spdy_zlib_inflate(src, (ctrl.length - SPDY_SYNFRAME_SIZE), + if (!spdy_zlib_inflate(c, src, (ctrl.length - SPDY_SYNFRAME_SIZE), &(s->hblock->header_block), &(s->hblock->header_block_len))) { free(s->hblock->header_block); free(s->hblock); @@ -316,13 +342,27 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb) static int spdy_ctrl_frame_settings(struct netbuf *nb) { - int r; + kore_log("SPDY_SETTINGS (to be implemented)"); + + return (KORE_RESULT_OK); +} + +static int +spdy_ctrl_frame_ping(struct netbuf *nb) +{ + u_int32_t id; struct connection *c = (struct connection *)nb->owner; - kore_log("SPDY_SETTINGS"); - r = net_recv_queue(c, SPDY_FRAME_SIZE, spdy_frame_recv); + id = ntohl(*(u_int32_t *)(nb->buf + SPDY_FRAME_SIZE)); + kore_log("SPDY_PING: %d", id); - return (r); + /* XXX todo - check if we sent the ping. */ + if ((id % 2) == 0) { + kore_log("received malformed client PING (%d)", id); + return (KORE_RESULT_ERROR); + } + + return (spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, id)); } static int @@ -332,9 +372,14 @@ spdy_stream_get_header(struct spdy_header_block *s, char *header, char **out) u_int8_t *p, *end; u_int32_t i, nlen, vlen; + p = s->header_block + 4; end = s->header_block + s->header_block_len; - p = s->header_block + 4; + if (p >= end) { + kore_log("p >= end when looking for headers"); + return (KORE_RESULT_ERROR); + } + for (i = 0; i < s->header_pairs; i++) { nlen = net_read32(p); if ((p + nlen + 4) >= end) { @@ -367,41 +412,45 @@ spdy_stream_get_header(struct spdy_header_block *s, char *header, char **out) } static int -spdy_zlib_inflate(u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) +spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len, + u_int8_t **dst, u_int32_t *olen) { - z_stream zlib; size_t have; int r, ret; u_char inflate_buffer[SPDY_ZLIB_CHUNK]; - kore_log("spdy_zlib_inflate(%p, %d)", src, len); + kore_log("spdy_zlib_inflate(%p, %p, %d)", c, src, len); - 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); + if (c->inflate_started == 0) { + c->z_inflate.avail_in = 0; + c->z_inflate.next_in = Z_NULL; + c->z_inflate.zalloc = Z_NULL; + c->z_inflate.zfree = Z_NULL; + if ((r = inflateInit(&(c->z_inflate))) != Z_OK) { + kore_log("inflateInit() failed: %d", r); + return (KORE_RESULT_ERROR); + } + + c->inflate_started = 1; } *olen = 0; *dst = NULL; ret = -1; - zlib.avail_in = len; - zlib.next_in = src; + c->z_inflate.avail_in = len; + c->z_inflate.next_in = src; while (ret == -1) { - zlib.avail_out = SPDY_ZLIB_CHUNK; - zlib.next_out = inflate_buffer; + c->z_inflate.avail_out = SPDY_ZLIB_CHUNK; + c->z_inflate.next_out = inflate_buffer; - r = inflate(&zlib, Z_SYNC_FLUSH); + r = inflate(&(c->z_inflate), Z_SYNC_FLUSH); switch (r) { case Z_NEED_DICT: - r = inflateSetDictionary(&zlib, SPDY_dictionary_txt, - SPDY_ZLIB_DICT_SIZE); + r = inflateSetDictionary(&(c->z_inflate), + SPDY_dictionary_txt, SPDY_ZLIB_DICT_SIZE); if (r != Z_OK) { - inflateEnd(&zlib); + inflateEnd(&(c->z_inflate)); kore_log("inflateSetDictionary(): %d", r); return (KORE_RESULT_ERROR); } @@ -414,12 +463,13 @@ spdy_zlib_inflate(u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) kore_log("inflate(): %d", r); break; case Z_OK: - have = SPDY_ZLIB_CHUNK - zlib.avail_out; + have = SPDY_ZLIB_CHUNK - c->z_inflate.avail_out; *olen += have; *dst = (u_int8_t *)kore_realloc(*dst, *olen); memcpy((*dst) + (*olen - have), inflate_buffer, have); - if (zlib.avail_in != 0 || zlib.avail_out == 0) + if (c->z_inflate.avail_in != 0 || + c->z_inflate.avail_out == 0) break; /* FALLTHROUGH */ case Z_STREAM_END: @@ -428,48 +478,51 @@ spdy_zlib_inflate(u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) } } - inflateEnd(&zlib); return (ret); } static int -spdy_zlib_deflate(u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) +spdy_zlib_deflate(struct connection *c, u_int8_t *src, size_t len, + u_int8_t **dst, u_int32_t *olen) { - z_stream zlib; size_t have; int r, ret; u_char deflate_buffer[SPDY_ZLIB_CHUNK]; - kore_log("spdy_zlib_deflate(%p, %d)", src, len); + kore_log("spdy_zlib_deflate(%p, %p, %d)", c, src, len); - zlib.avail_in = 0; - zlib.next_in = Z_NULL; - zlib.zalloc = Z_NULL; - zlib.zfree = Z_NULL; - if ((r = deflateInit(&zlib, -1)) != Z_OK) { - kore_log("deflateInit() failed: %d", r); - return (KORE_RESULT_ERROR); - } + if (c->deflate_started == 0) { + c->z_deflate.avail_in = 0; + c->z_deflate.next_in = Z_NULL; + c->z_deflate.zalloc = Z_NULL; + c->z_deflate.zfree = Z_NULL; + if ((r = deflateInit(&(c->z_deflate), -1)) != Z_OK) { + kore_log("deflateInit() failed: %d", r); + return (KORE_RESULT_ERROR); + } - r = deflateSetDictionary(&zlib, SPDY_dictionary_txt, - SPDY_ZLIB_DICT_SIZE); - if (r != Z_OK) { - deflateEnd(&zlib); - kore_log("delfateSetDictionary(): %d", r); - return (KORE_RESULT_ERROR); + r = deflateSetDictionary(&(c->z_deflate), SPDY_dictionary_txt, + SPDY_ZLIB_DICT_SIZE); + if (r != Z_OK) { + deflateEnd(&(c->z_deflate)); + kore_log("delfateSetDictionary(): %d", r); + return (KORE_RESULT_ERROR); + } + + c->deflate_started = 1; } *olen = 0; *dst = NULL; ret = -1; - zlib.avail_in = len; - zlib.next_in = src; + c->z_deflate.avail_in = len; + c->z_deflate.next_in = src; while (ret == -1) { - zlib.avail_out = SPDY_ZLIB_CHUNK; - zlib.next_out = deflate_buffer; + c->z_deflate.avail_out = SPDY_ZLIB_CHUNK; + c->z_deflate.next_out = deflate_buffer; - r = deflate(&zlib, Z_SYNC_FLUSH); + r = deflate(&(c->z_deflate), Z_SYNC_FLUSH); switch (r) { case Z_BUF_ERROR: case Z_DATA_ERROR: @@ -478,17 +531,17 @@ spdy_zlib_deflate(u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) kore_log("deflate(): %d", r); break; case Z_OK: - have = SPDY_ZLIB_CHUNK - zlib.avail_out; + have = SPDY_ZLIB_CHUNK - c->z_deflate.avail_out; *olen += have; *dst = (u_int8_t *)kore_realloc(*dst, *olen); memcpy((*dst) + (*olen - have), deflate_buffer, have); - if (zlib.avail_in == 0 && zlib.avail_out != 0) + if (c->z_deflate.avail_in == 0 && + c->z_deflate.avail_out != 0) ret = KORE_RESULT_OK; break; } } - deflateEnd(&zlib); return (ret); } diff --git a/src/utils.c b/src/utils.c @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "spdy.h" #include "kore.h"