summaryrefslogtreecommitdiff
path: root/fhp.c
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2016-08-28 00:20:02 -0400
committerPaul Duncan <pabs@pablotron.org>2016-08-28 00:20:02 -0400
commit1bc717dc54b9964e7c62082b34d2d74e3daaa6a6 (patch)
treec528c5acdba586f9642ad9e96e454bcde16879ab /fhp.c
parentf0668928544479c030e05d7cfc87f0c392a6d065 (diff)
downloadlibfhp-1bc717dc54b9964e7c62082b34d2d74e3daaa6a6.tar.bz2
libfhp-1bc717dc54b9964e7c62082b34d2d74e3daaa6a6.zip
add te parser (not working)
Diffstat (limited to 'fhp.c')
-rw-r--r--fhp.c217
1 files changed, 214 insertions, 3 deletions
diff --git a/fhp.c b/fhp.c
index 44c20e4..fd1f746 100644
--- a/fhp.c
+++ b/fhp.c
@@ -160,6 +160,10 @@
CASE_TOKEN_CHARS \
case '/':
+#define CASE_TE_CHARS \
+ CASE_ALNUM_CHARS \
+ case '-':
+
//
// rfc7230, Appendix B
// https://tools.ietf.org/html/rfc7230
@@ -235,8 +239,13 @@ fhp_errors[] = {
"invalid character after carriage return",
"invalid character in HTTP header name",
"invalid error code",
- "invalid body type",
"buffer too small",
+ "invalid body type",
+ "too many transfer encodings",
+ "invalid character in transfer encoding name",
+ "invalid character in transfer encoding",
+ "bad transfer encoding state",
+ "transfer encoding parser already done",
};
fhp_err_t
@@ -392,10 +401,212 @@ fhp_get_default_env(void) {
}
//
+// 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;
+}
+
+//
// context functions
//
-static const fhp_t DEFAULT_CONTEXT = {
+static const fhp_t FHP_DEFAULT_CONTEXT = {
.state = FHP_STATE_INIT,
.user_data = NULL,
.cb = NULL,
@@ -416,7 +627,7 @@ fhp_init(
fhp_cb_t cb,
void * const user_data
) {
- *fhp = DEFAULT_CONTEXT;
+ *fhp = FHP_DEFAULT_CONTEXT;
fhp->env = env ? env : fhp_get_default_env();
fhp->user_data = user_data;
fhp->cb = cb;