变更HTTP业务层回调函数定义,增加session系列操作方法定义及虚接口实现。
* 不提供业务层针对单个数据包(段)的处理函数(返回值),业务层只能对单个session定义操作; * 通过session的方法(函数)通知解析层对该session的处理方法。
This commit is contained in:
@@ -43,7 +43,7 @@ static const char * __str_std_header_field_map[] =
|
||||
static enum tfe_http_std_field __str_header_field_to_std_field_id(const char * str_field, size_t len)
|
||||
{
|
||||
/* TODO: store the header text in hash table or rbtree, or use AC multistring search algo. */
|
||||
for (int i = 0; i < TFE_DIM(__str_std_header_field_map); i++)
|
||||
for (unsigned int i = 0; i < TFE_DIM(__str_std_header_field_map); i++)
|
||||
{
|
||||
const char * __std_header_field = __str_std_header_field_map[i];
|
||||
if (__std_header_field == NULL)
|
||||
@@ -113,26 +113,19 @@ void __hf_public_req_fill_from_private(struct http_half_private * hf_private, st
|
||||
struct tfe_http_req_spec * hf_req_spec = &hf_public->req_spec;
|
||||
|
||||
/* accept-encoding, host is located in header's K-V structure */
|
||||
hf_req_spec->method = parser->method;
|
||||
const static struct http_field_name __accept_encoding_field_name =
|
||||
{
|
||||
.field_id = TFE_HTTP_ACCEPT_ENCODING,
|
||||
.field_name = NULL
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
hf_req_spec->accept_encoding = (char *)tfe_http_field_read(hf_public, &__accept_encoding_field_name);
|
||||
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);
|
||||
|
||||
/* uri is stored in underlay evbuffer, we need to append a terminal zero */
|
||||
static const char __zero = 0;
|
||||
evbuffer_add(hf_private->evbuf_uri, &__zero, sizeof(__zero));
|
||||
hf_req_spec->uri = (char *)evbuffer_pullup(hf_private->evbuf_uri, evbuffer_get_length(hf_private->evbuf_uri));
|
||||
hf_req_spec->uri = (char *) evbuffer_pullup(hf_private->evbuf_uri, evbuffer_get_length(hf_private->evbuf_uri));
|
||||
|
||||
/* TODO: URL
|
||||
* url is more complex. need to review RFC */
|
||||
@@ -153,21 +146,19 @@ void __hf_public_resp_fill_from_private(struct http_half_private * hf_private, s
|
||||
};
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* ==================================================================================================================
|
||||
* REQUEST PARSER CALLBACKS
|
||||
* ================================================================================================================== */
|
||||
|
||||
#define __HF_PRIVATE_CHANGE_STATUS(_status, _now, _to) \
|
||||
#define __HF_PRIVATE_CHANGE_STATUS(_status, _now, _to) \
|
||||
do { assert(_status == _now); _status = _to; } while(0)
|
||||
|
||||
static int __parser_callback_on_message_begin(struct http_parser * parser)
|
||||
{
|
||||
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser);
|
||||
enum tfe_http_direction direction = hf_private->hf_public.direction;
|
||||
|
||||
assert(hf_private->evbuf_uri == NULL && hf_private->evbuf_body == NULL);
|
||||
assert(hf_private->evbuf_header_field == NULL && hf_private->evbuf_header_value == NULL);
|
||||
|
||||
@@ -179,6 +170,7 @@ static int __parser_callback_on_message_begin(struct http_parser * parser)
|
||||
hf_private->status_header = STATUS_INIT;
|
||||
hf_private->status_body = STATUS_INIT;
|
||||
hf_private->status_message = STATUS_READING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,6 +227,7 @@ static int __parser_callback_on_headers_complete(http_parser * parser)
|
||||
|
||||
__HF_PRIVATE_CHANGE_STATUS(hf_private->status_header, STATUS_READING, STATUS_COMPLETE);
|
||||
__HF_PRIVATE_CHANGE_STATUS(hf_private->status_body, STATUS_INIT, STATUS_READING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,6 +261,90 @@ static http_parser_settings __http_half_parse_setting =
|
||||
.on_chunk_complete = NULL
|
||||
};
|
||||
|
||||
const char * hf_ops_field_read(const struct tfe_http_half * half, const struct http_field_name * field)
|
||||
{
|
||||
const struct http_half_private * hf_private = to_hf_private(half);
|
||||
assert(hf_private->major == 0 || hf_private->major == 1);
|
||||
|
||||
struct http_header_private * __header_iter = NULL;
|
||||
struct http_header_private * __header_found = NULL;
|
||||
|
||||
TAILQ_FOREACH(__header_iter, &hf_private->header_list, next)
|
||||
{
|
||||
if (http_field_name_compare(__header_iter->field, field) != 0) continue;
|
||||
__header_found = __header_iter;
|
||||
break;
|
||||
}
|
||||
|
||||
return __header_found != NULL ? __header_iter->value : NULL;
|
||||
}
|
||||
|
||||
int hf_ops_field_write(struct tfe_http_half * half, const struct http_field_name * name, const char * value)
|
||||
{
|
||||
struct http_half_private * hf_private = to_hf_private(half);
|
||||
assert(hf_private->major == 0 || hf_private->major == 1);
|
||||
|
||||
struct http_header_private * __header = ALLOC(struct http_header_private, 1);
|
||||
__header->field = http_field_name_duplicate(name);
|
||||
__header->value = tfe_strdup(value);
|
||||
|
||||
TAILQ_INSERT_TAIL(&hf_private->header_list, __header, next);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tfe_http_half * hf_ops_allow_write(const struct tfe_http_half * half)
|
||||
{
|
||||
return (struct tfe_http_half *) half;
|
||||
}
|
||||
|
||||
const char * hf_ops_field_iterate(const struct tfe_http_half * half, void ** iter, struct http_field_name * field)
|
||||
{
|
||||
struct http_header_private ** __header_iter = (struct http_header_private **) iter;
|
||||
const struct http_half_private * hf_private = to_hf_private(half);
|
||||
|
||||
if (*__header_iter == NULL)
|
||||
{
|
||||
*__header_iter = TAILQ_FIRST(&hf_private->header_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
*__header_iter = TAILQ_NEXT(*__header_iter, next);
|
||||
}
|
||||
|
||||
if (*__header_iter == NULL) return NULL;
|
||||
|
||||
/* Reference of inner data, user should copy it */
|
||||
field->field_id = (*__header_iter)->field->field_id;
|
||||
field->field_name = (*__header_iter)->field->field_name;
|
||||
return (*__header_iter)->value;
|
||||
}
|
||||
|
||||
int hf_ops_append_body(struct tfe_http_half * half, char * buff, size_t size, int flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hf_private_destory(struct http_half_private * hf_private)
|
||||
{
|
||||
if (hf_private->parse_object != NULL) free(hf_private->parse_object);
|
||||
free(hf_private);
|
||||
}
|
||||
|
||||
void hf_ops_free(struct tfe_http_half * half)
|
||||
{
|
||||
return hf_private_destory(to_hf_private(half));
|
||||
}
|
||||
|
||||
struct tfe_http_half_ops __http_half_ops =
|
||||
{
|
||||
.ops_http_field_read = hf_ops_field_read,
|
||||
.ops_http_field_write = hf_ops_field_write,
|
||||
.ops_http_allow_write = hf_ops_allow_write,
|
||||
.ops_http_field_iterate = hf_ops_field_iterate,
|
||||
.ops_append_body = hf_ops_append_body,
|
||||
.ops_free = hf_ops_free
|
||||
};
|
||||
|
||||
struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short major, short minor)
|
||||
{
|
||||
struct http_half_private * hf_private = ALLOC(struct http_half_private, 1);
|
||||
@@ -275,9 +352,8 @@ struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short ma
|
||||
assert(ht_dir == TFE_HTTP_REQUEST || ht_dir == TFE_HTTP_RESPONSE);
|
||||
|
||||
/* PUBLIC */
|
||||
hf_private->hf_public.major_version = major;
|
||||
hf_private->hf_public.minor_version = minor;
|
||||
hf_private->hf_public.direction = ht_dir;
|
||||
hf_private->hf_public.ops = &__http_half_ops;
|
||||
|
||||
/* PRIVATE */
|
||||
hf_private->parse_object = (struct http_parser *) malloc(sizeof(struct http_parser));
|
||||
@@ -297,12 +373,6 @@ struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short ma
|
||||
return hf_private;
|
||||
}
|
||||
|
||||
void hf_private_destory(struct http_half_private * hf_private)
|
||||
{
|
||||
if (hf_private->parse_object != NULL) free(hf_private->parse_object);
|
||||
free(hf_private);
|
||||
}
|
||||
|
||||
int hf_private_parse(struct http_half_private * hf_private, const unsigned char * data, size_t len)
|
||||
{
|
||||
assert(hf_private->parse_cursor <= len);
|
||||
@@ -322,23 +392,21 @@ int hf_private_parse(struct http_half_private * hf_private, const unsigned char
|
||||
if (sz_parsed && HTTP_PARSER_ERRNO(hf_private->parse_object) == HPE_PAUSED)
|
||||
{
|
||||
http_parser_pause(hf_private->parse_object, 0);
|
||||
ret = 1;
|
||||
goto __out;
|
||||
}
|
||||
hf_private->parse_cursor += sz_parsed;
|
||||
|
||||
/* Touch message's boundary, the parser jumps to end */
|
||||
if (hf_private->status_message == STATUS_COMPLETE)
|
||||
{
|
||||
ret = 1;
|
||||
goto __out;
|
||||
if (data[hf_private->parse_cursor] == '\r' && data[hf_private->parse_cursor + 1] == '\n')
|
||||
{
|
||||
hf_private->parse_cursor++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Some kind of exception happend */
|
||||
if (sz_parsed && HTTP_PARSER_ERRNO(hf_private->parse_object) > 0)
|
||||
if (sz_parsed != __len_with_offset)
|
||||
{
|
||||
hf_private->parse_errno = HTTP_PARSER_ERRNO(hf_private->parse_object);
|
||||
ret = -1;
|
||||
goto __out;
|
||||
ret = -1; goto __out;
|
||||
}
|
||||
|
||||
__out:
|
||||
|
||||
Reference in New Issue
Block a user