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 --- te-parser.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 te-parser.c (limited to 'te-parser.c') 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; +} -- cgit v1.2.3