summaryrefslogtreecommitdiff
path: root/fhp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fhp.c')
-rw-r--r--fhp.c216
1 files changed, 178 insertions, 38 deletions
diff --git a/fhp.c b/fhp.c
index a2ba7a2..6048b2b 100644
--- a/fhp.c
+++ b/fhp.c
@@ -1,4 +1,114 @@
#include "internal.h"
+#include <stdio.h>
+
+//
+// header value parser
+//
+
+static fhp_err_t
+fhp_header_value_parser_init(fhp_t * const fhp) {
+ uint32_t hash = fhp->header_name_hash;
+ fhp_header_value_parser_t parser = FHP_HEADER_VALUE_PARSER_NONE;
+ fhp_err_t err;
+
+ /* fprintf(
+ stderr,
+ "hashes: header = %u, env = %u, str = %u, str(lc) = %u\n",
+ hash,
+ fhp->env->hashes[FHP_STR_TRANSFER_ENCODING],
+ fhp_hash_string("Transfer-Encoding"),
+ fhp_lc_hash_string("Transfer-Encoding")
+ ); */
+
+ if (hash == fhp->env->hashes[FHP_STR_TRANSFER_ENCODING]) {
+ // set parser type
+ parser = FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING;
+
+ // init parser
+ if ((err = fhp_te_parser_init(&(fhp->parsers.te))) != FHP_OK)
+ return err;
+ } else if (hash == fhp->env->hashes[FHP_STR_CONTENT_LENGTH]) {
+ // set parser type
+ parser = FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH;
+ } else {
+ // set default parser type
+ parser = FHP_HEADER_VALUE_PARSER_NONE;
+ }
+
+ // set value parser
+ fhp->header_value_parser = parser;
+
+ // return success
+ return FHP_OK;
+}
+
+static fhp_err_t
+fhp_header_value_parser_push(
+ fhp_t * const fhp,
+ uint8_t * const buf,
+ size_t len
+) {
+ fhp_err_t r = FHP_OK;
+
+ switch (fhp->header_value_parser) {
+ case FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING:
+ r = fhp_te_parser_push(&(fhp->parsers.te), buf, len);
+ break;
+ case FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH:
+ // TODO
+ r = FHP_OK;
+ break;
+ default:
+ // do nothing
+ r = FHP_OK;
+ break;
+ }
+
+ // return result
+ return r;
+}
+
+static fhp_err_t
+fhp_header_value_parser_done(fhp_t * const fhp) {
+ fhp_err_t r = FHP_OK;
+
+ switch (fhp->header_value_parser) {
+ case FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING:
+ // finish parsing tes
+ if ((r = fhp_te_parser_done(&(fhp->parsers.te), &(fhp->num_tes))) != FHP_OK)
+ return r;
+
+ // check number of tes
+ if (fhp->num_tes > FHP_MAX_TRANSFER_ENCODINGS)
+ return FHP_ERR_TOO_MANY_TES;
+
+ // copy tes to context
+ if ((r = fhp_te_parser_get_tes(&(fhp->parsers.te), fhp->tes, FHP_MAX_TRANSFER_ENCODINGS)) != FHP_OK)
+ return r;
+
+ // notify callback
+ if (!fhp->cb(fhp, FHP_TOKEN_HEADER_TRANSFER_ENCODING, 0, 0))
+ return FHP_ERR_CB;
+
+ break;
+ case FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH:
+ // TODO
+ r = FHP_OK;
+
+ break;
+ default:
+ // do nothing
+ r = FHP_OK;
+
+ break;
+ }
+
+ // clear header value parser
+ fhp->header_value_parser = FHP_HEADER_VALUE_PARSER_NONE;
+
+ // return result
+ return r;
+}
//
// context functions
@@ -13,6 +123,7 @@ static const fhp_t FHP_DEFAULT_CONTEXT = {
.buf_len = 0,
.is_hashing = false,
.header_name_hash = 0,
+ .header_value_parser = FHP_HEADER_VALUE_PARSER_NONE,
.body_type = FHP_BODY_TYPE_NONE,
.content_length = 0,
.num_tes = 0,
@@ -40,7 +151,7 @@ fhp_buf_clear(fhp_t * const fhp) {
fhp->buf_len = 0;
}
-static bool
+static fhp_err_t
fhp_buf_flush(
fhp_t * const fhp,
fhp_token_t token
@@ -48,21 +159,26 @@ fhp_buf_flush(
if (fhp->buf_len > 0) {
// push data
if (!fhp->cb(fhp, token, fhp->buf, fhp->buf_len))
- return false;
+ return FHP_ERR_CB;
// update buffer hash
if (fhp->is_hashing)
- fhp->buf_hash = fhp_hash_push(fhp->buf_hash, fhp->buf, fhp->buf_len);
+ fhp->buf_hash = fhp_lc_hash_push(fhp->buf_hash, fhp->buf, fhp->buf_len);
+
+ // push to header value parser
+ fhp_err_t err;
+ if ((err = fhp_header_value_parser_push(fhp, fhp->buf, fhp->buf_len)) != FHP_OK)
+ return err;
// clear buffer
fhp_buf_clear(fhp);
}
// return success
- return true;
+ return FHP_OK;
}
-static bool
+static fhp_err_t
fhp_buf_push(
fhp_t * const fhp,
fhp_token_t token,
@@ -70,8 +186,9 @@ fhp_buf_push(
) {
// flush buffer
if (fhp->buf_len + 1 >= FHP_MAX_BUF_SIZE) {
- if (!fhp_buf_flush(fhp, token))
- return false;
+ fhp_err_t err;
+ if ((err = fhp_buf_flush(fhp, token)) != FHP_OK)
+ return err;
}
// append to buffer
@@ -79,7 +196,7 @@ fhp_buf_push(
fhp->buf_len++;
// return success
- return true;
+ return FHP_OK;
}
static fhp_err_t
@@ -158,6 +275,8 @@ fhp_push_byte(
fhp_t * const fhp,
uint8_t byte
) {
+ fhp_err_t err;
+
retry:
switch (fhp->state) {
case FHP_STATE_INIT:
@@ -185,14 +304,14 @@ retry:
switch (byte) {
CASE_TOKEN_CHARS
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_METHOD_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_METHOD_FRAGMENT, byte)) != FHP_OK)
+ return err;
break;
case ' ':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_METHOD_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_METHOD_FRAGMENT)) != FHP_OK)
+ return err;
// disable buffer hashing
fhp->is_hashing = false;
@@ -237,8 +356,8 @@ retry:
switch (byte) {
case ' ':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_URL_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_URL_FRAGMENT)) != FHP_OK)
+ return err;
// send end token
if (!fhp->cb(fhp, FHP_TOKEN_URL_END, 0, 0))
@@ -256,8 +375,8 @@ retry:
break;
CASE_URL_CHARS
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_URL_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_URL_FRAGMENT, byte)) != FHP_OK)
+ return err;
}
break;
@@ -291,8 +410,8 @@ retry:
}
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_URL_FRAGMENT, fhp->hex))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_URL_FRAGMENT, fhp->hex)) != FHP_OK)
+ return err;
// set state
fhp->state = FHP_STATE_URL;
@@ -322,8 +441,8 @@ retry:
case '\r':
case '\n':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_VERSION_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_VERSION_FRAGMENT)) != FHP_OK)
+ return err;
// send end token
if (!fhp->cb(fhp, FHP_TOKEN_VERSION_END, 0, 0))
@@ -351,8 +470,8 @@ retry:
break;
CASE_VERSION_CHARS
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_VERSION_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_VERSION_FRAGMENT, byte)) != FHP_OK)
+ return err;
break;
default:
@@ -433,14 +552,14 @@ retry:
switch (byte) {
CASE_TOKEN_CHARS
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT, byte)) != FHP_OK)
+ return err;
break;
case ':':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT)) != FHP_OK)
+ return err;
// disable buffer hashing and cache header name hash
fhp->is_hashing = false;
@@ -475,6 +594,11 @@ retry:
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_VALUE_START, 0, 0))
return FHP_ERR_CB;
+ // init header value parser
+ fhp_err_t err;
+ if ((err = fhp_header_value_parser_init(fhp)) != FHP_OK)
+ return err;
+
// set state
fhp->state = FHP_STATE_HEADER_VALUE;
goto retry;
@@ -496,8 +620,8 @@ retry:
// FIXME: need more limits on valid octets
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT, byte)) != FHP_OK)
+ return err;
break;
}
@@ -521,8 +645,8 @@ retry:
// add space to buffer
// folding to ' ', as per RFC7230 3.2.4
// https://tools.ietf.org/html/rfc7230#section-3.2.4
- if (!fhp_buf_push(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT, ' '))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT, ' ')) != FHP_OK)
+ return err;
// set state
fhp->state = FHP_STATE_HEADER_VALUE;
@@ -530,20 +654,28 @@ retry:
break;
CASE_TOKEN_CHARS
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT)) != FHP_OK)
+ return err;
// end header value
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_VALUE_END, 0, 0))
return FHP_ERR_CB;
+ // end header value parser
+ if ((err = fhp_header_value_parser_done(fhp)) != FHP_OK)
+ return err;
+
// send start token
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_NAME_START, 0, 0))
return FHP_ERR_CB;
+ // enable buffer hashing
+ fhp->is_hashing = true;
+ fhp->buf_hash = fhp_hash_init();
+
// add to buffer
- if (!fhp_buf_push(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT, byte))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_push(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT, byte)) != FHP_OK)
+ return err;
// set state
fhp->state = FHP_STATE_HEADER_NAME;
@@ -551,26 +683,34 @@ retry:
break;
case '\r':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT)) != FHP_OK)
+ return err;
// end header value
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_VALUE_END, 0, 0))
return FHP_ERR_CB;
+ // end header value parser
+ if ((err = fhp_header_value_parser_done(fhp)) != FHP_OK)
+ return err;
+
// set state
fhp->state = FHP_STATE_HEADERS_END_CR;
break;
case '\n':
// flush buffer
- if (!fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT))
- return FHP_ERR_CB;
+ if ((err = fhp_buf_flush(fhp, FHP_TOKEN_HEADER_VALUE_FRAGMENT)) != FHP_OK)
+ return err;
// end header value
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_VALUE_END, 0, 0))
return FHP_ERR_CB;
+ // end header value parser
+ if ((err = fhp_header_value_parser_done(fhp)) != FHP_OK)
+ return err;
+
// set state
fhp->state = FHP_STATE_HEADERS_END;