summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--env.c3
-rw-r--r--error.c3
-rw-r--r--fhp.c403
-rw-r--r--hash.c3
-rw-r--r--internal.h200
-rw-r--r--te-parser.c203
-rw-r--r--token.c3
8 files changed, 410 insertions, 412 deletions
diff --git a/Makefile b/Makefile
index 32976d7..7878027 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
CC ?= cc
CFLAGS=-std=c99 -W -Wall -pedantic -O2 -Iinclude -fPIC
-OBJS=fhp.o hash.o error.o token.o env.o
+OBJS=fhp.o hash.o error.o token.o env.o te-parser.o
SONAME=libfhp.so
LIB=libfhp.so
@@ -22,5 +22,5 @@ $(LIB): $(OBJS)
$(TEST_APP): $(LIB) $(TEST_OBJS)
$(CC) -o $(TEST_APP) $(TEST_OBJS) $(TEST_LDFLAGS)
-%.o: %.c include/fhp/fhp.h
+%.o: %.c internal.h include/fhp/fhp.h
$(CC) -c $(CFLAGS) $<
diff --git a/env.c b/env.c
index 721d392..8994598 100644
--- a/env.c
+++ b/env.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
static char * const
fhp_strings[] = {
diff --git a/error.c b/error.c
index e88ab4f..3a5ea9c 100644
--- a/error.c
+++ b/error.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
//
// error functions
diff --git a/fhp.c b/fhp.c
index 917141d..a2ba7a2 100644
--- a/fhp.c
+++ b/fhp.c
@@ -1,405 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
-
-#define UNUSED(a) ((void) (a))
-
-#define CASE_ALNUM_CHARS \
- case '0': \
- case '1': \
- case '2': \
- case '3': \
- case '4': \
- case '5': \
- case '6': \
- case '7': \
- case '8': \
- case '9': \
- case 'a': \
- case 'b': \
- case 'c': \
- case 'd': \
- case 'e': \
- case 'f': \
- case 'g': \
- case 'h': \
- case 'i': \
- case 'j': \
- case 'k': \
- case 'l': \
- case 'm': \
- case 'n': \
- case 'o': \
- case 'p': \
- case 'q': \
- case 'r': \
- case 's': \
- case 't': \
- case 'u': \
- case 'v': \
- case 'w': \
- case 'x': \
- case 'y': \
- case 'z': \
- case 'A': \
- case 'B': \
- case 'C': \
- case 'D': \
- case 'E': \
- case 'F': \
- case 'G': \
- case 'H': \
- case 'I': \
- case 'J': \
- case 'K': \
- case 'L': \
- case 'M': \
- case 'N': \
- case 'O': \
- case 'P': \
- case 'Q': \
- case 'R': \
- case 'S': \
- case 'T': \
- case 'U': \
- case 'V': \
- case 'W': \
- case 'X': \
- case 'Y': \
- case 'Z':
-
-#define CASE_DIGIT_CHARS \
- case '0': \
- case '1': \
- case '2': \
- case '3': \
- case '4': \
- case '5': \
- case '6': \
- case '7': \
- case '8': \
- case '9':
-
-#define CASE_HEX_ALPHA_CHARS \
- case 'a': \
- case 'b': \
- case 'c': \
- case 'd': \
- case 'e': \
- case 'f': \
- case 'A': \
- case 'B': \
- case 'C': \
- case 'D': \
- case 'E': \
- case 'F':
-
-//
-// rfc7230, Appendix B
-// https://tools.ietf.org/html/rfc7230
-//
-// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
-// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
-// token = 1*tchar
-//
-#define CASE_TOKEN_CHARS \
- CASE_ALNUM_CHARS \
- case '!': \
- case '#': \
- case '$': \
- case '%': \
- case '&': \
- case '\'': \
- case '*': \
- case '+': \
- case '-': \
- case '.': \
- case '^': \
- case '_': \
- case '|': \
- case '~': \
-
-#define CASE_URL_CHARS \
- CASE_ALNUM_CHARS \
- case '!': \
- case '"': \
- case '#': \
- case '$': \
- case '&': \
- case '\'': \
- case '(': \
- case ')': \
- case '*': \
- case '+': \
- case ',': \
- case '-': \
- case '.': \
- case '/': \
- case ':': \
- case ';': \
- case '<': \
- case '=': \
- case '>': \
- case '?': \
- case '@': \
- case '[': \
- case '\\': \
- case ']': \
- case '^': \
- case '_': \
- case '`': \
- case '{': \
- case '|': \
- case '}': \
- case '~':
-
-#define CASE_VISUAL_CHARS \
- CASE_URL_CHARS \
- case '%':
-
-#define CASE_VERSION_CHARS \
- CASE_TOKEN_CHARS \
- case '/':
-
-#define CASE_TE_CHARS \
- CASE_ALNUM_CHARS \
- case '-':
-
-//
-// rfc7230, Appendix B
-// https://tools.ietf.org/html/rfc7230
-//
-// OWS = *( SP / HTAB )
-//
-#define CASE_OWS_CHARS \
- case ' ': \
- case '\t':
-
-//
-// strings
-//
-
-typedef enum {
- FHP_STR_GET,
- FHP_STR_POST,
- FHP_STR_HEAD,
- FHP_STR_PUT,
- FHP_STR_DELETE,
- FHP_STR_OPTIONS,
- FHP_STR_HTTP_10,
- FHP_STR_HTTP_11,
- FHP_STR_CONTENT_LENGTH,
- FHP_STR_TRANSFER_ENCODING,
- FHP_STR_GZIP,
- FHP_STR_X_GZIP,
- FHP_STR_DEFLATE,
- FHP_STR_X_DEFLATE,
- FHP_STR_COMPRESS,
- FHP_STR_X_COMPRESS,
- FHP_STR_CHUNKED,
- FHP_STR_LAST
-} fhp_str_t;
-
-//
-// transfer encoding buffer functions
-//
-
-static void
-fhp_te_parser_buf_flush(fhp_te_parser_t * const te) {
- te->buf_hash = fhp_lc_hash_push(te->buf_hash, te->buf, te->len);
- te->len = 0;
-}
-
-static void
-fhp_te_parser_buf_push(
- fhp_te_parser_t * const te,
- uint8_t byte
-) {
- // flush buffer (if necessary)
- if (te->len + 1 >= FHP_TE_MAX_BUF_SIZE)
- fhp_te_parser_buf_flush(te);
-
- // push to buffer
- te->buf[te->len] = byte;
- te->len++;
-}
-
-//
-// transfer encoding parser functions
-//
-
-static const fhp_te_parser_t FHP_DEFAULT_TE_PARSER = {
- .state = FHP_TE_STATE_INIT,
- .len = 0,
- .num_tes = 0,
- .err = FHP_OK,
-};
-
-fhp_err_t
-fhp_te_parser_init(fhp_te_parser_t * const te) {
- // init parser
- *te = FHP_DEFAULT_TE_PARSER;
-
- // return succes
- return FHP_OK;
-}
-
-static fhp_err_t
-fhp_te_parser_push_byte(
- fhp_te_parser_t * const te,
- uint8_t byte
-) {
-retry:
- switch (te->state) {
- case FHP_TE_STATE_INIT:
- // set state
- te->state = FHP_TE_STATE_SPACE;
- goto retry;
-
- break;
- case FHP_TE_STATE_NAME:
- switch (byte) {
- CASE_TE_CHARS
- // add to buffer
- fhp_te_parser_buf_push(te, byte);
-
- break;
- CASE_OWS_CHARS
- // flush buffer (if necessary)
- if (te->len > 0)
- fhp_te_parser_buf_flush(te);
-
- // check number of encodings
- if (te->num_tes + 1 >= FHP_TE_MAX_TES)
- return FHP_ERR_TOO_MANY_TES;
-
- // add to list of transfer encodings
- // FIXME: check length
- te->tes[te->num_tes] = te->buf_hash;
- te->num_tes++;
-
- // set state
- te->state = FHP_TE_STATE_IGNORE_UNTIL_COMMA;
-
- break;
- case ',':
- // flush buffer (if necessary)
- if (te->len > 0)
- fhp_te_parser_buf_flush(te);
-
- // check number of encodings
- if (te->num_tes + 1 >= FHP_TE_MAX_TES)
- return FHP_ERR_TOO_MANY_TES;
-
- // add to list of transfer encodings
- // FIXME: check length
- te->tes[te->num_tes] = te->buf_hash;
- te->num_tes++;
-
- // set state
- te->state = FHP_TE_STATE_SPACE;
-
- break;
- default:
- // invalid transfer encoding character
- return FHP_ERR_INVALID_CHAR_IN_TE_NAME;
- }
-
- break;
- case FHP_TE_STATE_IGNORE_UNTIL_COMMA:
- switch (byte) {
- case ',':
- // set state
- te->state = FHP_TE_STATE_SPACE;
-
- break;
- default:
- // do nothing (ignore)
- NULL;
- }
-
- break;
- case FHP_TE_STATE_SPACE:
- switch (byte) {
- CASE_OWS_CHARS
- // ignore leading spaces
- break;
- CASE_TE_CHARS
- // clear buffer, init hash
- te->len = 0;
- te->buf_hash = fhp_hash_init();
-
- // set state
- te->state = FHP_TE_STATE_NAME;
- goto retry;
-
- break;
- default:
- // return error
- return FHP_ERR_INVALID_CHAR_IN_TE;
- }
-
- break;
- case FHP_TE_STATE_ERROR:
- // return last error
- return te->err;
-
- break;
- case FHP_TE_STATE_DONE:
- // shouldn't be reached
- return FHP_ERR_TE_PARSER_DONE;
-
- break;
- default:
- // never reached
- return FHP_ERR_BAD_TE_STATE;
- }
-
- // return succes
- return FHP_OK;
-}
-
-fhp_err_t
-fhp_te_parser_push(
- fhp_te_parser_t *te,
- uint8_t * const buf,
- size_t len
-) {
- for (size_t i = 0; i < len; i++) {
- // push byte
- fhp_err_t err = fhp_te_parser_push_byte(te, buf[len]);
-
- // check error
- if (err != FHP_OK) {
- // cache error
- te->err = err;
-
- // set state
- te->state = FHP_TE_STATE_ERROR;
-
- // return error
- return err;
- }
- }
-
- // return succes
- return FHP_OK;
-}
-
-fhp_err_t
-fhp_te_parser_done(fhp_te_parser_t * const te) {
- uint8_t buf[1] = { 20 };
-
- // flush data, check for error
- fhp_err_t err = fhp_te_parser_push(te, buf, 1);
- if (err != FHP_OK)
- return err;
-
- // set state
- te->state = FHP_TE_STATE_DONE;
-
- // return success
- return FHP_OK;
-}
+#include "internal.h"
//
// context functions
diff --git a/hash.c b/hash.c
index deae792..c35590e 100644
--- a/hash.c
+++ b/hash.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
//
// hash functions (djb2)
diff --git a/internal.h b/internal.h
new file mode 100644
index 0000000..94caebd
--- /dev/null
+++ b/internal.h
@@ -0,0 +1,200 @@
+#include <string.h>
+#include "fhp/fhp.h"
+
+#define UNUSED(a) ((void) (a))
+
+#define CASE_ALNUM_CHARS \
+ case '0': \
+ case '1': \
+ case '2': \
+ case '3': \
+ case '4': \
+ case '5': \
+ case '6': \
+ case '7': \
+ case '8': \
+ case '9': \
+ case 'a': \
+ case 'b': \
+ case 'c': \
+ case 'd': \
+ case 'e': \
+ case 'f': \
+ case 'g': \
+ case 'h': \
+ case 'i': \
+ case 'j': \
+ case 'k': \
+ case 'l': \
+ case 'm': \
+ case 'n': \
+ case 'o': \
+ case 'p': \
+ case 'q': \
+ case 'r': \
+ case 's': \
+ case 't': \
+ case 'u': \
+ case 'v': \
+ case 'w': \
+ case 'x': \
+ case 'y': \
+ case 'z': \
+ case 'A': \
+ case 'B': \
+ case 'C': \
+ case 'D': \
+ case 'E': \
+ case 'F': \
+ case 'G': \
+ case 'H': \
+ case 'I': \
+ case 'J': \
+ case 'K': \
+ case 'L': \
+ case 'M': \
+ case 'N': \
+ case 'O': \
+ case 'P': \
+ case 'Q': \
+ case 'R': \
+ case 'S': \
+ case 'T': \
+ case 'U': \
+ case 'V': \
+ case 'W': \
+ case 'X': \
+ case 'Y': \
+ case 'Z':
+
+#define CASE_DIGIT_CHARS \
+ case '0': \
+ case '1': \
+ case '2': \
+ case '3': \
+ case '4': \
+ case '5': \
+ case '6': \
+ case '7': \
+ case '8': \
+ case '9':
+
+#define CASE_HEX_ALPHA_CHARS \
+ case 'a': \
+ case 'b': \
+ case 'c': \
+ case 'd': \
+ case 'e': \
+ case 'f': \
+ case 'A': \
+ case 'B': \
+ case 'C': \
+ case 'D': \
+ case 'E': \
+ case 'F':
+
+//
+// rfc7230, Appendix B
+// https://tools.ietf.org/html/rfc7230
+//
+// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+// token = 1*tchar
+//
+#define CASE_TOKEN_CHARS \
+ CASE_ALNUM_CHARS \
+ case '!': \
+ case '#': \
+ case '$': \
+ case '%': \
+ case '&': \
+ case '\'': \
+ case '*': \
+ case '+': \
+ case '-': \
+ case '.': \
+ case '^': \
+ case '_': \
+ case '|': \
+ case '~': \
+
+#define CASE_URL_CHARS \
+ CASE_ALNUM_CHARS \
+ case '!': \
+ case '"': \
+ case '#': \
+ case '$': \
+ case '&': \
+ case '\'': \
+ case '(': \
+ case ')': \
+ case '*': \
+ case '+': \
+ case ',': \
+ case '-': \
+ case '.': \
+ case '/': \
+ case ':': \
+ case ';': \
+ case '<': \
+ case '=': \
+ case '>': \
+ case '?': \
+ case '@': \
+ case '[': \
+ case '\\': \
+ case ']': \
+ case '^': \
+ case '_': \
+ case '`': \
+ case '{': \
+ case '|': \
+ case '}': \
+ case '~':
+
+#define CASE_VISUAL_CHARS \
+ CASE_URL_CHARS \
+ case '%':
+
+#define CASE_VERSION_CHARS \
+ CASE_TOKEN_CHARS \
+ case '/':
+
+#define CASE_TE_CHARS \
+ CASE_ALNUM_CHARS \
+ case '-':
+
+//
+// rfc7230, Appendix B
+// https://tools.ietf.org/html/rfc7230
+//
+// OWS = *( SP / HTAB )
+//
+#define CASE_OWS_CHARS \
+ case ' ': \
+ case '\t':
+
+//
+// strings
+//
+
+typedef enum {
+ FHP_STR_GET,
+ FHP_STR_POST,
+ FHP_STR_HEAD,
+ FHP_STR_PUT,
+ FHP_STR_DELETE,
+ FHP_STR_OPTIONS,
+ FHP_STR_HTTP_10,
+ FHP_STR_HTTP_11,
+ FHP_STR_CONTENT_LENGTH,
+ FHP_STR_TRANSFER_ENCODING,
+ FHP_STR_GZIP,
+ FHP_STR_X_GZIP,
+ FHP_STR_DEFLATE,
+ FHP_STR_X_DEFLATE,
+ FHP_STR_COMPRESS,
+ FHP_STR_X_COMPRESS,
+ FHP_STR_CHUNKED,
+ FHP_STR_LAST
+} fhp_str_t;
diff --git a/te-parser.c b/te-parser.c
new file mode 100644
index 0000000..507038b
--- /dev/null
+++ b/te-parser.c
@@ -0,0 +1,203 @@
+#include "internal.h"
+
+//
+// transfer encoding buffer functions
+//
+
+static void
+fhp_te_parser_buf_flush(fhp_te_parser_t * const te) {
+ te->buf_hash = fhp_lc_hash_push(te->buf_hash, te->buf, te->len);
+ te->len = 0;
+}
+
+static void
+fhp_te_parser_buf_push(
+ fhp_te_parser_t * const te,
+ uint8_t byte
+) {
+ // flush buffer (if necessary)
+ if (te->len + 1 >= FHP_TE_MAX_BUF_SIZE)
+ fhp_te_parser_buf_flush(te);
+
+ // push to buffer
+ te->buf[te->len] = byte;
+ te->len++;
+}
+
+//
+// transfer encoding parser functions
+//
+
+static const fhp_te_parser_t FHP_DEFAULT_TE_PARSER = {
+ .state = FHP_TE_STATE_INIT,
+ .len = 0,
+ .num_tes = 0,
+ .err = FHP_OK,
+};
+
+fhp_err_t
+fhp_te_parser_init(fhp_te_parser_t * const te) {
+ // init parser
+ *te = FHP_DEFAULT_TE_PARSER;
+
+ // return succes
+ return FHP_OK;
+}
+
+static fhp_err_t
+fhp_te_parser_push_byte(
+ fhp_te_parser_t * const te,
+ uint8_t byte
+) {
+retry:
+ switch (te->state) {
+ case FHP_TE_STATE_INIT:
+ // set state
+ te->state = FHP_TE_STATE_SPACE;
+ goto retry;
+
+ break;
+ case FHP_TE_STATE_NAME:
+ switch (byte) {
+ CASE_TE_CHARS
+ // add to buffer
+ fhp_te_parser_buf_push(te, byte);
+
+ break;
+ CASE_OWS_CHARS
+ // flush buffer (if necessary)
+ if (te->len > 0)
+ fhp_te_parser_buf_flush(te);
+
+ // check number of encodings
+ if (te->num_tes + 1 >= FHP_TE_MAX_TES)
+ return FHP_ERR_TOO_MANY_TES;
+
+ // add to list of transfer encodings
+ // FIXME: check length
+ te->tes[te->num_tes] = te->buf_hash;
+ te->num_tes++;
+
+ // set state
+ te->state = FHP_TE_STATE_IGNORE_UNTIL_COMMA;
+
+ break;
+ case ',':
+ // flush buffer (if necessary)
+ if (te->len > 0)
+ fhp_te_parser_buf_flush(te);
+
+ // check number of encodings
+ if (te->num_tes + 1 >= FHP_TE_MAX_TES)
+ return FHP_ERR_TOO_MANY_TES;
+
+ // add to list of transfer encodings
+ // FIXME: check length
+ te->tes[te->num_tes] = te->buf_hash;
+ te->num_tes++;
+
+ // set state
+ te->state = FHP_TE_STATE_SPACE;
+
+ break;
+ default:
+ // invalid transfer encoding character
+ return FHP_ERR_INVALID_CHAR_IN_TE_NAME;
+ }
+
+ break;
+ case FHP_TE_STATE_IGNORE_UNTIL_COMMA:
+ switch (byte) {
+ case ',':
+ // set state
+ te->state = FHP_TE_STATE_SPACE;
+
+ break;
+ default:
+ // do nothing (ignore)
+ NULL;
+ }
+
+ break;
+ case FHP_TE_STATE_SPACE:
+ switch (byte) {
+ CASE_OWS_CHARS
+ // ignore leading spaces
+ break;
+ CASE_TE_CHARS
+ // clear buffer, init hash
+ te->len = 0;
+ te->buf_hash = fhp_hash_init();
+
+ // set state
+ te->state = FHP_TE_STATE_NAME;
+ goto retry;
+
+ break;
+ default:
+ // return error
+ return FHP_ERR_INVALID_CHAR_IN_TE;
+ }
+
+ break;
+ case FHP_TE_STATE_ERROR:
+ // return last error
+ return te->err;
+
+ break;
+ case FHP_TE_STATE_DONE:
+ // shouldn't be reached
+ return FHP_ERR_TE_PARSER_DONE;
+
+ break;
+ default:
+ // never reached
+ return FHP_ERR_BAD_TE_STATE;
+ }
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_te_parser_push(
+ fhp_te_parser_t *te,
+ uint8_t * const buf,
+ size_t len
+) {
+ for (size_t i = 0; i < len; i++) {
+ // push byte
+ fhp_err_t err = fhp_te_parser_push_byte(te, buf[len]);
+
+ // check error
+ if (err != FHP_OK) {
+ // cache error
+ te->err = err;
+
+ // set state
+ te->state = FHP_TE_STATE_ERROR;
+
+ // return error
+ return err;
+ }
+ }
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_te_parser_done(fhp_te_parser_t * const te) {
+ uint8_t buf[1] = { 20 };
+
+ // flush data, check for error
+ fhp_err_t err = fhp_te_parser_push(te, buf, 1);
+ if (err != FHP_OK)
+ return err;
+
+ // set state
+ te->state = FHP_TE_STATE_DONE;
+
+ // return success
+ return FHP_OK;
+}
diff --git a/token.c b/token.c
index d32c952..4e5dbfc 100644
--- a/token.c
+++ b/token.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
//
// token functions