diff options
| author | lijia <[email protected]> | 2024-09-02 19:16:34 +0800 |
|---|---|---|
| committer | lijia <[email protected]> | 2024-09-05 15:53:54 +0800 |
| commit | 28bc857231d14f67e46e1fd0433916064a8e9dbc (patch) | |
| tree | 660c33b024152fe61bb2492171e67b69a6361c67 /decoders/http | |
| parent | e05b3b13d531006f2c7801988dea436aa613a44e (diff) | |
http push line and all headers togetherdev-http-push-headers-together
Diffstat (limited to 'decoders/http')
| -rw-r--r-- | decoders/http/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | decoders/http/http_decoder.c | 354 | ||||
| -rw-r--r-- | decoders/http/http_decoder_half.c | 1045 | ||||
| -rw-r--r-- | decoders/http/http_decoder_half.h | 25 | ||||
| -rw-r--r-- | decoders/http/http_decoder_private.h | 1 | ||||
| -rw-r--r-- | decoders/http/http_decoder_result_queue.c | 18 | ||||
| -rw-r--r-- | decoders/http/http_decoder_string.c | 289 | ||||
| -rw-r--r-- | decoders/http/http_decoder_string.h | 73 | ||||
| -rw-r--r-- | decoders/http/http_decoder_table.c | 579 | ||||
| -rw-r--r-- | decoders/http/http_decoder_table.h | 79 | ||||
| -rw-r--r-- | decoders/http/http_decoder_tunnel.c | 13 | ||||
| -rw-r--r-- | decoders/http/http_decoder_utils.c | 153 | ||||
| -rw-r--r-- | decoders/http/http_decoder_utils.h | 22 | ||||
| -rw-r--r-- | decoders/http/version.map | 1 |
14 files changed, 785 insertions, 1870 deletions
diff --git a/decoders/http/CMakeLists.txt b/decoders/http/CMakeLists.txt index c242afe..0c7511e 100644 --- a/decoders/http/CMakeLists.txt +++ b/decoders/http/CMakeLists.txt @@ -1,7 +1,6 @@ include_directories(${CMAKE_SOURCE_DIR}/deps) -set(HTTP_SRC http_decoder.c http_decoder_utils.c http_decoder_half.c - http_decoder_table.c http_decoder_string.c http_content_decompress.c +set(HTTP_SRC http_decoder.c http_decoder_utils.c http_decoder_half.c http_content_decompress.c http_decoder_result_queue.c http_decoder_stat.c http_decoder_tunnel.c) add_library(http STATIC ${HTTP_SRC}) diff --git a/decoders/http/http_decoder.c b/decoders/http/http_decoder.c index 5e2db72..a812f80 100644 --- a/decoders/http/http_decoder.c +++ b/decoders/http/http_decoder.c @@ -39,7 +39,7 @@ struct http_message *http_body_message_new(enum http_message_type type, struct h return msg; } -static void http_message_decompress_buffer_free(struct http_message *msg) +static void http_msg_decompress_buffer_free(struct http_message *msg) { struct http_decoder_half_data *ref_data = NULL; if (HTTP_MESSAGE_REQ_BODY_START == msg->type || HTTP_MESSAGE_REQ_BODY == msg->type || HTTP_MESSAGE_REQ_BODY_END == msg->type) @@ -56,11 +56,29 @@ static void http_message_decompress_buffer_free(struct http_message *msg) } } +static void http_msg_line_headers_free(struct http_message *msg) +{ + struct http_decoder_half_data *ref_data = NULL; + if (HTTP_MESSAGE_REQ_LINE_HEADERS == msg->type) + { + ref_data = msg->ref_queue->array[msg->queue_index].req_data; + } + else if (HTTP_MESSAGE_RES_LINE_HEADERS == msg->type) + { + ref_data = msg->ref_queue->array[msg->queue_index].res_data; + } + if (ref_data != NULL) + { + http_half_line_headers_free(ref_data); + } +} + static void http_message_free(void *http_msg, void *cb_arg) { if (http_msg) { - http_message_decompress_buffer_free((struct http_message *)http_msg); + http_msg_decompress_buffer_free((struct http_message *)http_msg); + http_msg_line_headers_free((struct http_message *)http_msg); FREE(http_msg); } } @@ -110,11 +128,10 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d half_data = NULL; } - half_data = http_decoder_half_data_new(mempool); + half_data = http_decoder_half_data_new(mempool, FLOW_TYPE_C2S); ret = http_decoder_result_queue_push_req(queue, half_data); if (ret < 0) { - fprintf(stderr, "http_decoder_result_queue_push req failed."); http_decoder_half_data_free(mempool, half_data); half_data = NULL; } @@ -125,38 +142,17 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_TRANSACTION_NEW, 1); break; - case HTTP_EVENT_REQ_LINE: - msg = http_message_new(HTTP_MESSAGE_REQ_LINE, queue, queue_idx, HTTP_REQUEST); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - if (httpd_tunnel_identify(httpd_env, FLOW_TYPE_C2S, half_data)) - { - exdata->tunnel_state = HTTP_TUN_C2S_HDR_START; - // http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTPD_STAT_TUNNEL, 1); - } - if (httpd_is_tunnel_session(httpd_env, exdata)) - { - http_decoder_get_url(half_data, mempool); - } - break; - case HTTP_EVENT_REQ_HDR: - msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx, HTTP_REQUEST); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - break; + case HTTP_EVENT_REQ_HDR_END: + { - http_decoder_join_url_finally(ev_ctx, half_data, mempool); + http_parse_headers_finally(ev_ctx, half_data, mempool); /* maybe some parsed headers in buffer, but has not pushed to plugins yet */ - - if (http_decoder_half_data_has_parsed_header(half_data)) { - msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx, HTTP_REQUEST); + msg = http_message_new(HTTP_MESSAGE_REQ_LINE_HEADERS, queue, queue_idx, HTTP_REQUEST); session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); } - http_half_data_update_commit_index(half_data); - msg = http_message_new(HTTP_MESSAGE_REQ_HEADER_END, queue, queue_idx, HTTP_REQUEST); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - - int tot_c2s_headers = http_half_data_get_total_parsed_header_count(half_data); + int tot_c2s_headers = http_half_get_header_count(half_data); http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_HEADERS, tot_c2s_headers); const char *tmp_url = NULL; @@ -171,15 +167,14 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d break; case HTTP_EVENT_REQ_BODY_DATA: { - hstring raw_body = {}; + hstring *raw_body = http_half_get_raw_body(half_data); hstring decompress_body = {}; - http_decoder_half_data_get_raw_body(half_data, (const char **)&raw_body.iov_base, &raw_body.iov_len); http_half_get_lastest_decompress_buffer(half_data, &decompress_body); - msg = http_body_message_new(HTTP_MESSAGE_REQ_BODY, queue, queue_idx, HTTP_REQUEST, &raw_body, &decompress_body); + msg = http_body_message_new(HTTP_MESSAGE_REQ_BODY, queue, queue_idx, HTTP_REQUEST, raw_body, &decompress_body); session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); if (decompress_body.iov_base != NULL) { - http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_ZIP_BYTES, raw_body.iov_len); + http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_ZIP_BYTES, raw_body->iov_len); http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_UNZIP_BYTES, decompress_body.iov_len); } } @@ -237,11 +232,10 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d half_data = NULL; } - half_data = http_decoder_half_data_new(mempool); + half_data = http_decoder_half_data_new(mempool, FLOW_TYPE_S2C); ret = http_decoder_result_queue_push_res(queue, half_data); if (ret < 0) { - fprintf(stderr, "http_decoder_result_queue_push res failed."); http_decoder_half_data_free(mempool, half_data); half_data = NULL; } @@ -256,37 +250,18 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d } } break; - case HTTP_EVENT_RES_LINE: - msg = http_message_new(HTTP_MESSAGE_RES_LINE, queue, queue_idx, HTTP_RESPONSE); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - if (httpd_tunnel_identify(httpd_env, FLOW_TYPE_S2C, half_data)) - { - exdata->tunnel_state = HTTP_TUN_S2C_START; - } - else - { - // connect response fail, reset tunnel_state - exdata->tunnel_state = HTTP_TUN_NON; - } - break; - case HTTP_EVENT_RES_HDR: - msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx, HTTP_RESPONSE); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - break; + case HTTP_EVENT_RES_HDR_END: + { + http_parse_headers_finally(ev_ctx, half_data, mempool); /* maybe some header in table buffer but has not pushed to plugins */ half_data = http_decoder_result_queue_peek_res(queue); - if (http_decoder_half_data_has_parsed_header(half_data)) { - msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx, HTTP_RESPONSE); + msg = http_message_new(HTTP_MESSAGE_RES_LINE_HEADERS, queue, queue_idx, HTTP_RESPONSE); session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); } - http_half_data_update_commit_index(half_data); - msg = http_message_new(HTTP_MESSAGE_RES_HEADER_END, queue, queue_idx, HTTP_RESPONSE); - session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); - - int tot_s2c_headers = http_half_data_get_total_parsed_header_count(half_data); + int tot_s2c_headers = http_half_get_header_count(half_data); http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_HEADERS, tot_s2c_headers); if (httpd_is_tunnel_session(httpd_env, exdata)) @@ -303,15 +278,14 @@ static void http_event_handler(enum http_event event, struct http_decoder_half_d break; case HTTP_EVENT_RES_BODY_DATA: { - hstring raw_body = {}; - http_decoder_half_data_get_raw_body(half_data, (const char **)&raw_body.iov_base, &raw_body.iov_len); + hstring *raw_body = http_half_get_raw_body(half_data); hstring decompress_body = {}; http_half_get_lastest_decompress_buffer(half_data, &decompress_body); - msg = http_body_message_new(HTTP_MESSAGE_RES_BODY, queue, queue_idx, HTTP_RESPONSE, &raw_body, &decompress_body); + msg = http_body_message_new(HTTP_MESSAGE_RES_BODY, queue, queue_idx, HTTP_RESPONSE, raw_body, &decompress_body); session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg); if (decompress_body.iov_base != NULL) { - http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_ZIP_BYTES, raw_body.iov_len); + http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_ZIP_BYTES, raw_body->iov_len); http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_UNZIP_BYTES, decompress_body.iov_len); } } @@ -457,8 +431,7 @@ static int load_http_decoder_config(const char *cfg_path, FILE *fp = fopen(cfg_path, "r"); if (NULL == fp) { - fprintf(stderr, "[%s:%d]Can't open config file:%s", - __FUNCTION__, __LINE__, cfg_path); + fprintf(stderr, "[%s]Can't open config file:%s", __FUNCTION__, cfg_path); return -1; } @@ -471,8 +444,7 @@ static int load_http_decoder_config(const char *cfg_path, toml_table_t *basic_sec_tbl = toml_table_in(root, "basic"); if (NULL == basic_sec_tbl) { - fprintf(stderr, "[%s:%d]config file:%s has no key: [basic]", - __FUNCTION__, __LINE__, cfg_path); + fprintf(stderr, "[%s]config file:%s has no key: [basic]", __FUNCTION__, cfg_path); toml_free(root); return -1; } @@ -537,67 +509,6 @@ static int load_http_decoder_config(const char *cfg_path, return ret; } -static int http_msg_get_request_header(const struct http_message *msg, const char *name, size_t name_len, - struct http_header_field *hdr_result) -{ - const struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - return http_decoder_half_data_get_header(req_data, name, name_len, hdr_result); -} - -static int http_msg_get_response_header(const struct http_message *msg, const char *name, size_t name_len, - struct http_header_field *hdr_result) -{ - const struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - return http_decoder_half_data_get_header(res_data, name, name_len, hdr_result); -} - -static int http_msg_request_header_next(const struct http_message *msg, - struct http_header_field *hdr) -{ - const struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - return http_decoder_half_data_iter_header((struct http_decoder_half_data *)req_data, hdr); -} - -static int http_msg_response_header_next(const struct http_message *msg, struct http_header_field *hdr) -{ - const struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - return http_decoder_half_data_iter_header((struct http_decoder_half_data *)res_data, hdr); -} - -#if 0 -static int http_msg_get_request_raw_body(const struct http_message *msg, hstring *body) -{ - const struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - return http_decoder_half_data_get_raw_body(req_data, body); -} - -static int http_msg_get_response_raw_body(const struct http_message *msg, hstring *body) -{ - const struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - return http_decoder_half_data_get_raw_body(res_data, body); -} - -static int http_msg_get_request_decompress_body(const struct http_message *msg, hstring *body) -{ - const struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - return http_decoder_half_data_get_decompress_body(req_data, body); -} - -static int http_msg_get_response_decompress_body(const struct http_message *msg, hstring *body) -{ - const struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - return http_decoder_half_data_get_decompress_body(res_data, body); -} -#endif - static struct http_decoder_exdata *httpd_session_exdata_new(struct session *sess, struct http_decoder_env *httpd_env, long long req_start_seq, long long res_start_seq) { @@ -688,6 +599,7 @@ extern "C" { http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_STAT_PARSE_ERR, 1); stellar_session_plugin_dettach_current_session(sess); + return; } } @@ -920,132 +832,84 @@ extern "C" return msg->type; } - void http_message_get0_request_line(const struct http_message *msg, - struct http_request_line *line) + const struct http_request_line *http_message_get0_request_line(const struct http_message *msg) { - if (unlikely(NULL == msg || msg->type != HTTP_MESSAGE_REQ_LINE)) + if (unlikely(NULL == msg || (msg->type != HTTP_MESSAGE_REQ_LINE_HEADERS))) { - if (line) - { - line->method = NULL; - line->uri = NULL; - line->version = NULL; - } - return; + return NULL; } assert(msg->ref_queue); assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; + struct http_decoder_half_data *req_data = msg->ref_queue->array[msg->queue_index].req_data; - http_decoder_half_data_get_request_line(req_data, line); + return http_decoder_half_data_get_request_line(req_data); } - void http_message_get0_response_line(const struct http_message *msg, - struct http_response_line *line) + const struct http_response_line *http_message_get0_response_line(const struct http_message *msg) { - if (unlikely(NULL == msg || msg->type != HTTP_MESSAGE_RES_LINE)) + if (unlikely(NULL == msg || (msg->type != HTTP_MESSAGE_RES_LINE_HEADERS))) { - if (line) - { - line->version = NULL; - line->status = NULL; - } - return; + return NULL; } assert(msg->ref_queue); assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - - http_decoder_half_data_get_response_line(res_data, line); + struct http_decoder_half_data *res_data = msg->ref_queue->array[msg->queue_index].res_data; + return http_decoder_half_data_get_response_line(res_data); } - void http_message_get0_header(const struct http_message *msg, const char *name, size_t name_len, - struct http_header_field *hdr_result) + const struct http_header_field *http_message_get0_header(const struct http_message *msg, const char *field_name, size_t field_name_len) + // void http_message_get0_header(const struct http_message *msg, const char *name, size_t name_len, struct http_header_field *hdr_result) { - int ret = -1; - if (unlikely(NULL == msg || NULL == name || 0 == name_len)) + if (unlikely(NULL == msg || NULL == field_name || 0 == field_name_len)) { - goto fail; + return NULL; } assert(msg->ref_queue); assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - if (HTTP_MESSAGE_REQ_HEADER == msg->type) + const struct http_decoder_half_data *half_data = NULL; + const struct http_header_field *expect_header = NULL; + if (HTTP_MESSAGE_REQ_LINE_HEADERS == msg->type) { - ret = http_msg_get_request_header(msg, name, name_len, hdr_result); + half_data = msg->ref_queue->array[msg->queue_index].req_data; + expect_header = http_half_get_header_field(half_data, field_name, field_name_len); } - else if (HTTP_MESSAGE_RES_HEADER == msg->type) + else if (HTTP_MESSAGE_RES_LINE_HEADERS == msg->type) { - ret = http_msg_get_response_header(msg, name, name_len, hdr_result); + half_data = msg->ref_queue->array[msg->queue_index].res_data; + expect_header = http_half_get_header_field(half_data, field_name, field_name_len); } - if (ret >= 0) - { - return; - } - fail: - if (hdr_result) - { - hdr_result->name = NULL; - hdr_result->value = NULL; - } - return; - } - int http_message_get0_next_header(const struct http_message *msg, struct http_header_field *header) - { - int ret = 1; - if (unlikely(NULL == msg)) - { - goto fail; - } - assert(msg->ref_queue); - assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - if (HTTP_MESSAGE_REQ_HEADER == msg->type) - { - ret = http_msg_request_header_next(msg, header); - } - else if (HTTP_MESSAGE_RES_HEADER == msg->type) - { - ret = http_msg_response_header_next(msg, header); - } - if (ret < 0) - { - goto fail; - } - return 0; - fail: - if (header) - { - header->name = NULL; - header->value = NULL; - } - return -1; + return expect_header; } - int http_message_reset_header_iter(struct http_message *msg) + const struct http_header_field *http_message_get0_next_header(const struct http_message *msg, const struct http_header_field *cur_header) + // int http_message_get0_next_header(const struct http_message *msg, struct http_header_field *header) { if (unlikely(NULL == msg)) { - return -1; + return NULL; } assert(msg->ref_queue); assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - if (HTTP_MESSAGE_REQ_HEADER == msg->type) + const struct http_decoder_half_data *half_data = NULL; + const struct http_header_field *next_header = NULL; + + if (HTTP_MESSAGE_REQ_LINE_HEADERS == msg->type) { - struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - return http_decoder_half_data_reset_header_iter(req_data); + half_data = msg->ref_queue->array[msg->queue_index].req_data; + // ret = http_msg_request_header_next(msg, header); + next_header = http_half_get_next_header_field(half_data, cur_header); } - else if (HTTP_MESSAGE_RES_HEADER == msg->type) + else if (HTTP_MESSAGE_RES_LINE_HEADERS == msg->type) { - struct http_decoder_half_data *res_data = - msg->ref_queue->array[msg->queue_index].res_data; - return http_decoder_half_data_reset_header_iter(res_data); + half_data = msg->ref_queue->array[msg->queue_index].res_data; + next_header = http_half_get_next_header_field(half_data, cur_header); + // ret = http_msg_response_header_next(msg, header); } - return -1; + + return next_header; } void http_message_get0_uncompressed_body(const struct http_message *msg, const char **body_ptr, size_t *body_len) @@ -1073,8 +937,6 @@ extern "C" void http_message_get0_decompressed_body(const struct http_message *msg, const char **dec_body_ptr, size_t *dec_body_len) { - enum http_content_encoding ecode = HTTP_CONTENT_ENCODING_NONE; - struct http_decoder_half_data *ref_data = NULL; if (unlikely(NULL == msg)) { goto fail; @@ -1087,31 +949,7 @@ extern "C" *dec_body_len = msg->decompress_payload.iov_len; return; } - /** - * @brief If the body hasn't been compressed, same as http_message_get0_uncompressed_body(). - * - */ - - if (HTTP_MESSAGE_REQ_BODY_START == msg->type || HTTP_MESSAGE_REQ_BODY == msg->type || HTTP_MESSAGE_REQ_BODY_END == msg->type) - { - ref_data = msg->ref_queue->array[msg->queue_index].req_data; - } - else if (HTTP_MESSAGE_RES_BODY_START == msg->type || HTTP_MESSAGE_RES_BODY == msg->type || HTTP_MESSAGE_RES_BODY_END == msg->type) - { - ref_data = msg->ref_queue->array[msg->queue_index].res_data; - } - ecode = http_half_data_get_content_encoding(ref_data); - if (ref_data != NULL && HTTP_CONTENT_ENCODING_NONE != ecode) - { - goto fail; - } - if (msg->raw_payload.iov_base != NULL && msg->raw_payload.iov_len != 0) - { - *dec_body_ptr = msg->raw_payload.iov_base; - *dec_body_len = msg->raw_payload.iov_len; - } - return; fail: if (dec_body_ptr) { @@ -1147,39 +985,7 @@ extern "C" } return; } -#if 0 - void http_message_decoded_url_get0(const struct http_message *msg, struct iovec *url) - { - if (unlikely(NULL == msg)) - { - if (url) - { - url->iov_base = NULL; - url->iov_len = 0; - } - return; - } - assert(msg->ref_queue); - assert(msg->queue_index < HD_RESULT_QUEUE_LEN); - struct http_decoder_half_data *req_data = - msg->ref_queue->array[msg->queue_index].req_data; - - if (http_half_data_get_decode_url(req_data, url) < 0) - { - goto fail; - } - return; - - fail: - if (url) - { - url->iov_base = NULL; - url->iov_len = 0; - } - return; - } -#endif int http_message_get_transaction_seq(const struct http_message *msg) { if (unlikely(NULL == msg)) diff --git a/decoders/http/http_decoder_half.c b/decoders/http/http_decoder_half.c index 70991c6..562dbdc 100644 --- a/decoders/http/http_decoder_half.c +++ b/decoders/http/http_decoder_half.c @@ -4,6 +4,7 @@ #include <arpa/inet.h> #include "http_decoder_private.h" #include "llhttp.h" +#include "stellar/session.h" #include "uthash/utlist.h" struct http_decompress_buffer @@ -13,30 +14,56 @@ struct http_decompress_buffer struct http_decompress_buffer *next, *prev; }; -struct http_decoder_half_data +struct http_header_field_inner { - struct http_decoder_table *table; + struct http_header_field field; + uint8_t name_is_dup; + uint8_t value_is_dup; + uint8_t is_completed; /* on_header_value_complete() */ + struct http_header_field_inner *next, *prev; +}; - int major_version; - int minor_version; - int status_code; +struct http_request_line_inner +{ + struct http_request_line req_line; + uint8_t method_is_dup; + uint8_t uri_is_dup; + uint8_t version_is_dup; + uint8_t is_completed; // Including method, uri and version +}; - enum http_event state; +struct http_response_line_inner +{ + struct http_response_line res_line; + uint8_t version_is_dup; + uint8_t status_is_dup; + uint8_t is_completed; // Including version and status +}; +struct http_decoder_half_data +{ + enum flow_type flow_dir; + enum http_event state; enum http_content_encoding content_encoding; struct http_content_decompress *decompress; -#if 0 - char *ref_decompress_body; - size_t decompress_body_len; -#else + hstring raw_body; struct http_decompress_buffer *decompress_buffer_list; -#endif - int joint_url_complete; - int url_is_encoded; // http://<host>[:<port>]/<path>?<searchpart> hstring joint_url; - hstring decoded_url; long long transaction_index; + union + { + struct http_request_line_inner req_line_inner; + struct http_response_line_inner res_line_inner; + }; + struct http_header_field_inner *filed_list; + + struct http_header_field_inner *tmp_parsing_header; // in In processing but not completed + union + { + struct http_request_line_inner req_line_inner; + struct http_response_line_inner res_line_inner; + } tmp_parsing_line; // in In processing but not completed }; struct http_decoder_half @@ -46,40 +73,232 @@ struct http_decoder_half enum llhttp_errno error; int decompress_switch; struct http_decoder_env *httpd_env; - - // uint8_t is_request_flow; enum http_event event; http_event_cb *http_ev_cb; struct http_event_context *http_ev_ctx; - - struct http_decoder_half_data *ref_data; - + struct http_decoder_half_data *ref_data; /* pointer to current half_data on_message_begin */ long long trans_counter; long long err_counter; long long transaction_seq; // accumulated - const char *data; int data_len; }; -// #define HTTP_DECODER_DEBUG -#ifdef HTTP_DECODER_DEBUG -static void printf_debug_info(const char *desc, const char *at, size_t length) +hstring *http_half_get_raw_body(struct http_decoder_half_data *data) +{ + return &data->raw_body; +} + +static void http_half_append_string(const char *at, size_t length, char **old_str, size_t *old_str_len, int old_str_is_dup) +{ + size_t raw_len = *old_str_len; + char *append_str = CALLOC(char, raw_len + length); + memcpy(append_str, *old_str, raw_len); + memcpy(append_str + raw_len, at, length); + + if (old_str_is_dup) + { + FREE(*old_str); + } + *old_str = append_str; + *old_str_len = raw_len + length; +} + +static void http_half_append_req_method(struct http_decoder_half_data *data, const char *at, size_t length) +{ + /* first time use reference to raw packet */ + if (NULL == data->tmp_parsing_line.req_line_inner.req_line.method) + { + data->tmp_parsing_line.req_line_inner.req_line.method = at; + data->tmp_parsing_line.req_line_inner.req_line.method_len = length; + data->tmp_parsing_line.req_line_inner.method_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&data->tmp_parsing_line.req_line_inner.req_line.method, + &data->tmp_parsing_line.req_line_inner.req_line.method_len, data->tmp_parsing_line.req_line_inner.method_is_dup); + data->tmp_parsing_line.req_line_inner.method_is_dup = 1; + } +} + +static void http_half_append_req_uri(struct http_decoder_half_data *data, const char *at, size_t length) +{ + /* first time use reference to raw packet */ + if (NULL == data->tmp_parsing_line.req_line_inner.req_line.uri) + { + data->tmp_parsing_line.req_line_inner.req_line.uri = at; + data->tmp_parsing_line.req_line_inner.req_line.uri_len = length; + data->tmp_parsing_line.req_line_inner.uri_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&data->tmp_parsing_line.req_line_inner.req_line.uri, + &data->tmp_parsing_line.req_line_inner.req_line.uri_len, data->tmp_parsing_line.req_line_inner.uri_is_dup); + data->tmp_parsing_line.req_line_inner.uri_is_dup = 1; + } +} + +static void http_half_append_req_version(struct http_request_line_inner *req_line_inner, const char *at, size_t length) +{ + if (NULL == req_line_inner->req_line.version) + { + req_line_inner->req_line.version = at; + req_line_inner->req_line.version_len = length; + req_line_inner->version_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&req_line_inner->req_line.version, + &req_line_inner->req_line.version_len, req_line_inner->version_is_dup); + req_line_inner->version_is_dup = 1; + } +} + +static void http_half_append_res_version(struct http_response_line_inner *res_line_inner, const char *at, size_t length) +{ + if (NULL == res_line_inner->res_line.version) + { + res_line_inner->res_line.version = at; + res_line_inner->res_line.version_len = length; + res_line_inner->version_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&res_line_inner->res_line.version, + &res_line_inner->res_line.version_len, res_line_inner->version_is_dup); + res_line_inner->version_is_dup = 1; + } +} + +static void http_half_append_version(struct http_decoder_half_data *data, const char *at, size_t length) { - if (at) + if (FLOW_TYPE_C2S == data->flow_dir) { - char *temp = http_safe_dup(at, length); - printf("HTTP PARSER STAGE: %s: %s\n", desc, temp); - FREE(temp); + http_half_append_req_version(&data->tmp_parsing_line.req_line_inner, at, length); } else { - printf("HTTP PARSER STAGE: %s\n", desc); + http_half_append_res_version(&data->tmp_parsing_line.res_line_inner, at, length); } } -#else -#define printf_debug_info(desc, at, length) -#endif + +static void http_half_append_version_integer(struct http_decoder_half_data *data, int major, int minor) +{ + if (FLOW_TYPE_C2S == data->flow_dir) + { + data->tmp_parsing_line.req_line_inner.req_line.major_version = major; + data->tmp_parsing_line.req_line_inner.req_line.minor_version = minor; + } + else + { + data->tmp_parsing_line.res_line_inner.res_line.major_version = major; + data->tmp_parsing_line.res_line_inner.res_line.minor_version = minor; + } +} + +static void http_half_append_res_status(struct http_decoder_half_data *data, const char *at, size_t length) +{ + struct http_response_line_inner *res_line_inner = &data->tmp_parsing_line.res_line_inner; + if (NULL == res_line_inner->res_line.status) + { + res_line_inner->res_line.status = at; + res_line_inner->res_line.status_len = length; + res_line_inner->status_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&res_line_inner->res_line.status, + &res_line_inner->res_line.status_len, res_line_inner->status_is_dup); + res_line_inner->status_is_dup = 1; + } +} + +static void http_half_append_header_name(struct http_decoder_half_data *data, const char *at, size_t length) +{ + if (data->tmp_parsing_header == NULL) + { + data->tmp_parsing_header = CALLOC(struct http_header_field_inner, 1); + } + /* first time use reference to raw packet */ + if (NULL == data->tmp_parsing_header->field.name || 0 == data->tmp_parsing_header->field.name_len) + { + data->tmp_parsing_header->field.name = at; + data->tmp_parsing_header->field.name_len = length; + data->tmp_parsing_header->name_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&data->tmp_parsing_header->field.name, + &data->tmp_parsing_header->field.name_len, data->tmp_parsing_header->name_is_dup); + data->tmp_parsing_header->name_is_dup = 1; + } +} + +static void http_half_append_header_value(struct http_decoder_half_data *data, const char *at, size_t length) +{ + assert(data->tmp_parsing_header); + /* first time use reference to raw packet */ + if (NULL == data->tmp_parsing_header->field.value || 0 == data->tmp_parsing_header->field.value_len) + { + data->tmp_parsing_header->field.value = at; + data->tmp_parsing_header->field.value_len = length; + data->tmp_parsing_header->value_is_dup = 0; + } + else + { + http_half_append_string(at, length, (char **)&data->tmp_parsing_header->field.value, + &data->tmp_parsing_header->field.value_len, data->tmp_parsing_header->value_is_dup); + data->tmp_parsing_header->value_is_dup = 1; + } +} + +static void http_half_set_complete_headers(struct http_decoder_half_data *data) +{ + /* move ownership to field_list */ + DL_APPEND(data->filed_list, data->tmp_parsing_header); + data->tmp_parsing_header = NULL; +} + +static void http_half_set_completed_req_line(struct http_decoder_half_data *data) +{ + memcpy(&data->req_line_inner, &data->tmp_parsing_line.req_line_inner, sizeof(struct http_request_line_inner)); + data->req_line_inner.is_completed = 1; + memset(&data->tmp_parsing_line.req_line_inner, 0, sizeof(struct http_request_line_inner)); +} + +static void http_half_set_completed_res_line(struct http_decoder_half_data *data) +{ + memcpy(&data->res_line_inner, &data->tmp_parsing_line.res_line_inner, sizeof(struct http_response_line_inner)); + data->res_line_inner.is_completed = 1; + memset(&data->tmp_parsing_line.res_line_inner, 0, sizeof(struct http_response_line_inner)); +} + +const struct http_header_field *http_half_get_next_header_field(const struct http_decoder_half_data *half_data, const struct http_header_field *current_header) +{ + if (NULL == current_header) + { // first time + return &half_data->filed_list->field; + } + const struct http_header_field_inner *inner_fidld = container_of(current_header, struct http_header_field_inner, field); + if (inner_fidld->next == half_data->filed_list) + { // the last item + return NULL; + } + return &inner_fidld->next->field; +} + +const struct http_header_field *http_half_get_header_field(const struct http_decoder_half_data *half_data, const char *field_name, size_t field_name_len) +{ + struct http_header_field_inner *el; + DL_FOREACH(half_data->filed_list, el) + { + if (http_strncasecmp_safe(el->field.name, field_name, el->field.name_len, field_name_len) == 0) + { + return &el->field; + } + } + return NULL; +} void http_half_decompress_buffer_free(struct http_decoder_half_data *data, hstring *decompress_body) { @@ -125,19 +344,15 @@ void http_half_get_lastest_decompress_buffer(struct http_decoder_half_data *data static void http_decoder_half_data_decompress(struct http_decoder_half_data *data) { assert(data); - if (data->content_encoding == HTTP_CONTENT_ENCODING_NONE) { return; } - - hstring raw_body = {}; - http_decoder_table_get_body(data->table, (char **)&raw_body.iov_base, &raw_body.iov_len); - if (raw_body.iov_base == NULL || raw_body.iov_len == 0) + hstring *raw_body = &data->raw_body; + if (raw_body->iov_base == NULL || raw_body->iov_len == 0) { return; } - if (NULL == data->decompress) { data->decompress = http_content_decompress_create(data->content_encoding); @@ -146,12 +361,9 @@ static void http_decoder_half_data_decompress(struct http_decoder_half_data *dat assert(data->decompress); char *local_outdata = NULL; size_t local_outdata_len = 0; - if (http_content_decompress_write(data->decompress, (char *)raw_body.iov_base, - raw_body.iov_len, - &local_outdata, - &local_outdata_len) == -1) + if (http_content_decompress_write(data->decompress, (char *)raw_body->iov_base, + raw_body->iov_len, &local_outdata, &local_outdata_len) == -1) { - // log error http_content_decompress_destroy(data->decompress); data->decompress = NULL; return; @@ -171,8 +383,6 @@ static void http_decoder_half_data_decompress(struct http_decoder_half_data *dat /* Possible return values 0, -1, `HPE_PAUSED` */ static int on_message_begin(llhttp_t *http) { - printf_debug_info("on_message_begin", NULL, 0); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); @@ -186,7 +396,6 @@ static int on_message_begin(llhttp_t *http) } half->ref_data = NULL; - assert(half->http_ev_cb != NULL); half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler() @@ -197,8 +406,6 @@ static int on_message_begin(llhttp_t *http) static int on_message_complete(llhttp_t *http) { - printf_debug_info("on_message_complete", NULL, 0); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); @@ -234,224 +441,125 @@ static int on_message_complete(llhttp_t *http) return 0; } -static int on_reset(llhttp_t *http __attribute__((unused))) -{ - printf_debug_info("on_reset", NULL, 0); - - return 0; -} - -static inline int is_line_crlf(struct http_decoder_half *half) +static int on_method(llhttp_t *http, const char *at, size_t length) { - const char *chr_r = (char *)memrchr(half->data, '\r', half->data_len); - const char *chr_n = (char *)memrchr(half->data, '\n', half->data_len); - if (chr_r && chr_n && (chr_r + 1 == chr_n)) + if (0 == length) { - return 1; + return 0; } - return 0; -} - -static int on_method(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_method", at, length); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_METHOD, at, length); + http_half_append_req_method(half->ref_data, at, length); return 0; } -/* Information-only callbacks, return value is ignored */ static int on_method_complete(llhttp_t *http) { - printf_debug_info("on_method_complete", NULL, 0); - - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); - assert(half); - - if (is_line_crlf(half) == 0) - { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_METHOD); - } - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_METHOD); - + (void)http; return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_uri(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_uri", at, length); - + if (0 == length) + { + return 0; + } struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_URI, at, length); + http_half_append_req_uri(half->ref_data, at, length); return 0; } -static void http_decoder_cached_portion_url(struct http_decoder_half *half, const hstring *uri_result) -{ - struct http_decoder_half_data *ref_data = half->ref_data; - int uri_skip_len = 0; - - if ((uri_result->iov_len) > 7 && (strncasecmp("http://", (char *)uri_result->iov_base, 7) == 0)) // absolute URI - { - uri_skip_len = strlen("http://"); - ref_data->joint_url_complete = 1; - } - else - { - ref_data->joint_url_complete = 0; - } - - ref_data->joint_url.iov_len = uri_result->iov_len - uri_skip_len; - ref_data->joint_url.iov_base = MEMPOOL_CALLOC(half->http_ev_ctx->ref_mempool, char, ref_data->joint_url.iov_len); - memcpy(ref_data->joint_url.iov_base, (char *)uri_result->iov_base + uri_skip_len, ref_data->joint_url.iov_len); -} - /* Information-only callbacks, return value is ignored */ static int on_uri_complete(llhttp_t *http) { - printf_debug_info("on_uri_complete", NULL, 0); - - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); - assert(half); - - if (is_line_crlf(half) == 0) - { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_URI); - } - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_URI); - - hstring uri_result = {}; - http_decoder_table_get_uri(half->ref_data->table, (char **)&uri_result.iov_base, &uri_result.iov_len); - assert(uri_result.iov_base); - http_decoder_cached_portion_url(half, &uri_result); - + (void)http; return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_version(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_version", at, length); - + if (0 == length) + { + return 0; + } struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); + http_half_append_version(half->ref_data, at, length); - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_VERSION, at, length); return 0; } /* Information-only callbacks, return value is ignored */ static int on_version_complete(llhttp_t *http) { - printf_debug_info("on_version_complete", NULL, 0); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - if (is_line_crlf(half) == 0) - { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_VERSION); - } - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_VERSION); - - half->ref_data->major_version = llhttp_get_http_major(&half->parser); - half->ref_data->minor_version = llhttp_get_http_minor(&half->parser); + http_half_append_version_integer(half->ref_data, llhttp_get_http_major(&half->parser), llhttp_get_http_minor(&half->parser)); if (half->parser.type == HTTP_REQUEST) { - half->event = HTTP_EVENT_REQ_LINE; - if (half->http_ev_cb) // http_event_handler() - { - half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); - } + http_half_set_completed_req_line(half->ref_data); } - return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_status(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_status", at, length); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_STATUS, at, length); + http_half_append_res_status(half->ref_data, at, length); return 0; } /* Information-only callbacks, return value is ignored */ static int on_status_complete(llhttp_t *http) { - printf_debug_info("on_status_complete", NULL, 0); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - if (is_line_crlf(half) == 0) - { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_STATUS); - } - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_STATUS); - half->ref_data->status_code = llhttp_get_status_code(&half->parser); - - if (half->parser.type == HTTP_RESPONSE) - { - half->event = HTTP_EVENT_RES_LINE; - if (half->http_ev_cb != NULL) // http_event_handler() - { - half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); - } - } - + half->ref_data->tmp_parsing_line.res_line_inner.res_line.status_code = llhttp_get_status_code(&half->parser); + http_half_set_completed_res_line(half->ref_data); return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_header_field(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_header_field", at, length); - + if (0 == length) + { + return 0; + } struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_HDRKEY, at, length); + http_half_append_header_name(half->ref_data, at, length); return 0; } /* Information-only callbacks, return value is ignored */ static int on_header_field_complete(llhttp_t *http) { - printf_debug_info("on_header_field_complete", NULL, 0); - - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); - assert(half); - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRKEY); - + (void)http; return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_header_value(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_header_value", at, length); - + if (0 == length) + { + return 0; + } struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); - - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_HDRVAL, at, length); + http_half_append_header_value(half->ref_data, at, length); + // http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_HDRVAL, at, length); return 0; } @@ -459,33 +567,9 @@ static int on_header_value(llhttp_t *http, const char *at, size_t length) /* Information-only callbacks, return value is ignored */ static int on_header_value_complete(llhttp_t *http) { - printf_debug_info("on_header_value_complete", NULL, 0); - + (void)http; struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); - assert(half); - - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRKEY) == - STRING_STATE_CACHE) - { - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRKEY); - } - - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRVAL); - - if (half->ref_data->content_encoding == HTTP_CONTENT_ENCODING_NONE) - { - struct http_header_field http_hdr = {}; - - if (http_decoder_table_get_header(half->ref_data->table, (char *)"Content-Encoding", 16, &http_hdr) == 0) - { - half->ref_data->content_encoding = http_content_encoding_str2int(http_hdr.value, http_hdr.value_len); - } - } - - if (http->type == HTTP_REQUEST) - { - http_decoder_get_host_feed_url(half); - } + http_half_set_complete_headers(half->ref_data); return 0; } @@ -495,8 +579,6 @@ static int on_header_value_complete(llhttp_t *http) */ static int on_chunk_header(llhttp_t *http __attribute__((unused))) { - printf_debug_info("on_chunk_header", NULL, 0); - return 0; } @@ -506,8 +588,6 @@ static int on_chunk_header(llhttp_t *http __attribute__((unused))) */ static int on_chunk_header_complete(llhttp_t *http __attribute__((unused))) { - printf_debug_info("on_chunk_header_complete", NULL, 0); - return 0; } @@ -519,13 +599,11 @@ static int on_chunk_header_complete(llhttp_t *http __attribute__((unused))) */ static int on_headers_complete(llhttp_t *http) { - printf_debug_info("on_headers_complete", NULL, 0); - struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); assert(half->ref_data); - http_decoder_table_set_header_complete(half->ref_data->table); + // http_decoder_table_set_header_complete(half->ref_data->table); if (half->parser.type == HTTP_REQUEST) { @@ -536,18 +614,22 @@ static int on_headers_complete(llhttp_t *http) half->event = HTTP_EVENT_RES_HDR_END; } half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler() - return 0; } /* Possible return values 0, -1, HPE_USER */ static int on_body(llhttp_t *http, const char *at, size_t length) { - printf_debug_info("on_body", at, length); - + if (0 == length) + { + return 0; + } struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser); assert(half); + half->ref_data->raw_body.iov_base = (void *)NULL; + half->ref_data->raw_body.iov_len = 0; + // trigger body_begin event if (half->parser.type == HTTP_REQUEST) { @@ -566,17 +648,8 @@ static int on_body(llhttp_t *http, const char *at, size_t length) } } - if (half->ref_data != NULL) - { - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_BODY) == - STRING_STATE_COMMIT) - { - http_decoder_table_reset(half->ref_data->table, HTTP_ITEM_BODY); - } - - http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_BODY, at, length); - http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_BODY); - } + half->ref_data->raw_body.iov_base = (void *)at; + half->ref_data->raw_body.iov_len = length; if (1 == half->decompress_switch && half->ref_data->content_encoding != HTTP_CONTENT_ENCODING_NONE) { @@ -602,35 +675,25 @@ static void http_decoder_half_init(struct http_decoder_half *half, http_event_cb llhttp_settings_init(&half->settings); llhttp_init(&half->parser, type, &half->settings); - // half->is_request_flow = (type == HTTP_REQUEST) ? 1 : 0; half->settings.on_message_begin = on_message_begin; half->settings.on_message_complete = on_message_complete; - half->settings.on_reset = on_reset; - + // half->settings.on_reset = on_reset; half->settings.on_url = on_uri; half->settings.on_url_complete = on_uri_complete; - half->settings.on_status = on_status; half->settings.on_status_complete = on_status_complete; - half->settings.on_method = on_method; half->settings.on_method_complete = on_method_complete; - half->settings.on_version = on_version; half->settings.on_version_complete = on_version_complete; - half->settings.on_header_field = on_header_field; half->settings.on_header_field_complete = on_header_field_complete; - half->settings.on_header_value = on_header_value; half->settings.on_header_value_complete = on_header_value_complete; - half->settings.on_chunk_header = on_chunk_header; half->settings.on_chunk_complete = on_chunk_header_complete; - half->settings.on_headers_complete = on_headers_complete; half->settings.on_body = on_body; - half->error = HPE_OK; half->http_ev_cb = http_ev_cb; // http_event_handler() half->ref_data = NULL; @@ -658,13 +721,11 @@ void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half) { return; } - if (half->http_ev_ctx != NULL) { MEMPOOL_FREE(mempool, half->http_ev_ctx); half->http_ev_ctx = NULL; } - MEMPOOL_FREE(mempool, half); } @@ -673,149 +734,232 @@ void http_decoder_half_reinit(struct http_decoder_half *half, nmx_pool_t *mempool, struct session *sess) { assert(half != NULL); - if (half->ref_data != NULL) - { - http_decoder_table_reinit(half->ref_data->table); - } half->http_ev_ctx->ref_mempool = mempool; half->http_ev_ctx->ref_session = sess; half->http_ev_ctx->ref_queue = queue; } -static void publish_message_for_parsed_header(struct http_decoder_half *half) +static int http_half_is_headers_completed(struct http_decoder_half *half) { - if (0 == http_decoder_table_has_parsed_header(half->ref_data->table)) + if (half->ref_data == NULL) { - return; + return 0; } if (half->parser.type == HTTP_REQUEST) { - half->event = HTTP_EVENT_REQ_HDR; + if ((int)half->event >= (int)HTTP_EVENT_REQ_HDR_END) + { + return 1; + } } else { - half->event = HTTP_EVENT_RES_HDR; + if ((int)half->event >= (int)HTTP_EVENT_RES_HDR_END) + { + return 1; + } } - half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler(); - return; + return 0; } -int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len) +static void http_half_header_filed_dup_name(struct http_header_field_inner *el) { - assert(half && data); - - half->data = (const char *)data; - half->data_len = data_len; - half->error = llhttp_execute(&half->parser, data, data_len); + el->field.name = http_string_dup(el->field.name, el->field.name_len); + el->name_is_dup = 1; +} - int ret = 0; - enum llhttp_type type = HTTP_BOTH; +static void http_half_header_filed_dup_value(struct http_header_field_inner *el) +{ + el->field.value = http_string_dup(el->field.value, el->field.value_len); + el->value_is_dup = 1; +} - switch (half->error) +/* + * save temporary data if line/headers is not completed. + */ +static void http_half_line_headers_cache(struct http_decoder_half *half) +{ + if (FLOW_TYPE_C2S == half->ref_data->flow_dir) { - case HPE_OK: - break; - case HPE_PAUSED: - llhttp_resume(&half->parser); - break; - case HPE_PAUSED_UPGRADE: - if (proxy_enable) + struct http_request_line_inner *req_inner; + if (half->ref_data->req_line_inner.is_completed) { - llhttp_resume_after_upgrade(&half->parser); + req_inner = &half->ref_data->req_line_inner; + } + else + { + req_inner = &half->ref_data->tmp_parsing_line.req_line_inner; + } + if (req_inner->method_is_dup == 0) + { + req_inner->req_line.method = http_string_dup(req_inner->req_line.method, req_inner->req_line.method_len); + req_inner->method_is_dup = 1; + } + if (req_inner->uri_is_dup == 0) + { + req_inner->req_line.uri = http_string_dup(req_inner->req_line.uri, req_inner->req_line.uri_len); + req_inner->uri_is_dup = 1; + } + if (req_inner->version_is_dup == 0) + { + req_inner->req_line.version = http_string_dup(req_inner->req_line.version, req_inner->req_line.version_len); + req_inner->version_is_dup = 1; } - ret = 0; - break; - default: - type = (enum llhttp_type)half->parser.type; - llhttp_init(&half->parser, type, &half->settings); - ret = -1; - break; - } - - if (ret < 0) - { - // fprintf(stdout, - // "llhttp_execute parse error: %s err_reason:%s\n", - // llhttp_errno_name(half->error), half->parser.reason); - return half->error; } - - if (half->ref_data != NULL) + else { - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_URI) == STRING_STATE_REFER) + struct http_response_line_inner *res_inner; + if (half->ref_data->res_line_inner.is_completed) { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_URI); + res_inner = &half->ref_data->res_line_inner; } - - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_STATUS) == STRING_STATE_REFER) + else { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_STATUS); + res_inner = &half->ref_data->tmp_parsing_line.res_line_inner; } - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_METHOD) == STRING_STATE_REFER) + if (res_inner->status_is_dup == 0) { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_METHOD); + res_inner->res_line.status = http_string_dup(res_inner->res_line.status, res_inner->res_line.status_len); + res_inner->status_is_dup = 1; } - - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_VERSION) == STRING_STATE_REFER) + if (res_inner->version_is_dup == 0) { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_VERSION); + res_inner->res_line.version = http_string_dup(res_inner->res_line.version, res_inner->res_line.version_len); + res_inner->version_is_dup = 1; } + } - if (http_decoder_table_header_complete(half->ref_data->table)) + /* copy completed headers if not dup */ + struct http_header_field_inner *el, *tmp; + DL_FOREACH_SAFE(half->ref_data->filed_list, el, tmp) + { + if (el->name_is_dup == 0) { - http_decoder_table_reset_header_complete(half->ref_data->table); + http_half_header_filed_dup_name(el); } - else + if (el->value_is_dup == 0) { - // if headers are not completed with EOF \r\n\r\n, push the parsed headers so far - publish_message_for_parsed_header(half); + http_half_header_filed_dup_value(el); } - - enum string_state hdr_key_state = - http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRKEY); - enum string_state hdr_val_state = - http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRVAL); - - /* Truncated in http header key - For example http header k-v => User-Agent: Chrome - case1: - packet1: User- hdr_key_state == STRING_STATE_REFER - packet2: Agent: Chrome - - case2: - packet1: User-Agent: hdr_key_state == STRING_STATE_COMMIT - hdr_val_state == STRING_STATE_INIT - packet2: Chrome - */ - if (hdr_key_state == STRING_STATE_REFER || - (hdr_key_state == STRING_STATE_COMMIT && hdr_val_state == STRING_STATE_INIT)) + } + // copy in parsing stage header + if (half->ref_data->tmp_parsing_header) + { + if (half->ref_data->tmp_parsing_header->field.name && half->ref_data->tmp_parsing_header->name_is_dup == 0) { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRKEY); + http_half_header_filed_dup_name(half->ref_data->tmp_parsing_header); + half->ref_data->tmp_parsing_header->name_is_dup = 1; } + if (half->ref_data->tmp_parsing_header->field.value && half->ref_data->tmp_parsing_header->value_is_dup == 0) + { + http_half_header_filed_dup_value(half->ref_data->tmp_parsing_header); + half->ref_data->tmp_parsing_header->value_is_dup = 1; + } + } +} - /* Truncated in http header value - For example http header k-v => User-Agent: Chrome - packet1: User-Agent: Ch hdr_key_state == STRING_STATE_COMMIT - hdr_val_state == STRING_STATE_REFER - - packet2: rome - */ - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRVAL) == STRING_STATE_REFER) +static void http_half_headers_free(struct http_header_field_inner **field_list_head) +{ + if (NULL == field_list_head || NULL == *field_list_head) + { + return; + } + struct http_header_field_inner *head = *field_list_head; + struct http_header_field_inner *el, *tmp; + DL_FOREACH_SAFE(head, el, tmp) + { + if (el->name_is_dup == 1) { - /* Header key should have been committed - If it's not cached, cache it for next packet to use - */ - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRKEY); - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRVAL); + FREE(el->field.name); } + if (el->value_is_dup == 1) + { + FREE(el->field.value); + } + FREE(el); + } + *field_list_head = NULL; +} + +static void http_half_req_line_free(struct http_request_line_inner *req_inner) +{ + if (req_inner->method_is_dup == 1) + { + FREE(req_inner->req_line.method); + req_inner->method_is_dup = 0; + } + if (req_inner->uri_is_dup == 1) + { + FREE(req_inner->req_line.uri); + req_inner->uri_is_dup = 0; + } + if (req_inner->version_is_dup == 1) + { + FREE(req_inner->req_line.version); + req_inner->version_is_dup = 0; + } +} + +static void http_half_res_line_free(struct http_response_line_inner *res_inner) +{ + if (res_inner->status_is_dup == 1) + { + FREE(res_inner->res_line.status); + res_inner->status_is_dup = 0; + } + if (res_inner->version_is_dup == 1) + { + FREE(res_inner->res_line.version); + res_inner->version_is_dup = 0; + } +} + +void http_half_line_headers_free(struct http_decoder_half_data *ref_data) +{ + if (FLOW_TYPE_C2S == ref_data->flow_dir) + { + http_half_req_line_free(&ref_data->req_line_inner); + http_half_req_line_free(&ref_data->tmp_parsing_line.req_line_inner); + } + else + { + http_half_res_line_free(&ref_data->res_line_inner); + http_half_res_line_free(&ref_data->tmp_parsing_line.res_line_inner); + } + http_half_headers_free(&ref_data->filed_list); + http_half_headers_free(&ref_data->tmp_parsing_header); +} - if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_BODY) == STRING_STATE_REFER) +int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len) +{ + assert(half && data); + half->data = (const char *)data; + half->data_len = data_len; + half->error = llhttp_execute(&half->parser, data, data_len); + + switch (half->error) + { + case HPE_OK: + break; + case HPE_PAUSED: + llhttp_resume(&half->parser); + break; + case HPE_PAUSED_UPGRADE: + if (proxy_enable) { - http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_BODY); + llhttp_resume_after_upgrade(&half->parser); } + break; + default: + return half->error; + break; } + if (http_half_is_headers_completed(half) == 0) + { + http_half_line_headers_cache(half); + } return 0; } @@ -825,30 +969,17 @@ long long http_decoder_half_trans_count(struct http_decoder_half *half) { return 0; } - long long trans_cnt = half->trans_counter; half->trans_counter = 0; - return trans_cnt; } -struct http_decoder_half_data * -http_decoder_half_data_new(nmx_pool_t *mempool) +struct http_decoder_half_data *http_decoder_half_data_new(nmx_pool_t *mempool, enum flow_type flow_dir) { - struct http_decoder_half_data *data = - MEMPOOL_CALLOC(mempool, struct http_decoder_half_data, 1); + struct http_decoder_half_data *data = MEMPOOL_CALLOC(mempool, struct http_decoder_half_data, 1); assert(data); - - data->table = http_decoder_table_new(mempool); - assert(data->table); - - data->major_version = -1; - data->minor_version = -1; - data->status_code = -1; - + data->flow_dir = flow_dir; data->content_encoding = HTTP_CONTENT_ENCODING_NONE; - // data->ref_decompress_body = NULL; - // data->decompress_body_len = 0; data->decompress_buffer_list = NULL; return data; } @@ -878,13 +1009,6 @@ void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_d { return; } - - if (data->table != NULL) - { - http_decoder_table_free(data->table); - data->table = NULL; - } - if (data->decompress != NULL) { http_content_decompress_destroy(data->decompress); @@ -895,115 +1019,29 @@ void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_d { MEMPOOL_FREE(mempool, data->joint_url.iov_base); data->joint_url.iov_base = NULL; - data->joint_url_complete = 0; } http_decoder_half_decompress_buf_free(data); + http_half_line_headers_free(data); MEMPOOL_FREE(mempool, data); } -int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data, - struct http_request_line *line) -{ - http_decoder_table_get_method(data->table, &line->method, &line->method_len); - http_decoder_table_get_uri(data->table, &line->uri, &line->uri_len); - http_decoder_table_get_version(data->table, &line->version, &line->version_len); - - line->major_version = data->major_version; - line->minor_version = data->minor_version; - - return 0; -} - -int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data, - struct http_response_line *line) -{ - http_decoder_table_get_version(data->table, &line->version, &line->version_len); - http_decoder_table_get_status(data->table, &line->status, &line->status_len); - - line->major_version = data->major_version; - line->minor_version = data->minor_version; - line->status_code = data->status_code; - - return 0; -} - -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_result) -{ - return http_decoder_table_get_header(data->table, name, name_len, hdr_result); -} - -int http_decoder_half_data_iter_header(struct http_decoder_half_data *data, - struct http_header_field *header) -{ - return http_decoder_table_iter_header((struct http_decoder_table *)data->table, header); -} - -int http_decoder_half_data_reset_header_iter(struct http_decoder_half_data *req_data) -{ - if (NULL == req_data) - { - return -1; - } - return http_decoder_table_reset_header_iter(req_data->table); -} - -int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data) -{ - if (NULL == data) - { - return 0; - } - return http_decoder_table_has_parsed_header(data->table); -} - -int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len) +const struct http_request_line *http_decoder_half_data_get_request_line(struct http_decoder_half_data *data) { - if (NULL == data || NULL == body) - { - return -1; - } - return http_decoder_table_get_body(data->table, (char **)body, body_len); + return &data->req_line_inner.req_line; } -#if 0 -int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data, hstring *body) -{ - if (HTTP_CONTENT_ENCODING_NONE == data->content_encoding) - { - return http_decoder_table_get_body(data->table, body); - } - body->iov_base = data->ref_decompress_body; - body->iov_len = data->decompress_body_len; - return 0; -} -#endif - -void http_decoder_half_data_dump(struct http_decoder_half *half) +const struct http_response_line *http_decoder_half_data_get_response_line(struct http_decoder_half_data *data) { - if (NULL == half || NULL == half->ref_data) - { - return; - } - - http_decoder_table_dump(half->ref_data->table); + return &data->res_line_inner.res_line; } -static void using_session_addr_as_host(struct session *ref_session, struct http_header_field *host_result, nmx_pool_t *mempool) +struct http_header_field *http_using_session_addr_without_host(struct session *ref_session, nmx_pool_t *mempool) { -#if 1 // in native steallar, can't get the tuple4 from the session yet!!! + struct http_header_field *host_result = MEMPOOL_CALLOC(mempool, struct http_header_field, 1); struct httpd_session_addr ssaddr = {}; httpd_session_get_addr(ref_session, &ssaddr); - if (ssaddr.ipver != 4 && ssaddr.ipver != 6) - { - host_result->value = MEMPOOL_CALLOC(mempool, char, 1); - sprintf((char *)host_result->value, "%s", ""); - host_result->value_len = strlen((char *)host_result->value); - return; - } - char ip_string_buf[INET6_ADDRSTRLEN]; + if (4 == ssaddr.ipver) { host_result->value = MEMPOOL_CALLOC(mempool, char, (INET_ADDRSTRLEN + 7) /* "ip:port" max length */); @@ -1020,23 +1058,31 @@ static void using_session_addr_as_host(struct session *ref_session, struct http_ } else { - assert(0); + host_result->value = MEMPOOL_CALLOC(mempool, char, 1); + sprintf((char *)host_result->value, "%s", ""); + host_result->value_len = strlen((char *)host_result->value); + return host_result; } -#else - host_result->val.iov_base = MEMPOOL_CALLOC(mempool, char, 32); - sprintf((char *)host_result->val.iov_base, "%s", "todo:get_tuple4"); - host_result->val.iov_len = strlen((char *)host_result->val.iov_base); -#endif + return host_result; } void http_decoder_join_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool, const struct http_header_field *host_hdr) { int append_slash_len = 0; - if ('/' != ((char *)hfdata->joint_url.iov_base)[0]) + const char *join_uri = hfdata->req_line_inner.req_line.uri; + size_t join_url_len = hfdata->req_line_inner.req_line.uri_len; + + if (join_url_len > 7 && strncasecmp(join_uri, "http://", 7) == 0) + { + join_uri += 7; + join_url_len -= 7; + } + + if ('/' != join_uri[0]) { append_slash_len = 1; } - int url_cache_str_len = host_hdr->value_len + hfdata->joint_url.iov_len + append_slash_len; + int url_cache_str_len = host_hdr->value_len + join_url_len + append_slash_len; char *url_cache_str = MEMPOOL_CALLOC(mempool, char, url_cache_str_len); char *ptr = url_cache_str; @@ -1047,91 +1093,55 @@ void http_decoder_join_url(struct http_decoder_half_data *hfdata, nmx_pool_t *me *ptr = '/'; ptr++; } - memcpy(ptr, hfdata->joint_url.iov_base, hfdata->joint_url.iov_len); + memcpy(ptr, join_uri, join_url_len); - MEMPOOL_FREE(mempool, hfdata->joint_url.iov_base); // free the cached uri buffer hfdata->joint_url.iov_base = url_cache_str; hfdata->joint_url.iov_len = url_cache_str_len; - hfdata->joint_url_complete = 1; } -void http_decoder_get_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool) +int http_parse_headers_finally(struct http_event_context *ev_ctx, struct http_decoder_half_data *hfdata, nmx_pool_t *mempool) { - struct http_request_line reqline = {}; - http_decoder_half_data_get_request_line(hfdata, &reqline); - if (unlikely(http_strncasecmp_safe("CONNECT", (char *)reqline.method, 7, reqline.method_len) == 0)) + if (FLOW_TYPE_C2S == hfdata->flow_dir) { - hfdata->joint_url.iov_base = MEMPOOL_CALLOC(mempool, char, reqline.uri_len + 1); - memcpy(hfdata->joint_url.iov_base, reqline.uri, reqline.uri_len); - hfdata->joint_url.iov_len = reqline.uri_len; - hfdata->joint_url_complete = 1; - } -} - -int http_decoder_join_url_finally(struct http_event_context *ev_ctx, struct http_decoder_half_data *hfdata, nmx_pool_t *mempool) -{ - if (hfdata->joint_url_complete) - { - return 0; + const struct http_header_field *host_filed = http_half_get_header_field(hfdata, "Host", 4); + if (NULL == host_filed) + { + host_filed = http_using_session_addr_without_host(ev_ctx->ref_session, mempool); + } + http_decoder_join_url(hfdata, mempool, host_filed); } - struct http_header_field addr_as_host = {}; - using_session_addr_as_host(ev_ctx->ref_session, &addr_as_host, mempool); - http_decoder_join_url(hfdata, mempool, &addr_as_host); - MEMPOOL_FREE(mempool, addr_as_host.value); // free session addr to host buffer - return 1; -} -void http_decoder_get_host_feed_url(struct http_decoder_half *half) -{ - if (half->ref_data->joint_url_complete) + const struct http_header_field *encoding_field = http_half_get_header_field(hfdata, "Content-Encoding", 16); + if (NULL == encoding_field) { - return; + hfdata->content_encoding = HTTP_CONTENT_ENCODING_NONE; } - struct http_header_field host_result = {}; - int host_header_cnt = http_decoder_half_data_get_header(half->ref_data, (char *)"Host", 4, &host_result); - if (host_header_cnt < 0) + else { - return; + hfdata->content_encoding = http_content_encoding_str2int(encoding_field->value, encoding_field->value_len); } - http_decoder_join_url(half->ref_data, half->http_ev_ctx->ref_mempool, &host_result); + return 1; } int http_half_data_get_url(struct http_decoder_half_data *res_data, const char **url_val, size_t *url_len) { - if (0 == res_data->joint_url_complete) - { - return -1; - } + *url_val = res_data->joint_url.iov_base; *url_len = res_data->joint_url.iov_len; return 0; } -#if 0 -int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstring *url) -{ - if (0 == res_data->joint_url_complete) - { - return -1; - } - url->iov_base = res_data->decoded_url.iov_base; - url->iov_len = res_data->decoded_url.iov_len; - return 0; -} -#endif int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data) { return hf_data->transaction_index; } -void http_half_data_update_commit_index(struct http_decoder_half_data *half_data) +int http_half_get_header_count(struct http_decoder_half_data *half_data) { - http_decoder_table_update_commit_index(half_data->table); -} - -int http_half_data_get_total_parsed_header_count(struct http_decoder_half_data *half_data) -{ - return http_decoder_table_get_total_parsed_header(half_data->table); + int header_count = 0; + struct http_header_field_inner *el; + DL_COUNT(half_data->filed_list, el, header_count); + return header_count; } void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata *exdata) @@ -1153,7 +1163,6 @@ void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata session_mq_publish_message(sess, exdata->pub_topic_id, msg); } } - for (size_t i = 0; i < queue->queue_size; i++) { res_data = queue->array[i].res_data; @@ -1185,4 +1194,4 @@ enum http_content_encoding http_half_data_get_content_encoding(struct http_decod return HTTP_CONTENT_ENCODING_NONE; } return hf_data->content_encoding; -}
\ No newline at end of file +} diff --git a/decoders/http/http_decoder_half.h b/decoders/http/http_decoder_half.h index f525f78..6622b33 100644 --- a/decoders/http/http_decoder_half.h +++ b/decoders/http/http_decoder_half.h @@ -13,6 +13,7 @@ typedef struct iovec hstring; // only one http event is fired at a time 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, @@ -62,16 +63,13 @@ int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, co 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); +struct http_decoder_half_data *http_decoder_half_data_new(nmx_pool_t *mempool, enum flow_type flow_dir); 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); +const struct http_request_line *http_decoder_half_data_get_request_line(struct http_decoder_half_data *data); -int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data, - struct http_response_line *line); +const struct http_response_line *http_decoder_half_data_get_response_line(struct http_decoder_half_data *data); 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); @@ -86,6 +84,7 @@ int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *dat 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_half_flow_buffer_free(struct http_decoder_half_data *data); void http_decoder_half_data_dump(struct http_decoder_half *half); void http_decoder_get_host_feed_url(struct http_decoder_half *half); @@ -94,16 +93,20 @@ int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstri 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_parse_headers_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 +enum http_content_encoding http_half_data_get_content_encoding(struct http_decoder_half_data *hf_data); +const struct http_header_field *http_half_get_next_header_field(const struct http_decoder_half_data *half_data, const struct http_header_field *current_header); +const struct http_header_field *http_half_get_header_field(const struct http_decoder_half_data *half_data, const char *field_name, size_t field_name_len); +int http_half_get_header_count(struct http_decoder_half_data *half_data); +hstring *http_half_get_raw_body(struct http_decoder_half_data *data); +void http_half_line_headers_free(struct http_decoder_half_data *ref_data);
\ No newline at end of file diff --git a/decoders/http/http_decoder_private.h b/decoders/http/http_decoder_private.h index 04130f0..bc772cd 100644 --- a/decoders/http/http_decoder_private.h +++ b/decoders/http/http_decoder_private.h @@ -22,7 +22,6 @@ extern "C" #include "stellar/http.h" #include "http_decoder_result_queue.h" #include "http_decoder_half.h" -#include "http_decoder_table.h" #include "http_decoder_result_queue.h" #include "http_decoder_utils.h" #include "http_decoder_stat.h" diff --git a/decoders/http/http_decoder_result_queue.c b/decoders/http/http_decoder_result_queue.c index 5695138..72eb20b 100644 --- a/decoders/http/http_decoder_result_queue.c +++ b/decoders/http/http_decoder_result_queue.c @@ -1,8 +1,7 @@ #include <assert.h> #include "http_decoder_private.h" -struct http_decoder_result_queue * -http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size) +struct http_decoder_result_queue *http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size) { struct http_decoder_result_queue *queue = MEMPOOL_CALLOC(mempool, struct http_decoder_result_queue, 1); @@ -11,8 +10,7 @@ http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size) queue->req_index = 0; queue->res_index = 0; queue->queue_size = queue_size; - queue->array = MEMPOOL_CALLOC(mempool, struct http_decoder_result, - queue->queue_size); + queue->array = MEMPOOL_CALLOC(mempool, struct http_decoder_result, queue->queue_size); assert(queue->array); return queue; } @@ -104,8 +102,7 @@ int http_decoder_result_queue_push_res(struct http_decoder_result_queue *queue, return 0; } -struct http_decoder_half_data * -http_decoder_result_queue_pop_req(struct http_decoder_result_queue *queue) +struct http_decoder_half_data *http_decoder_result_queue_pop_req(struct http_decoder_result_queue *queue) { if (NULL == queue) { @@ -116,8 +113,7 @@ http_decoder_result_queue_pop_req(struct http_decoder_result_queue *queue) return req_data; } -struct http_decoder_half_data * -http_decoder_result_queue_pop_res(struct http_decoder_result_queue *queue) +struct http_decoder_half_data *http_decoder_result_queue_pop_res(struct http_decoder_result_queue *queue) { if (NULL == queue) { @@ -129,8 +125,7 @@ http_decoder_result_queue_pop_res(struct http_decoder_result_queue *queue) return res_data; } -struct http_decoder_half_data * -http_decoder_result_queue_peek_req(struct http_decoder_result_queue *queue) +struct http_decoder_half_data *http_decoder_result_queue_peek_req(struct http_decoder_result_queue *queue) { if (NULL == queue) { @@ -140,8 +135,7 @@ http_decoder_result_queue_peek_req(struct http_decoder_result_queue *queue) return queue->array[queue->req_index].req_data; } -struct http_decoder_half_data * -http_decoder_result_queue_peek_res(struct http_decoder_result_queue *queue) +struct http_decoder_half_data *http_decoder_result_queue_peek_res(struct http_decoder_result_queue *queue) { if (NULL == queue) { diff --git a/decoders/http/http_decoder_string.c b/decoders/http/http_decoder_string.c deleted file mode 100644 index 6fd5b04..0000000 --- a/decoders/http/http_decoder_string.c +++ /dev/null @@ -1,289 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include "http_decoder_private.h" - -static const char *string_state_to_desc(enum string_state state) -{ - switch (state) - { - case STRING_STATE_INIT: - return "init"; - break; - case STRING_STATE_REFER: - return "refer"; - break; - case STRING_STATE_CACHE: - return "cache"; - break; - case STRING_STATE_COMMIT: - return "commit"; - break; - default: - return "unknown"; - break; - } -} - -void http_decoder_string_refer(struct http_decoder_string *rstr, const char *at, size_t length) -{ - if (NULL == rstr) - { - return; - } - - switch (rstr->state) - { - case STRING_STATE_INIT: - case STRING_STATE_CACHE: - rstr->refer.iov_base = (char *)at; - rstr->refer.iov_len = length; - break; - default: - abort(); - break; - } - - rstr->state = STRING_STATE_REFER; -} - -static void string_refer2cache(struct http_decoder_string *rstr) -{ - if (0 == rstr->refer.iov_len) - { - return; - } - if (rstr->cache.iov_len >= rstr->max_cache_size) - { - return; - } - - size_t length = rstr->cache.iov_len + rstr->refer.iov_len; - if (length > rstr->max_cache_size) - { - length = rstr->max_cache_size; - } - - if (NULL == rstr->cache.iov_base) - { - rstr->cache.iov_base = CALLOC(char, length + 1); - memcpy(rstr->cache.iov_base, rstr->refer.iov_base, length); - } - else - { - rstr->cache.iov_base = REALLOC(char, rstr->cache.iov_base, length + 1); - memcpy((char *)rstr->cache.iov_base + rstr->cache.iov_len, rstr->refer.iov_base, - (length - rstr->cache.iov_len)); - } - - rstr->cache.iov_len = length; - rstr->refer.iov_base = NULL; - rstr->refer.iov_len = 0; -} - -static void string_commit2cache(struct http_decoder_string *rstr) -{ - if (rstr->cache.iov_len == rstr->commit.iov_len && - rstr->cache.iov_base == rstr->commit.iov_base) - { - rstr->commit.iov_base = NULL; - rstr->commit.iov_len = 0; - return; - } - - // Only http header key need to backward to cache - size_t length = 0; - if (rstr->commit.iov_len > rstr->max_cache_size) - { - length = rstr->max_cache_size; - } - else - { - length = rstr->commit.iov_len; - } - - if (length > 0) - { - if (NULL == rstr->cache.iov_base) - { - rstr->cache.iov_base = CALLOC(char, length + 1); - } - else - { - abort(); - } - memcpy(rstr->cache.iov_base, rstr->commit.iov_base, length); - rstr->cache.iov_len = length; - - rstr->commit.iov_base = NULL; - rstr->commit.iov_len = 0; - } -} - -void http_decoder_string_cache(struct http_decoder_string *rstr) -{ - if (NULL == rstr) - { - return; - } - - switch (rstr->state) - { - case STRING_STATE_REFER: - string_refer2cache(rstr); - break; - case STRING_STATE_CACHE: - break; - case STRING_STATE_COMMIT: - // commit backward to cache - string_commit2cache(rstr); - break; - default: - abort(); - break; - } - rstr->state = STRING_STATE_CACHE; -} - -void http_decoder_string_commit(struct http_decoder_string *rstr) -{ - if (NULL == rstr) - { - return; - } - - switch (rstr->state) - { - case STRING_STATE_REFER: - if (rstr->cache.iov_len) - { - http_decoder_string_cache(rstr); - - rstr->commit.iov_base = rstr->cache.iov_base; - rstr->commit.iov_len = rstr->cache.iov_len; - // not overwrite rstr->cache.iov_base - } - else - { - rstr->commit.iov_base = rstr->refer.iov_base; - rstr->commit.iov_len = rstr->refer.iov_len; - - rstr->refer.iov_base = NULL; - rstr->refer.iov_len = 0; - } - break; - case STRING_STATE_CACHE: - rstr->commit.iov_base = rstr->cache.iov_base; - rstr->commit.iov_len = rstr->cache.iov_len; - // not overwrite rstr->cache.iov_base - break; - default: - // abort(); - break; - } - - rstr->state = STRING_STATE_COMMIT; -} - -void http_decoder_string_reset(struct http_decoder_string *rstr) -{ - assert(rstr); - - switch (rstr->state) - { - case STRING_STATE_INIT: - case STRING_STATE_REFER: - case STRING_STATE_CACHE: - case STRING_STATE_COMMIT: - FREE(rstr->cache.iov_base); - memset(rstr, 0, sizeof(struct http_decoder_string)); - break; - default: - abort(); - break; - } - - rstr->state = STRING_STATE_INIT; -} - -void http_decoder_string_init(struct http_decoder_string *rstr, size_t max_cache_size) -{ - rstr->max_cache_size = max_cache_size; -} - -void http_decoder_string_reinit(struct http_decoder_string *rstr) -{ - if (rstr->state == STRING_STATE_CACHE) - { - return; - } - - if (rstr->state == STRING_STATE_COMMIT && - rstr->cache.iov_base == rstr->commit.iov_base && - rstr->cache.iov_len == rstr->commit.iov_len) - { - return; - } - - if (rstr->cache.iov_base != NULL) - { - FREE(rstr->cache.iov_base); - rstr->cache.iov_len = 0; - } - -#if 0 - rstr->refer.iov_base = NULL; - rstr->refer.iov_len = 0; - rstr->commit.iov_base = NULL; - rstr->commit.iov_len = 0; - rstr->state = STRING_STATE_INIT; -#endif -} - -enum string_state http_decoder_string_state(const struct http_decoder_string *rstr) -{ - return rstr->state; -} - -int http_decoder_string_get(const struct http_decoder_string *rstr, char **name, size_t *name_len) -{ - if (NULL == rstr || NULL == name || 0 == name_len) - { - return -1; - } - - if (http_decoder_string_state(rstr) == STRING_STATE_COMMIT) - { - *name = rstr->commit.iov_base; - *name_len = rstr->commit.iov_len; - } - else - { - *name = NULL; - *name_len = 0; - } - return 0; -} - -void http_decoder_string_dump(struct http_decoder_string *rstr, const char *desc) -{ - if (NULL == rstr) - { - return; - } - - char *refer_str = http_safe_dup((char *)rstr->refer.iov_base, rstr->refer.iov_len); - char *cache_str = http_safe_dup((char *)rstr->cache.iov_base, rstr->cache.iov_len); - char *commit_str = http_safe_dup((char *)rstr->commit.iov_base, rstr->commit.iov_len); - - printf("%s: state: %s, refer: {len: %02zu, iov_base: %s}, cache: {len: %02zu, iov_base: %s}, commit: {len: %02zu, iov_base: %s}\n", - desc, string_state_to_desc(rstr->state), - rstr->refer.iov_len, refer_str, - rstr->cache.iov_len, cache_str, - rstr->commit.iov_len, commit_str); - - FREE(refer_str); - FREE(cache_str); - FREE(commit_str); -}
\ No newline at end of file diff --git a/decoders/http/http_decoder_string.h b/decoders/http/http_decoder_string.h deleted file mode 100644 index 83721e9..0000000 --- a/decoders/http/http_decoder_string.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "stellar/http.h" - -enum string_state { - STRING_STATE_INIT, - STRING_STATE_REFER, - STRING_STATE_CACHE, - STRING_STATE_COMMIT, -}; - -/* state transition diagram - * +----------+ - * | | - * \|/ | - * +------+ | - * | init | | - * +------+ | - * | | - * +---->| | - * | \|/ | - * | +-------+ | - * | | refer |--+ | - * | +-------+ | | - * | | | | - * | \|/ | | - * | +-------+ | | - * +--| cache | | | - * +-------+ | | - * | | | - * |<------+ | - * \|/ | - * +--------+ | - * | commit | | - * +--------+ | - * | | - * \|/ | - * +--------+ | - * | reset |----+ - * +--------+ - */ - - -//http decoder string -struct http_decoder_string { - hstring refer; // shallow copy - hstring cache; // deep copy - hstring commit; - - enum string_state state; - size_t max_cache_size; -}; - -void http_decoder_string_refer(struct http_decoder_string *rstr, - const char *at, size_t length); - -void http_decoder_string_cache(struct http_decoder_string *rstr); - -void http_decoder_string_commit(struct http_decoder_string *rstr); - -void http_decoder_string_reset(struct http_decoder_string *rstr); - -void http_decoder_string_init(struct http_decoder_string *rstr, - size_t max_cache_size); - -void http_decoder_string_reinit(struct http_decoder_string *rstr); - -enum string_state http_decoder_string_state(const struct http_decoder_string *rstr); - -int http_decoder_string_get(const struct http_decoder_string *rstr, char **name, size_t *name_len); - -void http_decoder_string_dump(struct http_decoder_string *rstr, const char *desc); -
\ No newline at end of file diff --git a/decoders/http/http_decoder_table.c b/decoders/http/http_decoder_table.c deleted file mode 100644 index c85b876..0000000 --- a/decoders/http/http_decoder_table.c +++ /dev/null @@ -1,579 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include "http_decoder_private.h" - -#define INIT_HEADER_CNT 16 -#define MAX_URI_CACHE_SIZE 2048 -#define MAX_STATUS_CACHE_SIZE 32 -#define MAX_METHOD_CACHE_SIZE 8 -#define MAX_VERSION_CACHE_SIZE 4 -#define MAX_HEADER_KEY_CACHE_SIZE 4096 -#define MAX_HEADER_VALUE_CACHE_SIZE 4096 - -struct http_decoder_header -{ - struct http_decoder_string key; - struct http_decoder_string val; -}; - -struct http_decoder_table -{ - struct http_decoder_string uri; - struct http_decoder_string status; - struct http_decoder_string method; - struct http_decoder_string version; - struct http_decoder_string body; - - nmx_pool_t *ref_mempool; - int header_complete; // flag for all headers parsed completely - size_t header_cnt; - size_t header_index; // current parsing header - size_t header_iter; // plugins iterate cursor - size_t commit_header_index; // pushed to plugins, whether has called http_message_get0_next_header() - struct http_decoder_header *headers; -}; - -static void http_decoder_table_init(struct http_decoder_table *table) -{ - if (NULL == table) - { - return; - } - - struct http_decoder_header *header = NULL; - assert(table); - - http_decoder_string_init(&table->uri, MAX_URI_CACHE_SIZE); - http_decoder_string_init(&table->status, MAX_STATUS_CACHE_SIZE); - http_decoder_string_init(&table->method, MAX_METHOD_CACHE_SIZE); - http_decoder_string_init(&table->version, MAX_METHOD_CACHE_SIZE); - - for (size_t i = 0; i < table->header_cnt; i++) - { - header = &table->headers[i]; - http_decoder_string_init(&header->key, MAX_HEADER_KEY_CACHE_SIZE); - http_decoder_string_init(&header->val, MAX_HEADER_VALUE_CACHE_SIZE); - } - - http_decoder_string_init(&table->body, 0); -} - -struct http_decoder_table *http_decoder_table_new(nmx_pool_t *mempool) -{ - struct http_decoder_table *table = - MEMPOOL_CALLOC(mempool, struct http_decoder_table, 1); - assert(table); - - table->ref_mempool = mempool; - table->header_cnt = INIT_HEADER_CNT; - table->headers = MEMPOOL_CALLOC(mempool, struct http_decoder_header, - table->header_cnt); - table->commit_header_index = 0; - http_decoder_table_init(table); - - return table; -} - -void http_decoder_table_free(struct http_decoder_table *table) -{ - if (NULL == table) - { - return; - } - if (table->uri.cache.iov_base != NULL) - { - FREE(table->uri.cache.iov_base); - } - if (table->status.cache.iov_base != NULL) - { - FREE(table->status.cache.iov_base); - } - if (table->method.cache.iov_base != NULL) - { - FREE(table->method.cache.iov_base); - } - if (table->version.cache.iov_base != NULL) - { - FREE(table->version.cache.iov_base); - } - if (table->body.cache.iov_base != NULL) - { - FREE(table->body.cache.iov_base); - } - - if (table->headers != NULL) - { - for (size_t i = 0; i < table->header_cnt; i++) - { - if (table->headers[i].key.cache.iov_base != NULL) - { - FREE(table->headers[i].key.cache.iov_base); - } - - if (table->headers[i].val.cache.iov_base != NULL) - { - FREE(table->headers[i].val.cache.iov_base); - } - } - - MEMPOOL_FREE(table->ref_mempool, table->headers); - table->headers = NULL; - } - MEMPOOL_FREE(table->ref_mempool, table); -} - -enum string_state http_decoder_table_state(struct http_decoder_table *table, enum http_item type) -{ - if (NULL == table) - { - return STRING_STATE_INIT; - } - struct http_decoder_header *header = NULL; - enum string_state state = STRING_STATE_INIT; - assert(table); - - switch (type) - { - case HTTP_ITEM_URI: - state = http_decoder_string_state(&table->uri); - break; - case HTTP_ITEM_STATUS: - state = http_decoder_string_state(&table->status); - break; - case HTTP_ITEM_METHOD: - state = http_decoder_string_state(&table->method); - break; - case HTTP_ITEM_VERSION: - state = http_decoder_string_state(&table->version); - break; - case HTTP_ITEM_HDRKEY: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - state = http_decoder_string_state(&header->key); - break; - case HTTP_ITEM_HDRVAL: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - state = http_decoder_string_state(&header->val); - break; - case HTTP_ITEM_BODY: - state = http_decoder_string_state(&table->body); - break; - default: - abort(); - break; - } - - return state; -} - -void http_decoder_table_refer(struct http_decoder_table *table, enum http_item type, const char *at, size_t len) -{ - if (NULL == table) - { - return; - } - - struct http_decoder_header *header = NULL; - assert(table); - - switch (type) - { - case HTTP_ITEM_URI: - http_decoder_string_refer(&table->uri, at, len); - break; - case HTTP_ITEM_STATUS: - http_decoder_string_refer(&table->status, at, len); - break; - case HTTP_ITEM_METHOD: - http_decoder_string_refer(&table->method, at, len); - break; - case HTTP_ITEM_VERSION: - http_decoder_string_refer(&table->version, at, len); - break; - case HTTP_ITEM_HDRKEY: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - http_decoder_string_refer(&header->key, at, len); - break; - case HTTP_ITEM_HDRVAL: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - http_decoder_string_refer(&header->val, at, len); - break; - case HTTP_ITEM_BODY: - http_decoder_string_refer(&table->body, at, len); - break; - default: - abort(); - break; - } -} - -void http_decoder_table_cache(struct http_decoder_table *table, enum http_item type) -{ - if (NULL == table) - { - return; - } - - struct http_decoder_header *header = NULL; - assert(table); - - switch (type) - { - case HTTP_ITEM_URI: - http_decoder_string_cache(&table->uri); - break; - case HTTP_ITEM_STATUS: - http_decoder_string_cache(&table->status); - break; - case HTTP_ITEM_METHOD: - http_decoder_string_cache(&table->method); - break; - case HTTP_ITEM_VERSION: - http_decoder_string_cache(&table->version); - break; - case HTTP_ITEM_HDRKEY: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - http_decoder_string_cache(&header->key); - break; - case HTTP_ITEM_HDRVAL: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - http_decoder_string_cache(&header->val); - break; - case HTTP_ITEM_BODY: - http_decoder_string_cache(&table->body); - break; - default: - abort(); - break; - } -} - -void http_decoder_table_commit(struct http_decoder_table *table, enum http_item type) -{ - if (NULL == table) - { - return; - } - - size_t i = 0; - struct http_decoder_header *header = NULL; - assert(table); - - switch (type) - { - case HTTP_ITEM_URI: - http_decoder_string_commit(&table->uri); - break; - case HTTP_ITEM_STATUS: - http_decoder_string_commit(&table->status); - break; - case HTTP_ITEM_METHOD: - http_decoder_string_commit(&table->method); - break; - case HTTP_ITEM_VERSION: - http_decoder_string_commit(&table->version); - break; - case HTTP_ITEM_HDRKEY: - assert(table->header_index < table->header_cnt); - header = &table->headers[table->header_index]; - http_decoder_string_commit(&header->key); - break; - case HTTP_ITEM_HDRVAL: - header = &table->headers[table->header_index]; - http_decoder_string_commit(&header->val); - // inc index - if ((table->header_index + 1) >= table->header_cnt) - { - struct http_decoder_header *old_headers = table->headers; - table->headers = - MEMPOOL_CALLOC(table->ref_mempool, struct http_decoder_header, - table->header_cnt * 2); - table->header_cnt *= 2; - - for (i = 0; i <= table->header_index; i++) - { - table->headers[i] = old_headers[i]; - } - - MEMPOOL_FREE(table->ref_mempool, old_headers); - - for (i = table->header_index + 1; i < table->header_cnt; i++) - { - header = &table->headers[i]; - memset(header, 0, sizeof(struct http_decoder_header)); - http_decoder_string_init(&header->key, MAX_HEADER_KEY_CACHE_SIZE); - http_decoder_string_init(&header->val, MAX_HEADER_VALUE_CACHE_SIZE); - } - } - table->header_index++; - break; - case HTTP_ITEM_BODY: - http_decoder_string_commit(&table->body); - break; - default: - abort(); - break; - } -} - -void http_decoder_table_reset(struct http_decoder_table *table, enum http_item type) -{ - if (NULL == table) - { - return; - } - - struct http_decoder_header *header = NULL; - assert(table); - - switch (type) - { - case HTTP_ITEM_URI: - http_decoder_string_reset(&table->uri); - break; - case HTTP_ITEM_STATUS: - http_decoder_string_reset(&table->status); - break; - case HTTP_ITEM_METHOD: - http_decoder_string_reset(&table->method); - break; - case HTTP_ITEM_VERSION: - http_decoder_string_reset(&table->version); - break; - case HTTP_ITEM_HDRKEY: - header = &table->headers[table->header_index]; - http_decoder_string_reset(&header->key); - break; - case HTTP_ITEM_HDRVAL: - header = &table->headers[table->header_index]; - http_decoder_string_reset(&header->val); - break; - case HTTP_ITEM_BODY: - http_decoder_string_reset(&table->body); - break; - default: - abort(); - break; - } -} - -void http_decoder_table_reinit(struct http_decoder_table *table) -{ - assert(table); - struct http_decoder_header *header = NULL; - - http_decoder_string_reinit(&table->uri); - http_decoder_string_reinit(&table->status); - http_decoder_string_reinit(&table->method); - http_decoder_string_reinit(&table->version); - // for (size_t i = 0; i < table->header_iter; i++) { - for (size_t i = 0; i < table->commit_header_index; i++) - { - // todo, reset header_index, avoid realloc headers as much as possible - header = &table->headers[i]; - http_decoder_string_reinit(&header->key); - http_decoder_string_reinit(&header->val); - } - - http_decoder_string_reinit(&table->body); -} - -void http_decoder_table_dump(struct http_decoder_table *table) -{ - if (NULL == table) - { - return; - } - - http_decoder_string_dump(&table->uri, "uri"); - http_decoder_string_dump(&table->status, "status"); - http_decoder_string_dump(&table->method, "method"); - http_decoder_string_dump(&table->version, "version"); - http_decoder_string_dump(&table->body, "body"); - - for (size_t i = 0; i < table->header_cnt; i++) - { - struct http_decoder_header *header = &table->headers[i]; - if (NULL == header) - { - continue; - } - - http_decoder_string_dump(&header->key, "key"); - http_decoder_string_dump(&header->val, "val"); - } -} - -int http_decoder_table_get_uri(const struct http_decoder_table *table, char **out, size_t *out_len) -{ - if (NULL == table || NULL == out) - { - return -1; - } - return http_decoder_string_get(&table->uri, out, out_len); -} - -int http_decoder_table_get_method(const struct http_decoder_table *table, char **out, size_t *out_len) -{ - if (NULL == table || NULL == out) - { - return -1; - } - return http_decoder_string_get(&table->method, out, out_len); -} - -int http_decoder_table_get_status(const struct http_decoder_table *table, char **out, size_t *out_len) -{ - if (NULL == table || NULL == out) - { - return -1; - } - return http_decoder_string_get(&table->status, out, out_len); -} - -int http_decoder_table_get_version(const struct http_decoder_table *table, char **out, size_t *out_len) -{ - if (NULL == table || NULL == out) - { - return -1; - } - return http_decoder_string_get(&table->version, out, out_len); -} - -int http_decoder_table_get_body(const struct http_decoder_table *table, char **out, size_t *out_len) -{ - if (NULL == table || NULL == out) - { - return -1; - } - return http_decoder_string_get(&table->body, (char **)out, out_len); -} - -int http_decoder_table_get_header(const struct http_decoder_table *table, const char *name, size_t name_len, - struct http_header_field *hdr_result) -{ - for (size_t i = 0; i < table->header_cnt; i++) - { - const struct http_decoder_header *tmp_header = &table->headers[i]; - if (tmp_header->key.commit.iov_len != name_len) - { - continue; - } - - if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT && - http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT) - { - hstring tmp_key; - http_decoder_string_get(&tmp_header->key, (char **)&tmp_key.iov_base, &tmp_key.iov_len); - - if (tmp_key.iov_len == name_len && - (0 == strncasecmp((char *)tmp_key.iov_base, name, name_len))) - { - http_decoder_string_get(&tmp_header->key, &hdr_result->name, &hdr_result->name_len); - http_decoder_string_get(&tmp_header->val, &hdr_result->value, &hdr_result->value_len); - return 0; - } - } - } - return -1; -} - -int http_decoder_table_iter_header(struct http_decoder_table *table, struct http_header_field *hdr) -{ - if (NULL == table || NULL == hdr) - { - return -1; - } - if (table->header_iter >= table->header_cnt) - { - return -1; - } - - struct http_decoder_header *tmp_header = &table->headers[table->header_iter]; - if (tmp_header != NULL) - { - if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT && - http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT) - { - - http_decoder_string_get(&tmp_header->key, &hdr->name, &hdr->name_len); - http_decoder_string_get(&tmp_header->val, &hdr->value, &hdr->value_len); - table->header_iter++; - return 1; - } - } - - hdr->name = NULL; - hdr->name_len = 0; - hdr->value = NULL; - hdr->value_len = 0; - - return -1; -} - -int http_decoder_table_reset_header_iter(struct http_decoder_table *table) -{ - table->header_iter = 0; - return 0; -} - -int http_decoder_table_has_parsed_header(struct http_decoder_table *table) -{ - // if (NULL == table || (table->header_iter == table->header_index)) { - if (NULL == table || (table->commit_header_index == table->header_index)) - { - return 0; - } - - const struct http_decoder_header *tmp_header = &table->headers[table->header_iter]; - - if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT && http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT) - { - return 1; - } - - return 0; -} - -int http_decoder_table_header_complete(struct http_decoder_table *table) -{ - if (NULL == table) - { - return -1; - } - return table->header_complete; -} - -void http_decoder_table_set_header_complete(struct http_decoder_table *table) -{ - if (NULL == table) - { - return; - } - table->header_complete = 1; -} - -void http_decoder_table_reset_header_complete(struct http_decoder_table *table) -{ - if (NULL == table) - { - return; - } - table->header_complete = 0; -} - -void http_decoder_table_update_commit_index(struct http_decoder_table *table) -{ - table->commit_header_index = table->header_index; -} - -int http_decoder_table_get_total_parsed_header(struct http_decoder_table *table) -{ - return table->header_index; -}
\ No newline at end of file diff --git a/decoders/http/http_decoder_table.h b/decoders/http/http_decoder_table.h deleted file mode 100644 index 9a8d948..0000000 --- a/decoders/http/http_decoder_table.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include <stddef.h> -#include "stellar/http.h" -#include "http_decoder_private.h" -#include "http_decoder_string.h" - -enum http_item -{ - HTTP_ITEM_URI = 0x01, - HTTP_ITEM_STATUS = 0x02, - HTTP_ITEM_METHOD = 0x03, - HTTP_ITEM_VERSION = 0x04, - HTTP_ITEM_HDRKEY = 0x05, - HTTP_ITEM_HDRVAL = 0x06, - HTTP_ITEM_BODY = 0x07, -}; - -struct http_decoder_table; -struct http_decoder_table *http_decoder_table_new(nmx_pool_t *mempool); - -void http_decoder_table_free(struct http_decoder_table *table); - -enum string_state -http_decoder_table_state(struct http_decoder_table *table, enum http_item type); - -void http_decoder_table_refer(struct http_decoder_table *table, enum http_item type, - const char *at, size_t len); - -void http_decoder_table_cache(struct http_decoder_table *table, enum http_item type); - -void http_decoder_table_commit(struct http_decoder_table *table, enum http_item type); - -void http_decoder_table_reset(struct http_decoder_table *table, enum http_item type); - -void http_decoder_table_reinit(struct http_decoder_table *table); - -void http_decoder_table_dump(struct http_decoder_table *table); - -int http_decoder_table_get_uri(const struct http_decoder_table *table, char **out, size_t *out_len); - -int http_decoder_table_get_method(const struct http_decoder_table *table, char **out, size_t *out_len); - -int http_decoder_table_get_status(const struct http_decoder_table *table, char **out, size_t *out_len); - -int http_decoder_table_get_version(const struct http_decoder_table *table, char **out, size_t *out_len); - -int http_decoder_table_get_body(const struct http_decoder_table *table, char **out, size_t *out_len); - -int http_decoder_table_get_header(const struct http_decoder_table *table, - const char *name, size_t name_len, - struct http_header_field *hdr_res); - -int http_decoder_table_iter_header(struct http_decoder_table *table, - struct http_header_field *hdr); -int http_decoder_table_reset_header_iter(struct http_decoder_table *table); -/** - * @brief Is there a parsed header - * - * @retval yes(1) no(0) - */ -int http_decoder_table_has_parsed_header(struct http_decoder_table *table); - -/** - * @brief If headers have been parsed completely - * - * @retval yes(1) no(0) - */ -int http_decoder_table_header_complete(struct http_decoder_table *table); - -/** - * @brief set flag for headers parsed completely - */ -void http_decoder_table_set_header_complete(struct http_decoder_table *table); - -void http_decoder_table_reset_header_complete(struct http_decoder_table *table); - -void http_decoder_table_update_commit_index(struct http_decoder_table *table); - -int http_decoder_table_get_total_parsed_header(struct http_decoder_table *table); diff --git a/decoders/http/http_decoder_tunnel.c b/decoders/http/http_decoder_tunnel.c index a6abda8..d1677f0 100644 --- a/decoders/http/http_decoder_tunnel.c +++ b/decoders/http/http_decoder_tunnel.c @@ -21,20 +21,17 @@ int httpd_tunnel_identify(struct http_decoder_env *httpd_env, int curdir, struct if (FLOW_TYPE_C2S == curdir) { - struct http_request_line reqline = {}; - http_decoder_half_data_get_request_line(hfdata, &reqline); - if (0 == http_strncasecmp_safe("CONNECT", (char *)reqline.method, - 7, reqline.method_len)) + const struct http_request_line *reqline = http_decoder_half_data_get_request_line(hfdata); + if (0 == http_strncasecmp_safe("CONNECT", (char *)reqline->method, 7, reqline->method_len)) { return 1; } } else { - struct http_response_line resline = {}; - http_decoder_half_data_get_response_line(hfdata, &resline); - if (resline.status_code == HTTP_STATUS_OK && 0 == http_strncasecmp_safe("Connection established", (char *)resline.status, - strlen("Connection established"), resline.status_len)) + const struct http_response_line *resline = http_decoder_half_data_get_response_line(hfdata); + if ((resline->status_code == HTTP_STATUS_OK) && (0 == http_strncasecmp_safe("Connection established", (char *)resline->status, + strlen("Connection established"), resline->status_len))) { return 1; } diff --git a/decoders/http/http_decoder_utils.c b/decoders/http/http_decoder_utils.c index 08c66b0..25795d7 100644 --- a/decoders/http/http_decoder_utils.c +++ b/decoders/http/http_decoder_utils.c @@ -1,5 +1,6 @@ #include <string.h> #include <assert.h> +#include <arpa/inet.h> #include "stellar/http.h" #include "http_decoder_private.h" @@ -33,14 +34,8 @@ const char *http_message_type_to_string(enum http_message_type type) switch (type) { - case HTTP_MESSAGE_REQ_LINE: - sname = "HTTP_MESSAGE_REQ_LINE"; - break; - case HTTP_MESSAGE_REQ_HEADER: - sname = "HTTP_MESSAGE_REQ_HEADER"; - break; - case HTTP_MESSAGE_REQ_HEADER_END: - sname = "HTTP_MESSAGE_REQ_HEADER_END"; + case HTTP_MESSAGE_REQ_LINE_HEADERS: + sname = "HTTP_MESSAGE_REQ_LINE_HEADERS"; break; case HTTP_MESSAGE_REQ_BODY_START: sname = "HTTP_MESSAGE_REQ_BODY_START"; @@ -51,14 +46,8 @@ const char *http_message_type_to_string(enum http_message_type type) case HTTP_MESSAGE_REQ_BODY_END: sname = "HTTP_MESSAGE_REQ_BODY_END"; break; - case HTTP_MESSAGE_RES_LINE: - sname = "HTTP_MESSAGE_RES_LINE"; - break; - case HTTP_MESSAGE_RES_HEADER: - sname = "HTTP_MESSAGE_RES_HEADER"; - break; - case HTTP_MESSAGE_RES_HEADER_END: - sname = "HTTP_MESSAGE_RES_HEADER_END"; + case HTTP_MESSAGE_RES_LINE_HEADERS: + sname = "HTTP_MESSAGE_RES_LINE_HEADERS"; break; case HTTP_MESSAGE_RES_BODY_START: sname = "HTTP_MESSAGE_RES_BODY_START"; @@ -89,18 +78,14 @@ int http_message_type_is_req(struct session *sess, enum http_message_type msg_ty switch (msg_type) { - case HTTP_MESSAGE_REQ_LINE: - case HTTP_MESSAGE_REQ_HEADER: - case HTTP_MESSAGE_REQ_HEADER_END: + case HTTP_MESSAGE_REQ_LINE_HEADERS: case HTTP_MESSAGE_REQ_BODY_START: case HTTP_MESSAGE_REQ_BODY: case HTTP_MESSAGE_REQ_BODY_END: is_req_msg = 1; break; - case HTTP_MESSAGE_RES_LINE: - case HTTP_MESSAGE_RES_HEADER: - case HTTP_MESSAGE_RES_HEADER_END: + case HTTP_MESSAGE_RES_LINE_HEADERS: case HTTP_MESSAGE_RES_BODY_START: case HTTP_MESSAGE_RES_BODY: case HTTP_MESSAGE_RES_BODY_END: @@ -308,4 +293,126 @@ void httpd_session_get_addr(const struct session *sess, struct httpd_session_add break; } } -}
\ No newline at end of file +} + +void http_session_addr_ntop(const struct httpd_session_addr *sesaddr, char *buf, size_t buflen) +{ + char sip_str[INET6_ADDRSTRLEN] = {0}; + char dip_str[INET6_ADDRSTRLEN] = {0}; + uint16_t sport_host, dport_host; + if (sesaddr->ipver == 4) + { + inet_ntop(AF_INET, &sesaddr->saddr4, sip_str, sizeof(sip_str)); + inet_ntop(AF_INET, &sesaddr->daddr4, dip_str, sizeof(dip_str)); + + } + else if (sesaddr->ipver == 6) + { + inet_ntop(AF_INET6, &sesaddr->saddr6, sip_str, sizeof(sip_str)); + inet_ntop(AF_INET6, &sesaddr->daddr6, dip_str, sizeof(dip_str)); + } + sport_host = ntohs(sesaddr->sport); + dport_host = ntohs(sesaddr->dport); + snprintf(buf, buflen, "%s:%u-%s:%u", sip_str, sport_host, dip_str, dport_host); +} + +struct http_buffer *http_buffer_new(void) +{ + struct http_buffer *buffer = CALLOC(struct http_buffer, 1); + buffer->buffer = NULL; + buffer->buffer_size = 0; + return buffer; +} + +void http_buffer_free(struct http_buffer *buffer) +{ + if (NULL == buffer) + { + return; + } + FREE(buffer->buffer); + FREE(buffer); +} + +int http_buffer_add(struct http_buffer *buffer, const char *data, size_t data_len) +{ + if (NULL == buffer || NULL == data || 0 == data_len) + { + return -1; + } + buffer->buffer = REALLOC(char, buffer->buffer, buffer->buffer_size + data_len); + memcpy(buffer->buffer + buffer->buffer_size, data, data_len); + buffer->buffer_size += data_len; + return 0; +} + +int http_buffer_read(struct http_buffer *buffer, char **data, size_t *data_len) +{ + if (NULL == buffer) + { + if (data) + { + *data = NULL; + } + if (data_len) + { + *data_len = 0; + } + return -1; + } + *data = buffer->buffer; + *data_len = buffer->buffer_size; + return 0; +} + +char *http_string_dup(const char *str, size_t len) +{ + if (NULL == str || 0 == len) + { + return NULL; + } + char *new_str = ALLOC(char, len); + memcpy(new_str, str, len); + return new_str; +} + +enum http_method_type http_get_method(const char *method, size_t method_len) +{ + enum http_method_type type = HTTP_METHOD_UNKNOWN; + + if (NULL == method || 0 == method_len) + { + return type; + } + + if (http_strncasecmp_safe(method, "GET", method_len, 3) == 0) + { + type = HTTP_METHOD_GET; + } + else if (http_strncasecmp_safe(method, "POST", method_len, 4) == 0) + { + type = HTTP_METHOD_POST; + } + else if (http_strncasecmp_safe(method, "HEAD", method_len, 4) == 0) + { + type = HTTP_METHOD_HEAD; + } + else if (http_strncasecmp_safe(method, "PUT", method_len, 3) == 0) + { + type = HTTP_METHOD_PUT; + } + else if (http_strncasecmp_safe(method, "DELETE", method_len, 6) == 0) + { + type = HTTP_METHOD_DELETE; + } + else if (http_strncasecmp_safe(method, "CONNECT", method_len, 7) == 0) + { + type = HTTP_METHOD_CONNECT; + } + else if (http_strncasecmp_safe(method, "OPTIONS", method_len, 7) == 0) + { + type = HTTP_METHOD_OPTIONS; + } + + return type; +} diff --git a/decoders/http/http_decoder_utils.h b/decoders/http/http_decoder_utils.h index 01a32b2..a8d2d46 100644 --- a/decoders/http/http_decoder_utils.h +++ b/decoders/http/http_decoder_utils.h @@ -71,9 +71,29 @@ struct httpd_session_addr union { uint32_t saddr4; - uint32_t daddr4; struct in6_addr saddr6; + }; + union + { + uint32_t daddr4; struct in6_addr daddr6; }; }; +/* + why not use libevent evbuffer? + 1. evbuffer is a buffer chain, it is not suitable for http half flow cache; + 2. http_half_flow_buffer is a whole continuous buffer; + */ +struct http_buffer +{ + char *buffer; + size_t buffer_size; +}; + void httpd_session_get_addr(const struct session *sess, struct httpd_session_addr *addr); +void http_session_addr_ntop(const struct httpd_session_addr *sesaddr, char *buf, size_t buflen); +struct http_buffer *http_buffer_new(void); +void http_buffer_free(struct http_buffer *buffer); +int http_buffer_add(struct http_buffer *buffer, const char *data, size_t data_len); +int http_buffer_read(struct http_buffer *buffer, char **data, size_t *data_len); +char *http_string_dup(const char *str, size_t len);
\ No newline at end of file diff --git a/decoders/http/version.map b/decoders/http/version.map index a64b729..eacc6bc 100644 --- a/decoders/http/version.map +++ b/decoders/http/version.map @@ -6,6 +6,7 @@ global: http_decoder_exit; http_decoder_tcp_stream_msg_cb; http_url_decode; + http_get_method; }; local: *; };
\ No newline at end of file |
