summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fhp.c117
-rw-r--r--include/fhp/fhp.h23
2 files changed, 114 insertions, 26 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;
diff --git a/include/fhp/fhp.h b/include/fhp/fhp.h
index 3337cbe..9d680a9 100644
--- a/include/fhp/fhp.h
+++ b/include/fhp/fhp.h
@@ -33,6 +33,7 @@ typedef enum {
FHP_ERR_INVALID_CHAR_IN_HEADER_NAME,
FHP_ERR_INVALID_ERROR,
FHP_ERR_BUFFER_TOO_SMALL,
+ FHP_ERR_INVALID_BODY_TYPE,
FHP_ERR_LAST
} fhp_err_t;
@@ -82,6 +83,13 @@ typedef enum {
fhp_err_t
fhp_strtoken(fhp_token_t, char * const, size_t);
+typedef enum {
+ FHP_BODY_TYPE_NONE,
+ FHP_BODY_TYPE_CONTENT_LENGTH,
+ FHP_BODY_TYPE_TRANSFER_ENCODING,
+ FHP_BODY_TYPE_LAST
+} fhp_body_type_t;
+
//
// env functions
//
@@ -133,7 +141,8 @@ typedef enum {
FHP_STATE_LAST
} fhp_state_t;
-#define FHP_BUF_SIZE 1024
+#define FHP_MAX_BUF_SIZE 1024
+#define FHP_MAX_TRANSFER_ENCODINGS 4
struct fhp_t_ {
// env pointer
@@ -155,7 +164,7 @@ struct fhp_t_ {
uint64_t ofs;
// fragment data buffer
- uint8_t buf[FHP_BUF_SIZE];
+ uint8_t buf[FHP_MAX_BUF_SIZE];
size_t buf_len;
// buffer hashing state
@@ -168,6 +177,16 @@ struct fhp_t_ {
// hash of last header name
uint32_t header_name_hash;
+ // request body type
+ fhp_body_type_t body_type;
+
+ // content length
+ uint64_t content_length;
+
+ // transfer encodings
+ uint32_t tes[FHP_MAX_TRANSFER_ENCODINGS];
+ size_t num_tes;
+
// state for url hex decoder
uint32_t hex;
};