修正HTTP解析层处理HTTP-Header的错误流程
* 原流程在解析同一个Field-Value对时,无法正确处理Header多次调用拼成完整字符串的情况,现修正; * 原流程在处理Field-Value底层Buffer时计算长度有误,导致清空buffer时剩余最后的'\0',现修正。
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user