#ifndef FHP_H_ #define FHP_H #include // for uint8_t #include // for size_t #include // for size_t // // hash functions (djb2) // (see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/) // uint32_t fhp_hash_init(void); uint32_t fhp_hash_push(uint32_t, uint8_t * const, size_t); uint32_t fhp_hash_string(char * const); uint32_t fhp_lc_hash_push(uint32_t, uint8_t * const, size_t); uint32_t fhp_lc_hash_string(char * const); // // error functions // typedef enum { FHP_OK, FHP_ERR_CB, FHP_ERR_BAD_STATE, FHP_ERR_INVALID_CHAR, FHP_ERR_INVALID_CHAR_IN_METHOD, FHP_ERR_INVALID_CHAR_IN_URL, FHP_ERR_INVALID_CHAR_IN_URL_PERCENT, FHP_ERR_INVALID_CHAR_IN_VERSION, FHP_ERR_INVALID_CHAR_AFTER_CR, FHP_ERR_INVALID_CHAR_IN_HEADER_NAME, FHP_ERR_INVALID_ERROR, FHP_ERR_BUFFER_TOO_SMALL, FHP_ERR_INVALID_BODY_TYPE, FHP_ERR_TOO_MANY_TES, FHP_ERR_INVALID_CHAR_IN_TE_NAME, FHP_ERR_INVALID_CHAR_IN_TE, FHP_ERR_BAD_TE_STATE, FHP_ERR_TE_PARSER_DONE, FHP_ERR_NULL_TE_BUF, FHP_ERR_SMALL_TE_BUF, FHP_ERR_LAST } fhp_err_t; fhp_err_t fhp_strerror(fhp_err_t, char * const, size_t); // // token functions // typedef enum { FHP_TOKEN_METHOD_START, FHP_TOKEN_METHOD_FRAGMENT, FHP_TOKEN_METHOD_END, FHP_TOKEN_METHOD_GET, FHP_TOKEN_METHOD_POST, FHP_TOKEN_METHOD_HEAD, FHP_TOKEN_METHOD_PUT, FHP_TOKEN_METHOD_DELETE, FHP_TOKEN_METHOD_OPTIONS, FHP_TOKEN_METHOD_OTHER, FHP_TOKEN_URL_START, FHP_TOKEN_URL_FRAGMENT, FHP_TOKEN_URL_END, FHP_TOKEN_VERSION_START, FHP_TOKEN_VERSION_FRAGMENT, FHP_TOKEN_VERSION_END, FHP_TOKEN_VERSION_HTTP_10, FHP_TOKEN_VERSION_HTTP_11, FHP_TOKEN_VERSION_OTHER, FHP_TOKEN_HEADER_NAME_START, FHP_TOKEN_HEADER_NAME_FRAGMENT, FHP_TOKEN_HEADER_NAME_END, FHP_TOKEN_HEADER_VALUE_START, FHP_TOKEN_HEADER_VALUE_FRAGMENT, FHP_TOKEN_HEADER_VALUE_END, FHP_TOKEN_HEADER_TRANSFER_ENCODING, FHP_TOKEN_HEADER_CONTENT_LENGTH, FHP_TOKEN_LAST } fhp_token_t; 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 // #define FHP_ENV_NUM_HASHES 6 typedef struct { uint32_t hashes[FHP_ENV_NUM_HASHES]; } fhp_env_t; void fhp_env_init(fhp_env_t * const env); fhp_env_t *fhp_get_default_env(void); // // transfer encoding parser functions // typedef enum { FHP_TE_STATE_INIT, FHP_TE_STATE_NAME, FHP_TE_STATE_IGNORE_UNTIL_COMMA, FHP_TE_STATE_SPACE, FHP_TE_STATE_ERROR, FHP_TE_STATE_DONE, FHP_TE_STATE_LAST } fhp_te_state_t; #define FHP_TE_MAX_BUF_SIZE 16 #define FHP_TE_MAX_TES 4 typedef struct { fhp_te_state_t state; uint8_t buf[FHP_TE_MAX_BUF_SIZE]; size_t len; uint32_t buf_hash; uint32_t tes[FHP_TE_MAX_TES]; size_t num_tes; fhp_err_t err; } fhp_te_parser_t; fhp_err_t fhp_te_parser_init(fhp_te_parser_t * const te); fhp_err_t fhp_te_parser_push(fhp_te_parser_t *, uint8_t * const, size_t); fhp_err_t fhp_te_parser_done(fhp_te_parser_t * const, size_t * const); fhp_err_t fhp_te_parser_get_tes(fhp_te_parser_t * const, uint32_t * const, size_t); // // context functions // typedef struct fhp_t_ fhp_t; typedef bool (*fhp_cb_t)( fhp_t * const, fhp_token_t, uint8_t * const, size_t ); typedef enum { FHP_STATE_INIT, FHP_STATE_ERROR, FHP_STATE_METHOD, FHP_STATE_METHOD_END, FHP_STATE_URL, FHP_STATE_URL_PERCENT, FHP_STATE_URL_PERCENT_LAST, FHP_STATE_URL_END, FHP_STATE_VERSION, FHP_STATE_VERSION_END, FHP_STATE_VERSION_END_CR, FHP_STATE_STATUS_END, FHP_STATE_STATUS_END_CR, FHP_STATE_HEADER_NAME, FHP_STATE_HEADER_NAME_END, FHP_STATE_HEADER_NAME_END_CR, FHP_STATE_HEADER_VALUE, FHP_STATE_HEADER_VALUE_END_CR, FHP_STATE_HEADER_VALUE_END, FHP_STATE_HEADERS_END, FHP_STATE_HEADERS_END_CR, FHP_STATE_LAST } fhp_state_t; typedef enum { FHP_HEADER_VALUE_PARSER_NONE, FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING, FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH, FHP_HEADER_VALUE_PARSER_LAST } fhp_header_value_parser_t; #define FHP_MAX_BUF_SIZE 1024 #define FHP_MAX_TRANSFER_ENCODINGS 4 struct fhp_t_ { // env pointer fhp_env_t *env; // opaque user data void *user_data; // current parser state fhp_state_t state; // user callback fhp_cb_t cb; // last error fhp_err_t err; // number of bytes read uint64_t ofs; // fragment data buffer uint8_t buf[FHP_MAX_BUF_SIZE]; size_t buf_len; // buffer hashing state bool is_hashing; uint32_t buf_hash; // cached http method and version fhp_token_t http_method, http_version; // hash of last header name uint32_t header_name_hash; // header value parser fhp_header_value_parser_t header_value_parser; union { fhp_te_parser_t te; } parsers; // 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; }; fhp_err_t fhp_init(fhp_t * const, fhp_env_t * const, fhp_cb_t, void * const); fhp_err_t fhp_push(fhp_t * const, uint8_t * const, size_t); fhp_env_t * fhp_get_env(fhp_t * const); void * fhp_get_user_data(fhp_t * const); #endif /* FHP_H */