summaryrefslogtreecommitdiff
path: root/fhp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fhp.c')
-rw-r--r--fhp.c117
1 files changed, 93 insertions, 24 deletions
diff --git a/fhp.c b/fhp.c
index fdf344b..44c20e4 100644
--- a/fhp.c
+++ b/fhp.c
@@ -235,6 +235,7 @@ fhp_errors[] = {
"invalid character after carriage return",
"invalid character in HTTP header name",
"invalid error code",
+ "invalid body type",
"buffer too small",
};
@@ -343,6 +344,8 @@ fhp_strings[] = {
"x-gzip",
"deflate",
"x-deflate",
+ "compress",
+ "x-compress",
"chunked",
NULL
};
@@ -362,6 +365,8 @@ typedef enum {
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;
@@ -399,6 +404,9 @@ static const fhp_t DEFAULT_CONTEXT = {
.buf_len = 0,
.is_hashing = false,
.header_name_hash = 0,
+ .body_type = FHP_BODY_TYPE_NONE,
+ .content_length = 0,
+ .num_tes = 0,
};
fhp_err_t
@@ -452,7 +460,7 @@ fhp_buf_push(
uint8_t byte
) {
// flush buffer
- if (fhp->buf_len + 1 >= FHP_BUF_SIZE) {
+ if (fhp->buf_len + 1 >= FHP_MAX_BUF_SIZE) {
if (!fhp_buf_flush(fhp, token))
return false;
}
@@ -466,6 +474,77 @@ fhp_buf_push(
}
static fhp_err_t
+fhp_handle_method(fhp_t * const fhp) {
+ // get method token
+ fhp->http_method = FHP_TOKEN_METHOD_OTHER;
+ if (fhp->buf_hash == fhp->env->hashes[FHP_STR_GET]) {
+ fhp->http_method = FHP_TOKEN_METHOD_GET;
+ } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_POST]) {
+ fhp->http_method = FHP_TOKEN_METHOD_POST;
+ } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_HEAD]) {
+ fhp->http_method = FHP_TOKEN_METHOD_HEAD;
+ } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_PUT]) {
+ fhp->http_method = FHP_TOKEN_METHOD_PUT;
+ } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_DELETE]) {
+ fhp->http_method = FHP_TOKEN_METHOD_DELETE;
+ } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_OPTIONS]) {
+ fhp->http_method = FHP_TOKEN_METHOD_OPTIONS;
+ }
+
+ // send method token
+ if (!fhp->cb(fhp, fhp->http_method, 0, 0))
+ return FHP_ERR_CB;
+
+ // return success
+ return FHP_OK;
+}
+
+// FIXME: follow RFC7230 3.3.3
+// https://tools.ietf.org/html/rfc7230#section-3.3.3
+static fhp_err_t
+fhp_handle_header_name(fhp_t * const fhp) {
+ uint32_t hash = fhp->header_name_hash;
+
+ if (hash == fhp->env->hashes[FHP_STR_CONTENT_LENGTH]) {
+ switch (fhp->body_type) {
+ case FHP_BODY_TYPE_CONTENT_LENGTH:
+ // duplicate content-length, ignore first one
+ // FIXME: should print warning here
+ case FHP_BODY_TYPE_NONE:
+ fhp->body_type = FHP_BODY_TYPE_CONTENT_LENGTH;
+ break;
+ case FHP_BODY_TYPE_TRANSFER_ENCODING:
+ // ignore content-length
+ // FIXME: should print warnings
+ break;
+ default:
+ // never reached
+ return FHP_ERR_INVALID_BODY_TYPE;
+ }
+ } else if (hash == fhp->env->hashes[FHP_STR_TRANSFER_ENCODING]) {
+ switch (fhp->body_type) {
+ case FHP_BODY_TYPE_CONTENT_LENGTH:
+ // duplicate content-length, ignore first one
+ // FIXME: should print warning here
+ case FHP_BODY_TYPE_NONE:
+ fhp->body_type = FHP_BODY_TYPE_TRANSFER_ENCODING;
+ break;
+ case FHP_BODY_TYPE_TRANSFER_ENCODING:
+ // ignore content-length
+ // FIXME: should print warnings
+ break;
+ default:
+ // never reached
+ return FHP_ERR_INVALID_BODY_TYPE;
+ }
+ }
+
+ // return success
+ return FHP_OK;
+}
+
+
+static fhp_err_t
fhp_push_byte(
fhp_t * const fhp,
uint8_t byte
@@ -513,25 +592,10 @@ retry:
if (!fhp->cb(fhp, FHP_TOKEN_METHOD_END, 0, 0))
return FHP_ERR_CB;
- // get method token
- fhp->http_method = FHP_TOKEN_METHOD_OTHER;
- if (fhp->buf_hash == fhp->env->hashes[FHP_STR_GET]) {
- fhp->http_method = FHP_TOKEN_METHOD_GET;
- } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_POST]) {
- fhp->http_method = FHP_TOKEN_METHOD_POST;
- } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_HEAD]) {
- fhp->http_method = FHP_TOKEN_METHOD_HEAD;
- } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_PUT]) {
- fhp->http_method = FHP_TOKEN_METHOD_PUT;
- } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_DELETE]) {
- fhp->http_method = FHP_TOKEN_METHOD_DELETE;
- } else if (fhp->buf_hash == fhp->env->hashes[FHP_STR_OPTIONS]) {
- fhp->http_method = FHP_TOKEN_METHOD_OPTIONS;
- }
-
- // send method token
- if (!fhp->cb(fhp, fhp->http_method, 0, 0))
- return FHP_ERR_CB;
+ // handle method
+ fhp_err_t err = fhp_handle_method(fhp);
+ if (err != FHP_OK)
+ return err;
// set state
fhp->state = FHP_STATE_METHOD_END;
@@ -769,14 +833,19 @@ retry:
if (!fhp_buf_flush(fhp, FHP_TOKEN_HEADER_NAME_FRAGMENT))
return FHP_ERR_CB;
+ // disable buffer hashing and cache header name hash
+ fhp->is_hashing = false;
+ fhp->header_name_hash = fhp->buf_hash;
+
+ // handle header name
+ fhp_err_t err = fhp_handle_header_name(fhp);
+ if (err != FHP_OK)
+ return err;
+
// send end token
if (!fhp->cb(fhp, FHP_TOKEN_HEADER_NAME_END, 0, 0))
return FHP_ERR_CB;
- // disable buffer hashing
- fhp->is_hashing = false;
- fhp->header_name_hash = fhp->buf_hash;
-
// set state
fhp->state = FHP_STATE_HEADER_NAME_END;