properly deflate/inflate of name/value blocks. and add ability

to get headers from them.
This commit is contained in:
Joris Vink 2013-05-01 00:35:33 +02:00
parent bb3b804222
commit 05156c9a3a
9 changed files with 563 additions and 111 deletions

View File

@ -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)

31
includes/http.h Normal file
View File

@ -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 */

View File

@ -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);

View File

@ -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

47
src/http.c Normal file
View File

@ -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);
}

View File

@ -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));
}

View File

@ -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;
switch (ctrl->type) {
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) {
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);
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);
if ((s = spdy_stream_lookup(c, syn.stream_id)) != NULL) {
kore_log("duplicate SPDY_SYN_STREAM (%d)", syn.stream_id);
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);
s->prio = syn.prio;
s->flags = ctrl.flags;
s->stream_id = syn.stream_id;
s->header_block_len = 0;
s->header_block = NULL;
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;
}
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);
}
if (zlib.avail_in == 0)
break;
s->header_pairs = net_read32(s->header_block);
kore_log("got %d headers", s->header_pairs);
zlib.next_in = (u_char *)(syn + sizeof(struct spdy_syn_stream));
do {
zlib.avail_out = SPDY_ZLIB_CHUNK;
zlib.next_out = inflate_buffer;
#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); \
}
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);
}
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);
}
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);
}
free(path);
free(method);
free(host);
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);
}
@ -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);
}

View File

@ -92,6 +92,20 @@ kore_log_internal(char *file, int line, const char *fmt, ...)
printf("%s:%d - %s\n", file, line, buf);
}
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, ...)
{

196
src/zlib_dict.c Normal file
View File

@ -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 -
};