Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b

Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/http/chunk.c b/src/http/chunk.c
new file mode 100644
index 0000000..ec772f0
--- /dev/null
+++ b/src/http/chunk.c
@@ -0,0 +1,111 @@
+/**
+ * @file http/chunk.c Chunked Transfer Encoding
+ *
+ * Copyright (C) 2011 Creytiv.com
+ */
+
+#include <re_types.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include "http.h"
+
+
+static int decode_chunk_size(struct http_chunk *chunk, struct mbuf *mb)
+{
+	while (mbuf_get_left(mb)) {
+
+		char ch = (char)mbuf_read_u8(mb);
+		uint8_t c;
+
+		if (ch == '\n') {
+			if (chunk->digit) {
+				chunk->digit = false;
+				chunk->param = false;
+
+				return 0;
+			}
+			else
+				continue;
+		}
+
+		if (chunk->param)
+			continue;
+
+		if ('0' <= ch && ch <= '9')
+			c = ch - '0';
+		else if ('A' <= ch && ch <= 'F')
+			c = ch - 'A' + 10;
+		else if ('a' <= ch && ch <= 'f')
+			c = ch - 'a' + 10;
+		else if (ch == '\r' || ch == ' ' || ch == '\t')
+			continue;
+		else if (ch == ';' && chunk->digit) {
+			chunk->param = true;
+			continue;
+		}
+		else
+			return EPROTO;
+
+		chunk->digit = true;
+
+		chunk->size <<= 4;
+		chunk->size += c;
+	}
+
+	return ENODATA;
+}
+
+
+static int decode_trailer(struct http_chunk *chunk, struct mbuf *mb)
+{
+	while (mbuf_get_left(mb)) {
+
+		char ch = (char)mbuf_read_u8(mb);
+
+		if (ch == '\n') {
+			if (++chunk->lf >= 2)
+				return 0;
+		}
+		else if (ch != '\r')
+			chunk->lf = 0;
+	}
+
+	return ENODATA;
+}
+
+
+int http_chunk_decode(struct http_chunk *chunk, struct mbuf *mb, size_t *size)
+{
+	int err;
+
+	if (!chunk || !mb || !size)
+		return EINVAL;
+
+	if (chunk->trailer) {
+		err = decode_trailer(chunk, mb);
+		if (err)
+			return err;
+
+		*size = 0;
+
+		return 0;
+	}
+
+	err = decode_chunk_size(chunk, mb);
+	if (err)
+		return err;
+
+	if (chunk->size == 0) {
+		chunk->trailer = true;
+		chunk->lf = 1;
+
+		err = decode_trailer(chunk, mb);
+		if (err)
+			return err;
+	}
+
+	*size = chunk->size;
+	chunk->size = 0;
+
+	return 0;
+}