diff options
Diffstat (limited to 'decoders/http/http_decoder_half.h')
| -rw-r--r-- | decoders/http/http_decoder_half.h | 263 |
1 files changed, 163 insertions, 100 deletions
diff --git a/decoders/http/http_decoder_half.h b/decoders/http/http_decoder_half.h index f525f78..6daf32c 100644 --- a/decoders/http/http_decoder_half.h +++ b/decoders/http/http_decoder_half.h @@ -1,109 +1,172 @@ #pragma once +#include <stdint.h> #include <stddef.h> #include "stellar/session.h" #include "stellar/http.h" -#include "http_content_decompress.h" -#include "http_decoder_result_queue.h" -#include <llhttp.h> +#include "llhttp.h" +#include "uthash/utarray.h" +#include "http_decoder_decompress.h" + +#ifdef __cplusplus +extern "C" +{ +#endif +#define HTTP_HEADER_FIELD_RESERVE_NUM (16) + +#define HTTP_HEADER_FIELD_NAME_HOST "Host" +#define HTTP_HEADER_FIELD_NAME_USER_AGENT "User-Agent" +#define HTTP_HEADER_FIELD_NAME_REFERER "Referer" +#define HTTP_HEADER_FIELD_NAME_COOKIE "Cookie" +#define HTTP_HEADER_FIELD_NAME_SET_COOKIE "Set-Cookie" +#define HTTP_HEADER_FIELD_NAME_CONTENT_TYPE "Content-Type" +#define HTTP_HEADER_FIELD_NAME_CONTENT_LENGTH "Content-Length" +#define HTTP_HEADER_FIELD_NAME_CONTENT_ENCODING "Content-Encoding" +#define HTTP_HEADER_FIELD_NAME_TRANSFER_ENCODING "Transfer-Encoding" + + enum http_event + { + __HTTP_EVENT_RESERVED = 0, + HTTP_EVENT_REQ_INIT = 1 << 1, + HTTP_EVENT_REQ_LINE = 1 << 2, + HTTP_EVENT_REQ_HDR = 1 << 3, + HTTP_EVENT_REQ_HDR_END = 1 << 4, + HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5, + HTTP_EVENT_REQ_BODY_DATA = 1 << 6, + HTTP_EVENT_REQ_BODY_END = 1 << 7, + HTTP_EVENT_REQ_END = 1 << 8, + + HTTP_EVENT_RES_INIT = 1 << 9, + HTTP_EVENT_RES_LINE = 1 << 10, + HTTP_EVENT_RES_HDR = 1 << 11, + HTTP_EVENT_RES_HDR_END = 1 << 12, + HTTP_EVENT_RES_BODY_BEGIN = 1 << 13, + HTTP_EVENT_RES_BODY_DATA = 1 << 14, + HTTP_EVENT_RES_BODY_END = 1 << 15, + HTTP_EVENT_RES_END = 1 << 16, + }; + + struct http_body + { + char *body; + size_t body_sz; + size_t offset; // accumulated + int is_finished; + }; #ifndef hstring #include <bits/types/struct_iovec.h> -typedef struct iovec hstring; + typedef struct iovec hstring; #endif -// only one http event is fired at a time -enum http_event -{ - HTTP_EVENT_REQ_INIT = 1 << 1, - HTTP_EVENT_REQ_LINE = 1 << 2, - HTTP_EVENT_REQ_HDR = 1 << 3, - HTTP_EVENT_REQ_HDR_END = 1 << 4, - HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5, - HTTP_EVENT_REQ_BODY_DATA = 1 << 6, - HTTP_EVENT_REQ_BODY_END = 1 << 7, - HTTP_EVENT_REQ_END = 1 << 8, - - HTTP_EVENT_RES_INIT = 1 << 9, - HTTP_EVENT_RES_LINE = 1 << 10, - HTTP_EVENT_RES_HDR = 1 << 11, - HTTP_EVENT_RES_HDR_END = 1 << 12, - HTTP_EVENT_RES_BODY_BEGIN = 1 << 13, - HTTP_EVENT_RES_BODY_DATA = 1 << 14, - HTTP_EVENT_RES_BODY_END = 1 << 15, - HTTP_EVENT_RES_END = 1 << 16, -}; - -struct http_event_context -{ - struct http_decoder_exdata *ref_httpd_ctx; - nmx_pool_t *ref_mempool; - struct session *ref_session; - struct http_decoder_result_queue *ref_queue; -}; - -struct http_decoder_half; -struct http_decoder_half_data; -struct http_decoder_env; - -typedef void http_event_cb(enum http_event event, struct http_decoder_half_data **data, - struct http_event_context *ev_ctx, void *httpd_plugin_env); - -struct http_decoder_half * -http_decoder_half_new(struct http_decoder_exdata *hd_ctx, nmx_pool_t *mempool, http_event_cb *event_cb, - enum llhttp_type http_type, int decompress_switch, struct http_decoder_env *httpd_env, long long start_seq); - -void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half); - -void http_decoder_half_reinit(struct http_decoder_half *half, - struct http_decoder_result_queue *queue, - nmx_pool_t *mempool, struct session *sess); - -int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len); - -long long http_decoder_half_trans_count(struct http_decoder_half *half); - -// http decoder half data API -struct http_decoder_half_data * -http_decoder_half_data_new(nmx_pool_t *mempool); - -void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_data *data); - -int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data, - struct http_request_line *line); - -int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data, - struct http_response_line *line); - -int http_decoder_half_data_get_header(const struct http_decoder_half_data *data, - const char *name, size_t name_len, struct http_header_field *hdr_res); - -int http_decoder_half_data_iter_header(struct http_decoder_half_data *data, - struct http_header_field *header); -int http_decoder_half_data_reset_header_iter(struct http_decoder_half_data *req_data); -int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data); - -int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len); - -int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len); -void http_half_get_lastest_decompress_buffer(struct http_decoder_half_data *data, hstring *decompress_body); -void http_half_decompress_buffer_free(struct http_decoder_half_data *data, hstring *decompress_body); -void http_decoder_half_data_dump(struct http_decoder_half *half); - -void http_decoder_get_host_feed_url(struct http_decoder_half *half); -void http_decoder_get_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool); -int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstring *url); -void http_decoder_join_url(struct http_decoder_half_data *hfdata, - nmx_pool_t *mempool, - const struct http_header_field *host_hdr); -int http_decoder_join_url_finally(struct http_event_context *ev_ctx, - struct http_decoder_half_data *hfdata, - nmx_pool_t *mempool); -int http_half_data_get_url(struct http_decoder_half_data *res_data, const char **url_val, size_t *url_len); -int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data); - -void http_half_data_update_commit_index(struct http_decoder_half_data *half_data); -void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata *exdata); -void http_half_update_state(struct http_decoder_half_data *hf_data, enum http_event state); -int http_half_data_get_total_parsed_header_count(struct http_decoder_half_data *half_data); -void http_half_get_max_transaction_seq(struct http_decoder_exdata *exdata, long long *max_req_seq, long long *max_res_seq); -enum http_content_encoding http_half_data_get_content_encoding(struct http_decoder_half_data *hf_data);
\ No newline at end of file + struct http_half_data + { + enum flow_type flow_dir; + uint32_t transaction_seq; // seq of this half flow, is last http_lalf->transaction_num value + union + { + struct http_request_line req_line; + struct http_status_line status_line; + }; + + /* headers */ + struct http_buffer *cached_header_buffer; // maybe null + hstring joint_url; // malloc, need be free + enum http_content_encoding content_encoding_type; + int transfer_encoding_is_chunked; // -1: not set, 0: false, 1: true + UT_array *ut_filed_array; // inner struct, need to transform to header->field_array + struct http_header header; + + /* body */ + struct http_body raw_body; + struct http_content_decompress *decompress; + struct http_body decompress_body; + }; + + struct http_half_parser + { + llhttp_t llhttp_parser; + llhttp_settings_t settings; + struct http_half *half_ref; // used in llhttp callback context to get flow + }; + + enum http_stage + { + HTTP_STAGE_INIT = 0, + HTTP_STAGE_PENDING = 1, /* body without Content-Length, no Chunk-Encoding */ + HTTP_STAGE_HEADER_PARTIAL = 2, + HTTP_STAGE_BODY = 3, + }; + + struct http_stage_shaper + { + enum http_stage stage; + char *data; + size_t data_len; + long long remain_content_length; + const char *headers_start; // the first header field name + const char *headers_end; // the last char of \r\n\r\n + struct http_buffer *headers_cache; /* ownership move to struct http_decoder_half_data when headers completed */ + }; + + struct http_half_buffer + { + int is_malloc; // need free + int ref_count; // +1 when push a new message + char *buffer; + size_t buffer_size; + }; + + enum http_half_llhttp_stage_type + { + LLHTTP_STAGE_MESSAGE_BEGIN = 0, + LLHTTP_STAGE_URI, + LLHTTP_STAGE_METHOD, + LLHTTP_STAGE_STATUS, + LLHTTP_STAGE_VERSION, + LLHTTP_STAGE_HEADER_FIELD, + LLHTTP_STAGE_HEADER_FIELD_COMPLETE, + LLHTTP_STAGE_HEADER_VALUE, + LLHTTP_STAGE_HEADER_VALUE_COMPLETE, + LLHTTP_STAGE_HEADERS_COMPLETE, + LLHTTP_STAGE_BODY, + LLHTTP_STAGE_MESSAGE_COMPLETE, + __LLHTTP_STAGE_MAX, + }; + + struct http_half_llhttp_stage + { + const char *first_header_name_ptr; + const char *last_header_value_complete_ptr; /* at + length + 4 \r\n\r\n) */ + const char *last_headers_complete_ptr; + enum http_half_llhttp_stage_type llhttp_last_stage; + uint8_t llhttp_cb_count[__LLHTTP_STAGE_MAX]; + }; + + struct http_half + { + struct session *sess_ref; + struct http *http_env_ref; + + uint32_t transaction_num; // accumulated of all flows in this session + enum http_event event; + // struct http_stage_shaper shaper; + + struct http_half_parser parser; + struct http_half_data *flow_data; // malloc when every transaction start, ownership move to message when message completed + + struct http_buffer *cached_header_buffer; + struct http_half_llhttp_stage half_stage; + }; + void http_half_free(struct http_half *half); + void http_half_data_free(struct http_half_data *half_data); + void http_flow_parser_init(struct http_half_parser *flow_parser, enum llhttp_type type); + void http_flow_body_decompress(struct http_half_data *flow_data, const char *zipdata, size_t zipdatalen); + void http_event_handler(struct http_half *half, enum http_event event, struct http *httpd_env); + int http_flow_stage_shaping(struct http_half *half, const char *newdata, size_t newdata_len); + int http_half_flow_process(struct http_half *half, const char *newdata, size_t newdata_len); + int http_get_header_field_count(struct http_half_data *flow_data); + void http_flow_append_header_filed(struct http_half_data *flow_data, const char *at, size_t length); + void http_flow_append_header_value(struct http_half_data *flow_data, const char *at, size_t length); +#ifdef __cplusplus +} +#endif
\ No newline at end of file |
