add base64 encoder/decoder in prep for http/2.0 and websockets

This commit is contained in:
Joris Vink 2013-07-10 15:00:53 +02:00
parent bb2d4903f2
commit bb09e8b2a9
5 changed files with 177 additions and 0 deletions

View File

@ -252,6 +252,8 @@ void kore_strlcpy(char *, const char *, size_t);
void kore_server_disconnect(struct connection *);
int kore_split_string(char *, char *, char **, size_t);
long long kore_strtonum(const char *, long long, long long, int *);
int kore_base64_encode(u_int8_t *, u_int32_t, char **);
int kore_base64_decode(char *, u_int8_t **, u_int32_t *);
void kore_domain_init(void);
int kore_domain_new(char *);
@ -282,6 +284,7 @@ int net_recv_expand(struct connection *c, struct netbuf *, size_t,
void net_send_queue(struct connection *, u_int8_t *, size_t, int,
struct netbuf **, int (*cb)(struct netbuf *));
void kore_buf_free(struct kore_buf *);
struct kore_buf *kore_buf_create(u_int32_t);
void kore_buf_append(struct kore_buf *, u_int8_t *, u_int32_t);
u_int8_t *kore_buf_release(struct kore_buf *, u_int32_t *);

View File

@ -54,6 +54,7 @@ domain 10.211.55.3 {
static /css/style.css serve_style_css
static / serve_index
static /intro.jpg serve_intro
static /b64test serve_b64test
}
#domain domain.com {

View File

@ -22,6 +22,19 @@
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 *);
void test_base64(u_int8_t *, u_int32_t, struct kore_buf *);
char *b64tests[] = {
"1234567890",
"One two three four five",
"Man",
"any carnal pleasure.",
"any carnal pleasure",
"any carnal pleas",
"I am a nobody, nobody is perfect, therefor I am.",
NULL
};
int
serve_style_css(struct http_request *req)
@ -76,3 +89,51 @@ serve_intro(struct http_request *req)
return (ret);
}
int
serve_b64test(struct http_request *req)
{
int i, ret;
u_int32_t len;
struct kore_buf *res;
u_int8_t *data;
res = kore_buf_create(1024);
for (i = 0; b64tests[i] != NULL; i++)
test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res);
data = kore_buf_release(res, &len);
http_response_header_add(req, "content-type", "text/plain");
ret = http_response(req, 200, data, len);
kore_mem_free(data);
return (ret);
}
void
test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res)
{
char *in;
u_int32_t len;
u_int8_t *out;
kore_buf_appendf(res, "test '%s'\n", src);
if (!kore_base64_encode(src, slen, &in)) {
kore_buf_appendf(res, "encoding '%s' failed\n", src);
} else {
kore_buf_appendf(res, "encoded: '%s'\n", in);
if (!kore_base64_decode(in, &out, &len)) {
kore_buf_appendf(res, "decoding failed\n");
} else {
kore_buf_appendf(res, "decoded: '%s'\n", out);
kore_mem_free(out);
}
kore_mem_free(in);
}
kore_buf_appendf(res, "\n");
}

View File

@ -88,3 +88,10 @@ kore_buf_release(struct kore_buf *buf, u_int32_t *len)
return (p);
}
void
kore_buf_free(struct kore_buf *buf)
{
free(buf->data);
free(buf);
}

View File

@ -35,6 +35,8 @@ static struct {
{ NULL, 0 },
};
static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void
kore_debug_internal(char *file, int line, const char *fmt, ...)
{
@ -244,6 +246,109 @@ kore_time_ms(void)
return (tv.tv_sec * 1000 + (tv.tv_usec / 1000));
}
int
kore_base64_encode(u_int8_t *data, u_int32_t len, char **out)
{
struct kore_buf *res;
u_int8_t n, *pdata;
int i, padding;
u_int32_t idx, b, plen;
if ((len % 3) != 0) {
padding = 3 - (len % 3);
plen = len + padding;
pdata = (u_int8_t *)kore_malloc(plen);
memcpy(pdata, data, len);
memset(pdata + len, 0, padding);
} else {
plen = len;
padding = 0;
pdata = data;
}
res = kore_buf_create(plen);
i = 2;
b = 0;
for (idx = 0; idx < plen; idx++) {
b |= (pdata[idx] << (i * 8));
if (i-- == 0) {
for (i = 3; i >= 0; i--) {
n = (b >> (6 * i)) & 0x3f;
if (n >= sizeof(b64table)) {
kore_debug("unable to encode %d", n);
kore_buf_free(res);
return (KORE_RESULT_ERROR);
}
if (idx >= len && i < padding)
break;
kore_buf_append(res,
(u_int8_t *)&(b64table[n]), 1);
}
b = 0;
i = 2;
}
}
for (i = 0; i < padding; i++)
kore_buf_append(res, (u_int8_t *)"=", 1);
if (pdata != data)
kore_mem_free(pdata);
pdata = kore_buf_release(res, &plen);
*out = kore_malloc(plen + 1);
kore_strlcpy(*out, (char *)pdata, plen + 1);
kore_mem_free(pdata);
return (KORE_RESULT_OK);
}
int
kore_base64_decode(char *in, u_int8_t **out, u_int32_t *olen)
{
int i;
struct kore_buf *res;
u_int8_t d, n, o;
u_int32_t b, len, idx;
i = 3;
b = 0;
len = strlen(in);
res = kore_buf_create(len);
for (idx = 0; idx < len; idx++) {
for (o = 0; o < sizeof(b64table); o++) {
if (b64table[o] == in[idx]) {
d = o;
break;
}
}
/* XXX - This could be bad? */
if (o == sizeof(b64table))
d = 0;
b |= (d & 0x3f) << (i * 6);
if (i-- == 0) {
for (i = 2; i >= 0; i--) {
n = (b >> (8 * i));
kore_buf_append(res, &n, 1);
}
b = 0;
i = 3;
}
}
*out = kore_buf_release(res, olen);
return (KORE_RESULT_OK);
}
void
fatal(const char *fmt, ...)
{