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 05156c9a3a41d67b6f32b1a7855c0cec0c9bed7b
parent bb3b8042225205c1b7fec7581dfbfbf6db1021a1
Author: Joris Vink <joris@coders.se>
Date:   Wed,  1 May 2013 00:35:33 +0200

properly deflate/inflate of name/value blocks. and add ability
to get headers from them.

Diffstat:
Makefile | 4++--
includes/http.h | 31+++++++++++++++++++++++++++++++
includes/kore.h | 6++++++
includes/spdy.h | 40+++++++++++++++++++---------------------
src/http.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
src/net.c | 18++++++++++++++++++
src/spdy.c | 318+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
src/utils.c | 14++++++++++++++
src/zlib_dict.c | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 563 insertions(+), 111 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,14 +3,14 @@ CC=gcc BIN=kore -S_SRC= src/kore.c src/net.c src/spdy.c src/utils.c +S_SRC= src/kore.c src/net.c src/spdy.c src/http.c src/utils.c src/zlib_dict.c S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-I/usr/local/ssl/include CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wsign-compare -Iincludes -g -LDFLAGS=-static -Llibs -lssl -lcrypto -lz +LDFLAGS=-static -Llibs -lssl -lcrypto -ldl -lz light: $(S_OBJS) $(CC) $(CFLAGS) $(S_OBJS) $(LDFLAGS) -o $(BIN) diff --git a/includes/http.h b/includes/http.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __H_HTTP_H +#define __H_HTTP_H + +struct http_request { + char *host; + char *method; + char *path; + + struct connection *owner; + struct spdy_stream *stream; + + TAILQ_ENTRY(http_request) list; +}; + +#endif /* !__H_HTTP_H */ diff --git a/includes/kore.h b/includes/kore.h @@ -72,10 +72,13 @@ void *kore_malloc(size_t); void *kore_calloc(size_t, size_t); void *kore_realloc(void *, size_t); char *kore_strdup(const char *); +void kore_strlcpy(char *, const char *, size_t); void fatal(const char *, ...); void kore_log_internal(char *, int, const char *, ...); +u_int16_t net_read16(u_int8_t *); +u_int32_t net_read32(u_int8_t *); int net_recv(struct connection *); int net_send(struct connection *); int net_recv_queue(struct connection *, size_t, @@ -85,6 +88,9 @@ 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 http_new_request(struct connection *, struct spdy_stream *, + char *, char *, char *); + int spdy_frame_recv(struct netbuf *); struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t); diff --git a/includes/spdy.h b/includes/spdy.h @@ -17,34 +17,25 @@ #ifndef __H_SPDY_H #define __H_SPDY_H -#define KORE_SSL_PROTO_STRING "\x06spdy/3\x08http/1.1" - -struct spdy_frame { - u_int32_t frame_1; - u_int32_t frame_2; -}; - struct spdy_ctrl_frame { - int type:16; - int version:15; - int control_bit:1; - int length:24; - int flags:8; + u_int16_t version; + u_int16_t type; + u_int8_t flags; + u_int32_t length; }; struct spdy_data_frame { - int stream_id:31; - int control_bit:1; - int length:24; - int flags:8; + u_int32_t stream_id; + u_int8_t flags; + u_int32_t length; }; struct spdy_syn_stream { u_int32_t stream_id; u_int32_t assoc_stream_id; u_int8_t slot; - int reserved:5; - int prio:3; + u_int8_t reserved; + u_int8_t prio; }; struct spdy_stream { @@ -54,19 +45,26 @@ struct spdy_stream { u_int8_t *header_block; u_int32_t header_block_len; + u_int32_t header_pairs; TAILQ_ENTRY(spdy_stream) list; }; -#define SPDY_CONTROL_FRAME(x) ((x->frame_1 & (1 << 31))) +extern const unsigned char SPDY_dictionary_txt[]; + +#define KORE_SSL_PROTO_STRING "\x06spdy/3\x08http/1.1" +#define SPDY_CONTROL_FRAME(x) ((x & (1 << 31))) + #define SPDY_FRAME_SIZE 8 +#define SPDY_SYNFRAME_SIZE 10 +#define SPDY_ZLIB_DICT_SIZE 1423 #define SPDY_ZLIB_CHUNK 16348 -/* control frames. */ +/* control frames */ #define SPDY_CTRL_FRAME_SYN_STREAM 1 #define SPDY_CTRL_FRAME_SETTINGS 4 -/* flags. */ +/* flags */ #define FLAG_FIN 0x01 #define FLAG_UNIDIRECTIONAL 0x02 diff --git a/src/http.c b/src/http.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <openssl/err.h> +#include <openssl/ssl.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "spdy.h" +#include "kore.h" +#include "http.h" + +int +http_new_request(struct connection *c, struct spdy_stream *s, char *host, + char *method, char *path) +{ + kore_log("http_new_request(%p, %p, %s, %s, %s)", c, s, + host, method, path); + + return (KORE_RESULT_OK); +} diff --git a/src/net.c b/src/net.c @@ -196,3 +196,21 @@ net_recv(struct connection *c) return (r); } + +u_int16_t +net_read16(u_int8_t *b) +{ + u_int16_t r; + + r = *(u_int16_t *)b; + return (ntohs(r)); +} + +u_int32_t +net_read32(u_int8_t *b) +{ + u_int32_t r; + + r = *(u_int32_t *)b; + return (ntohl(r)); +} diff --git a/src/spdy.c b/src/spdy.c @@ -35,30 +35,39 @@ #include "spdy.h" #include "kore.h" +#include "http.h" static int spdy_ctrl_frame_syn_stream(struct netbuf *); static int spdy_ctrl_frame_settings(struct netbuf *); +static int spdy_stream_get_header(struct spdy_stream *, + 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 *); int spdy_frame_recv(struct netbuf *nb) { - struct spdy_ctrl_frame *ctrl; + struct spdy_ctrl_frame ctrl; int (*cb)(struct netbuf *), r; struct connection *c = (struct connection *)nb->owner; - struct spdy_frame *frame = (struct spdy_frame *)nb->buf; - - frame->frame_1 = ntohl(frame->frame_1); - frame->frame_2 = ntohl(frame->frame_2); - if (SPDY_CONTROL_FRAME(frame)) { + if (SPDY_CONTROL_FRAME(net_read32(nb->buf))) { kore_log("received control frame"); - ctrl = (struct spdy_ctrl_frame *)frame; - kore_log("type is %d", ctrl->type); - kore_log("version is %d", ctrl->version); - kore_log("length is %d", ctrl->length); + ctrl.version = net_read16(nb->buf) & 0x7fff; + ctrl.type = net_read16(nb->buf + 2); + ctrl.flags = *(u_int8_t *)(nb->buf + 4); + ctrl.length = net_read32(nb->buf + 4) & 0xffffff; + + kore_log("type is %d", ctrl.type); + kore_log("version is %d", ctrl.version); + kore_log("length is %d", ctrl.length); + kore_log("flags are %d", ctrl.flags); - switch (ctrl->type) { + switch (ctrl.type) { case SPDY_CTRL_FRAME_SYN_STREAM: cb = spdy_ctrl_frame_syn_stream; break; @@ -71,9 +80,9 @@ spdy_frame_recv(struct netbuf *nb) } if (cb != NULL) { - r = net_recv_expand(c, nb, ctrl->length, cb); + r = net_recv_expand(c, nb, ctrl.length, cb); } else { - kore_log("no callback for type %d", ctrl->type); + kore_log("no callback for type %d", ctrl.type); r = KORE_RESULT_ERROR; } } else { @@ -100,102 +109,78 @@ spdy_stream_lookup(struct connection *c, u_int32_t id) static int spdy_ctrl_frame_syn_stream(struct netbuf *nb) { - u_int16_t *b; 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 spdy_syn_stream syn; + struct spdy_ctrl_frame ctrl; + u_int8_t *src; + char *host, *method, *path; struct connection *c = (struct connection *)nb->owner; - ctrl = (struct spdy_ctrl_frame *)nb->buf; - syn = (struct spdy_syn_stream *)(nb->buf + SPDY_FRAME_SIZE); + ctrl.version = net_read16(nb->buf) & 0x7fff; + ctrl.type = net_read16(nb->buf + 2); + ctrl.flags = *(u_int8_t *)(nb->buf + 4); + ctrl.length = net_read32(nb->buf + 4) & 0xffffff; - syn->stream_id = ntohl(syn->stream_id); - syn->assoc_stream_id = ntohl(syn->assoc_stream_id); - b = (u_int16_t *)&(syn->slot); - *b = ntohl(*b); + syn.stream_id = net_read32(nb->buf + 8); + syn.assoc_stream_id = net_read32(nb->buf + 12); + syn.prio = net_read16(nb->buf + 16) & 0xe000; + syn.slot = net_read16(nb->buf + 16) & 0x7; - if ((syn->stream_id % 2) == 0 || syn->stream_id == 0) { + /* XXX need to send protocol errors here? */ + if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) { kore_log("client sent incorrect id for SPDY_SYN_STREAM (%d)", - syn->stream_id); + 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); + 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); + 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 = 0; + s->header_block = NULL; + + 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), + &(s->header_block), &(s->header_block_len))) { + free(s->header_block); + free(s); 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; - - zlib.next_in = (u_char *)(syn + sizeof(struct spdy_syn_stream)); - do { - zlib.avail_out = SPDY_ZLIB_CHUNK; - zlib.next_out = inflate_buffer; + s->header_pairs = net_read32(s->header_block); + kore_log("got %d headers", s->header_pairs); - 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); - } +#define GET_HEADER(n, r) \ + if (!spdy_stream_get_header(s, n, r)) { \ + free(s->header_block); \ + free(s); \ + kore_log("no such header: %s", n); \ + 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); - } + GET_HEADER(":path", &path); + GET_HEADER(":method", &method); + GET_HEADER(":host", &host); + if (!http_new_request(c, s, host, method, path)) { + free(s->header_block); + free(s); + return (KORE_RESULT_ERROR); + } - memcpy((s->header_block + have), inflate_buffer, - SPDY_ZLIB_CHUNK - zlib.avail_out); - } while (zlib.avail_out == 0); - } while (r != Z_STREAM_END); + free(path); + free(method); + free(host); - 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); } @@ -210,3 +195,160 @@ spdy_ctrl_frame_settings(struct netbuf *nb) return (r); } + +static int +spdy_stream_get_header(struct spdy_stream *s, char *header, char **out) +{ + u_int8_t *p; + char *cmp; + u_int32_t i, nlen, vlen; + + p = s->header_block + 4; + for (i = 0; i < s->header_pairs; i++) { + nlen = net_read32(p); + vlen = net_read32(p + nlen + 4); + + cmp = (char *)(p + 4); + if (!strncasecmp(cmp, header, nlen)) { + kore_log("found %s header", header); + + cmp = (char *)(p + nlen + 8); + *out = (char *)kore_malloc(vlen + 1); + kore_strlcpy(*out, cmp, vlen + 1); + return (KORE_RESULT_OK); + } + + kore_log("pair name %d bytes, value %d bytes", nlen, vlen); + + p += nlen + vlen + 8; + } + + return (KORE_RESULT_ERROR); +} + +static int +spdy_zlib_inflate(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); + + 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); + } + + *olen = 0; + *dst = NULL; + + ret = -1; + zlib.avail_in = len; + zlib.next_in = src; + while (ret == -1) { + zlib.avail_out = SPDY_ZLIB_CHUNK; + zlib.next_out = inflate_buffer; + + r = inflate(&zlib, Z_SYNC_FLUSH); + switch (r) { + case Z_NEED_DICT: + r = inflateSetDictionary(&zlib, SPDY_dictionary_txt, + SPDY_ZLIB_DICT_SIZE); + if (r != Z_OK) { + inflateEnd(&zlib); + kore_log("inflateSetDictionary(): %d", r); + return (KORE_RESULT_ERROR); + } + + continue; + case Z_BUF_ERROR: + case Z_DATA_ERROR: + case Z_MEM_ERROR: + ret = KORE_RESULT_ERROR; + kore_log("inflate(): %d", r); + break; + case Z_OK: + have = SPDY_ZLIB_CHUNK - zlib.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) + break; + /* FALLTHROUGH */ + case Z_STREAM_END: + ret = KORE_RESULT_OK; + break; + } + } + + inflateEnd(&zlib); + return (ret); +} + +static int +spdy_zlib_deflate(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); + + 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); + } + + 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); + } + + *olen = 0; + *dst = NULL; + + ret = -1; + zlib.avail_in = len; + zlib.next_in = src; + while (ret == -1) { + zlib.avail_out = SPDY_ZLIB_CHUNK; + zlib.next_out = deflate_buffer; + + r = deflate(&zlib, Z_SYNC_FLUSH); + switch (r) { + case Z_BUF_ERROR: + case Z_DATA_ERROR: + case Z_MEM_ERROR: + ret = KORE_RESULT_ERROR; + kore_log("deflate(): %d", r); + break; + case Z_OK: + have = SPDY_ZLIB_CHUNK - zlib.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) + ret = KORE_RESULT_OK; + break; + } + } + + deflateEnd(&zlib); + return (ret); +} diff --git a/src/utils.c b/src/utils.c @@ -93,6 +93,20 @@ kore_log_internal(char *file, int line, const char *fmt, ...) } void +kore_strlcpy(char *dst, const char *src, size_t len) +{ + char *d = dst; + const char *s = src; + + while ((*d++ = *s++) != '\0') { + if (d == (dst + len - 1)) { + *d = '\0'; + break; + } + } +} + +void fatal(const char *fmt, ...) { va_list args; diff --git a/src/zlib_dict.c b/src/zlib_dict.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +const unsigned char SPDY_dictionary_txt[] = { + 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // - - - - o p t i + 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // o n s - - - - h + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // e a d - - - - p + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // o s t - - - - p + 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // u t - - - - d e + 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // l e t e - - - - + 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // t r a c e - - - + 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // - a c c e p t - + 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p + 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t - c h a r s e + 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t - - - - a c c + 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e p t - e n c o + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // d i n g - - - - + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // a c c e p t - l + 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // a n g u a g e - + 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p + 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t - r a n g e s + 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // - - - - a g e - + 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // - - - a l l o w + 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // - - - - a u t h + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // o r i z a t i o + 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n - - - - c a c + 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // h e - c o n t r + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // o l - - - - c o + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // n n e c t i o n + 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t + 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // e n t - b a s e + 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t + 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e n t - e n c o + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // d i n g - - - - + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // c o n t e n t - + 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // l a n g u a g e + 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t + 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // e n t - l e n g + 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // t h - - - - c o + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // n t e n t - l o + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // c a t i o n - - + 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n + 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t - m d 5 - - - + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // - c o n t e n t + 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // - r a n g e - - + 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n + 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t - t y p e - - + 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // - - d a t e - - + 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // - - e t a g - - + 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // - - e x p e c t + 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // - - - - e x p i + 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // r e s - - - - f + 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // r o m - - - - h + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // o s t - - - - i + 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f - m a t c h - + 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // - - - i f - m o + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // d i f i e d - s + 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // i n c e - - - - + 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // i f - n o n e - + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // m a t c h - - - + 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // - i f - r a n g + 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e - - - - i f - + 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // u n m o d i f i + 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // e d - s i n c e + 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // - - - - l a s t + 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // - m o d i f i e + 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d - - - - l o c + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // a t i o n - - - + 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // - m a x - f o r + 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // w a r d s - - - + 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // - p r a g m a - + 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // - - - p r o x y + 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // - a u t h e n t + 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // i c a t e - - - + 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // - p r o x y - a + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // u t h o r i z a + 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // t i o n - - - - + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // r a n g e - - - + 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // - r e f e r e r + 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // - - - - r e t r + 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y - a f t e r - + 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // - - - s e r v e + 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r - - - - t e - + 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // - - - t r a i l + 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // e r - - - - t r + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // a n s f e r - e + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // n c o d i n g - + 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // - - - u p g r a + 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // d e - - - - u s + 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // e r - a g e n t + 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // - - - - v a r y + 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // - - - - v i a - + 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // - - - w a r n i + 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // n g - - - - w w + 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w - a u t h e n + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // t i c a t e - - + 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // - - m e t h o d + 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // - - - - g e t - + 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // - - - s t a t u + 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s - - - - 2 0 0 + 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // - O K - - - - v + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // e r s i o n - - + 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // - - H T T P - 1 + 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // - 1 - - - - u r + 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l - - - - p u b + 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // l i c - - - - s + 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // e t - c o o k i + 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e - - - - k e e + 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p - a l i v e - + 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // - - - o r i g i + 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n 1 0 0 1 0 1 2 + 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 0 1 2 0 2 2 0 5 + 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 2 0 6 3 0 0 3 0 + 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 2 3 0 3 3 0 4 3 + 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 0 5 3 0 6 3 0 7 + 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 4 0 2 4 0 5 4 0 + 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 6 4 0 7 4 0 8 4 + 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 0 9 4 1 0 4 1 1 + 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 4 1 2 4 1 3 4 1 + 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 4 4 1 5 4 1 6 4 + 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 1 7 5 0 2 5 0 4 + 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 5 0 5 2 0 3 - N + 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // o n - A u t h o + 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // r i t a t i v e + 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // - I n f o r m a + 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // t i o n 2 0 4 - + 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // N o - C o n t e + 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // n t 3 0 1 - M o + 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // v e d - P e r m + 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // a n e n t l y 4 + 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 0 0 - B a d - R + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // e q u e s t 4 0 + 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1 - U n a u t h + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // o r i z e d 4 0 + 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3 - F o r b i d + 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // d e n 4 0 4 - N + 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // o t - F o u n d + 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 5 0 0 - I n t e + 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // r n a l - S e r + 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // v e r - E r r o + 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r 5 0 1 - N o t + 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // - I m p l e m e + 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // n t e d 5 0 3 - + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // S e r v i c e - + 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // U n a v a i l a + 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // b l e J a n - F + 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // e b - M a r - A + 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // p r - M a y - J + 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // u n - J u l - A + 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // u g - S e p t - + 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // O c t - N o v - + 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // D e c - 0 0 - 0 + 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0 - 0 0 - M o n + 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // - - T u e - - W + 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // e d - - T h u - + 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // - F r i - - S a + 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t - - S u n - - + 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // G M T c h u n k + 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // e d - t e x t - + 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // h t m l - i m a + 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // g e - p n g - i + 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // m a g e - j p g + 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // - i m a g e - g + 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // i f - a p p l i + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x + 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // m l - a p p l i + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x + 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // h t m l - x m l + 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // - t e x t - p l + 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // a i n - t e x t + 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // - j a v a s c r + 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // i p t - p u b l + 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // i c p r i v a t + 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // e m a x - a g e + 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // - g z i p - d e + 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // f l a t e - s d + 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // c h c h a r s e + 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t - u t f - 8 c + 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // h a r s e t - i + 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // s o - 8 8 5 9 - + 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1 - u t f - - - + 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // - e n q - 0 - +};