commit bb09e8b2a9b748598207220ed5fd8c4ba4b12cd7
parent bb2d4903f25f9bb1b2541b90f9139217dc6b007d
Author: Joris Vink <joris@coders.se>
Date: Wed, 10 Jul 2013 15:00:53 +0200
add base64 encoder/decoder in prep for http/2.0 and websockets
Diffstat:
5 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/includes/kore.h b/includes/kore.h
@@ -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 *);
diff --git a/modules/example/module.conf b/modules/example/module.conf
@@ -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 {
diff --git a/modules/example/src/example.c b/modules/example/src/example.c
@@ -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");
+}
diff --git a/src/buf.c b/src/buf.c
@@ -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);
+}
diff --git a/src/utils.c b/src/utils.c
@@ -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, ...)
{