diff --git a/plugin/protocol/http/include/internal/http_half.h b/plugin/protocol/http/include/internal/http_half.h index cbe6f61..ac88810 100644 --- a/plugin/protocol/http/include/internal/http_half.h +++ b/plugin/protocol/http/include/internal/http_half.h @@ -51,8 +51,12 @@ struct http_half_private short minor; struct evbuffer * evbuf_uri; + struct evbuffer * evbuf_header_field; struct evbuffer * evbuf_header_value; + bool is_evbuf_header_field_set; + bool is_evbuf_header_value_set; + struct evbuffer * evbuf_body; enum hf_private_status body_status; @@ -64,6 +68,7 @@ struct http_half_private }; struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short major, short minor); + void hf_private_destory(struct http_half_private * hf_private); /** Parse the raw tcp input for HTTP half structure @@ -83,5 +88,7 @@ int hf_private_parse(struct http_half_private * hf_private, const unsigned char void hf_private_set_callback(struct http_half_private * hf_private, hf_private_cb * cb, void * user, void (* fn_user_deleter)(void *)); +void hf_private_set_session(struct http_half_private * hf_private, struct http_session_private * hs_private); + struct http_session_private * hs_private_create(struct http_connection_private * hc_private, struct http_half_private * hf_private_req, struct http_half_private * hf_private_resp); diff --git a/plugin/protocol/http/src/http_entry.cpp b/plugin/protocol/http/src/http_entry.cpp index bbca1f3..c0ca9f4 100644 --- a/plugin/protocol/http/src/http_entry.cpp +++ b/plugin/protocol/http/src/http_entry.cpp @@ -67,6 +67,7 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea /* HTTP Request and Session */ hf_private_request = hf_private_create(TFE_HTTP_REQUEST, 1, 0); hs_private = hs_private_create(hc_private, hf_private_request, NULL); + hf_private_set_session(hf_private_request, hs_private); /* Closure, catch stream, session and thread_id */ struct user_event_dispatch_closure * __closure = ALLOC(struct user_event_dispatch_closure, 1); @@ -139,13 +140,13 @@ enum tfe_stream_action __http_connection_entry_on_response(const struct tfe_stre int __http_connection_identify(const struct tfe_stream * stream, struct http_connection_private * ht_conn, const unsigned char * data, size_t len) { - struct http_half_private * hf_private = hf_private_create(TFE_HTTP_RESPONSE, 1, 0); + struct http_half_private * hf_private = hf_private_create(TFE_HTTP_REQUEST, 1, 0); int ret = hf_private_parse(hf_private, data, len); hf_private_destory(hf_private); return ret; } -#define HTTP_INDENTIFY_LENGTH 8 +#define HTTP_INDENTIFY_LENGTH 4 enum tfe_stream_action http_connection_entry_data(const struct tfe_stream * stream, unsigned int thread_id, enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme) @@ -159,12 +160,7 @@ enum tfe_stream_action http_connection_entry_data(const struct tfe_stream * stre goto __detach; /* Protocol Identification, we need 8 bytes at least to tell it is HTTP or not */ - if (len < HTTP_INDENTIFY_LENGTH) - { - static const unsigned int __defer_bytes = HTTP_INDENTIFY_LENGTH; - tfe_stream_action_set_opt(stream, ACTION_OPT_DEFER_BYTES, (void *) &__defer_bytes, sizeof(__defer_bytes)); - return ACTION_DEFER_DATA; - } + if (len < HTTP_INDENTIFY_LENGTH) goto __detach; /* Now, we want to identify this stream */ int ret = __http_connection_identify(stream, ht_conn, data, len); diff --git a/plugin/protocol/http/src/http_half.cpp b/plugin/protocol/http/src/http_half.cpp index 87a6eb3..836ff18 100644 --- a/plugin/protocol/http/src/http_half.cpp +++ b/plugin/protocol/http/src/http_half.cpp @@ -84,6 +84,8 @@ static void __http_half_header_kv_complete(struct http_half_private * hf_private /* Write a '\0' for evbuffers */ evbuffer_add(hf_private->evbuf_header_field, &__zero, sizeof(__zero)); evbuffer_add(hf_private->evbuf_header_value, &__zero, sizeof(__zero)); + sz_evbuf_field = evbuffer_get_length(hf_private->evbuf_header_field); + sz_evbuf_value = evbuffer_get_length(hf_private->evbuf_header_value); /* Convert evbuffer to const char * pair */ str_field = (const char *) evbuffer_pullup(hf_private->evbuf_header_field, sz_evbuf_field); @@ -107,6 +109,8 @@ static void __http_half_header_kv_complete(struct http_half_private * hf_private __clear_buffer: evbuffer_drain(hf_private->evbuf_header_field, sz_evbuf_field); evbuffer_drain(hf_private->evbuf_header_value, sz_evbuf_value); + hf_private->is_evbuf_header_value_set = false; + hf_private->is_evbuf_header_field_set = false; } void __hf_public_req_fill_from_private(struct http_half_private * hf_private, struct http_parser * parser) @@ -117,10 +121,10 @@ void __hf_public_req_fill_from_private(struct http_half_private * hf_private, st /* accept-encoding, host is located in header's K-V structure */ hf_req_spec->method = (enum tfe_http_std_method) parser->method; const static struct http_field_name __host_field_name = - { - .field_id = TFE_HTTP_HOST, - .field_name = NULL - }; + { + .field_id = TFE_HTTP_HOST, + .field_name = NULL + }; hf_req_spec->host = (char *) tfe_http_field_read(hf_public, &__host_field_name); @@ -131,7 +135,7 @@ void __hf_public_req_fill_from_private(struct http_half_private * hf_private, st /* TODO: URL * url is more complex. need to review RFC */ - hf_req_spec->url = NULL; + hf_req_spec->url = hf_req_spec->uri; } void __hf_public_resp_fill_from_private(struct http_half_private * hf_private, struct http_parser * parser) @@ -142,10 +146,10 @@ void __hf_public_resp_fill_from_private(struct http_half_private * hf_private, s /* Status Code */ hf_resp_spec->resp_code = parser->status_code; const static struct http_field_name __cont_encoding_field_name = - { - .field_id = TFE_HTTP_CONT_ENCODING, - .field_name = NULL - }; + { + .field_id = TFE_HTTP_CONT_ENCODING, + .field_name = NULL + }; /* Content Encoding */ hf_resp_spec->content_encoding = (char *) tfe_http_field_read(hf_public, &__cont_encoding_field_name); @@ -164,11 +168,13 @@ static int __parser_callback_on_message_begin(struct http_parser * parser) assert(hf_private->evbuf_uri == NULL && hf_private->evbuf_body == NULL); assert(hf_private->evbuf_header_field == NULL && hf_private->evbuf_header_value == NULL); - hf_private->evbuf_uri = evbuffer_new(); hf_private->evbuf_header_field = evbuffer_new(); hf_private->evbuf_header_value = evbuffer_new(); - hf_private->evbuf_body = evbuffer_new(); + hf_private->is_evbuf_header_field_set = false; + hf_private->is_evbuf_header_value_set = false; + hf_private->evbuf_uri = evbuffer_new(); + hf_private->evbuf_body = evbuffer_new(); hf_private->body_status = STATUS_INIT; hf_private->message_status = STATUS_READING; @@ -186,19 +192,19 @@ static int __parser_callback_on_uri_field(struct http_parser * parser, const cha static int __parser_callback_on_header_field(struct http_parser * parser, const char * at, size_t length) { struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser); - - /* Last field-value tuple doesn't push into hf_private, flush these */ - if (evbuffer_get_length(hf_private->evbuf_header_field) != 0) + if (hf_private->is_evbuf_header_field_set && hf_private->is_evbuf_header_value_set) { __http_half_header_kv_complete(hf_private); } + hf_private->is_evbuf_header_field_set = true; return evbuffer_add(hf_private->evbuf_header_field, at, length); } static int __parser_callback_on_header_value(struct http_parser * parser, const char * at, size_t length) { struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser); + hf_private->is_evbuf_header_value_set = true; return evbuffer_add(hf_private->evbuf_header_value, at, length); } @@ -429,6 +435,8 @@ struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short ma hf_private->parse_settings = &__http_half_parse_setting; hf_private->parse_object->data = hf_private; + + TAILQ_INIT(&hf_private->header_list); return hf_private; } @@ -440,6 +448,11 @@ void hf_private_set_callback(struct http_half_private * hf_private, hf_private_c hf_private->event_cb_user_deleter = user_deleter; } +void hf_private_set_session(struct http_half_private * hf_private, struct http_session_private * hs_private) +{ + hf_private->session = hs_private; +} + int hf_private_parse(struct http_half_private * hf_private, const unsigned char * data, size_t len) { assert(hf_private->parse_cursor <= len);