From 0089842c454e51367a10dd86856cca8884bd2f01 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 28 Aug 2016 00:37:50 -0400 Subject: add internal.h and te-parser.c --- Makefile | 4 +- env.c | 3 +- error.c | 3 +- fhp.c | 403 +----------------------------------------------------------- hash.c | 3 +- internal.h | 200 ++++++++++++++++++++++++++++++ te-parser.c | 203 ++++++++++++++++++++++++++++++ token.c | 3 +- 8 files changed, 410 insertions(+), 412 deletions(-) create mode 100644 internal.h create mode 100644 te-parser.c 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 -#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 -#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 -#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 -#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 +#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 -#include "fhp/fhp.h" +#include "internal.h" // // token functions -- cgit v1.2.3