修正HTTP解析层处理HTTP-Header的错误流程

* 原流程在解析同一个Field-Value对时,无法正确处理Header多次调用拼成完整字符串的情况,现修正;
* 原流程在处理Field-Value底层Buffer时计算长度有误,导致清空buffer时剩余最后的'\0',现修正。
This commit is contained in:
Lu Qiuwen
2018-09-18 18:50:25 +08:00
parent 8dee003483
commit 9ccc3d329e
3 changed files with 38 additions and 22 deletions

View File

@@ -51,8 +51,12 @@ struct http_half_private
short minor; short minor;
struct evbuffer * evbuf_uri; struct evbuffer * evbuf_uri;
struct evbuffer * evbuf_header_field; struct evbuffer * evbuf_header_field;
struct evbuffer * evbuf_header_value; struct evbuffer * evbuf_header_value;
bool is_evbuf_header_field_set;
bool is_evbuf_header_value_set;
struct evbuffer * evbuf_body; struct evbuffer * evbuf_body;
enum hf_private_status body_status; 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); 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); void hf_private_destory(struct http_half_private * hf_private);
/** Parse the raw tcp input for HTTP half structure /** 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 hf_private_set_callback(struct http_half_private * hf_private, hf_private_cb * cb,
void * user, void (* fn_user_deleter)(void *)); 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_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); struct http_half_private * hf_private_req, struct http_half_private * hf_private_resp);

View File

@@ -67,6 +67,7 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea
/* HTTP Request and Session */ /* HTTP Request and Session */
hf_private_request = hf_private_create(TFE_HTTP_REQUEST, 1, 0); hf_private_request = hf_private_create(TFE_HTTP_REQUEST, 1, 0);
hs_private = hs_private_create(hc_private, hf_private_request, NULL); 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 */ /* Closure, catch stream, session and thread_id */
struct user_event_dispatch_closure * __closure = ALLOC(struct user_event_dispatch_closure, 1); 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, int __http_connection_identify(const struct tfe_stream * stream,
struct http_connection_private * ht_conn, const unsigned char * data, size_t len) 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); int ret = hf_private_parse(hf_private, data, len);
hf_private_destory(hf_private); hf_private_destory(hf_private);
return ret; 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_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) 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; goto __detach;
/* Protocol Identification, we need 8 bytes at least to tell it is HTTP or not */ /* Protocol Identification, we need 8 bytes at least to tell it is HTTP or not */
if (len < HTTP_INDENTIFY_LENGTH) if (len < HTTP_INDENTIFY_LENGTH) goto __detach;
{
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;
}
/* Now, we want to identify this stream */ /* Now, we want to identify this stream */
int ret = __http_connection_identify(stream, ht_conn, data, len); int ret = __http_connection_identify(stream, ht_conn, data, len);

View File

@@ -84,6 +84,8 @@ static void __http_half_header_kv_complete(struct http_half_private * hf_private
/* Write a '\0' for evbuffers */ /* Write a '\0' for evbuffers */
evbuffer_add(hf_private->evbuf_header_field, &__zero, sizeof(__zero)); evbuffer_add(hf_private->evbuf_header_field, &__zero, sizeof(__zero));
evbuffer_add(hf_private->evbuf_header_value, &__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 */ /* Convert evbuffer to const char * pair */
str_field = (const char *) evbuffer_pullup(hf_private->evbuf_header_field, sz_evbuf_field); 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: __clear_buffer:
evbuffer_drain(hf_private->evbuf_header_field, sz_evbuf_field); evbuffer_drain(hf_private->evbuf_header_field, sz_evbuf_field);
evbuffer_drain(hf_private->evbuf_header_value, sz_evbuf_value); 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) 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 */ /* accept-encoding, host is located in header's K-V structure */
hf_req_spec->method = (enum tfe_http_std_method) parser->method; hf_req_spec->method = (enum tfe_http_std_method) parser->method;
const static struct http_field_name __host_field_name = const static struct http_field_name __host_field_name =
{ {
.field_id = TFE_HTTP_HOST, .field_id = TFE_HTTP_HOST,
.field_name = NULL .field_name = NULL
}; };
hf_req_spec->host = (char *) tfe_http_field_read(hf_public, &__host_field_name); 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 /* TODO: URL
* url is more complex. need to review RFC */ * 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) 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 */ /* Status Code */
hf_resp_spec->resp_code = parser->status_code; hf_resp_spec->resp_code = parser->status_code;
const static struct http_field_name __cont_encoding_field_name = const static struct http_field_name __cont_encoding_field_name =
{ {
.field_id = TFE_HTTP_CONT_ENCODING, .field_id = TFE_HTTP_CONT_ENCODING,
.field_name = NULL .field_name = NULL
}; };
/* Content Encoding */ /* Content Encoding */
hf_resp_spec->content_encoding = (char *) tfe_http_field_read(hf_public, &__cont_encoding_field_name); 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_uri == NULL && hf_private->evbuf_body == NULL);
assert(hf_private->evbuf_header_field == NULL && hf_private->evbuf_header_value == 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_field = evbuffer_new();
hf_private->evbuf_header_value = 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->body_status = STATUS_INIT;
hf_private->message_status = STATUS_READING; 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) 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); struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser);
if (hf_private->is_evbuf_header_field_set && hf_private->is_evbuf_header_value_set)
/* Last field-value tuple doesn't push into hf_private, flush these */
if (evbuffer_get_length(hf_private->evbuf_header_field) != 0)
{ {
__http_half_header_kv_complete(hf_private); __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); 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) 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); 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); 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_settings = &__http_half_parse_setting;
hf_private->parse_object->data = hf_private; hf_private->parse_object->data = hf_private;
TAILQ_INIT(&hf_private->header_list);
return hf_private; 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; 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) int hf_private_parse(struct http_half_private * hf_private, const unsigned char * data, size_t len)
{ {
assert(hf_private->parse_cursor <= len); assert(hf_private->parse_cursor <= len);