diff --git a/common/include/tfe_http.h b/common/include/tfe_http.h index a296dfd..33503a6 100644 --- a/common/include/tfe_http.h +++ b/common/include/tfe_http.h @@ -1,7 +1,13 @@ #pragma once - -#include #include +#include +#include +#include +#include + +#include +#include +#include /* Copy from http_parser.h */ #define HTTP_METHOD_MAP(XX) \ @@ -84,82 +90,6 @@ enum tfe_http_std_field TFE_HTTP_ACCEPT_ENCODING, }; -struct tfe_http_req_spec -{ - int method; - char * uri; - char * host; - char * url; //uri+host - char * accept_encoding; -}; - -struct tfe_http_resp_spec -{ - int resp_code; - char * content_encoding; -}; - -enum tfe_http_direction -{ - TFE_HTTP_REQUEST = 1, - TFE_HTTP_RESPONSE = 2 -}; - -struct tfe_http_half -{ - enum tfe_http_direction direction; - short major_version; //HTTP/1.x or HTTP/ 2 - short minor_version; //HTTP 1.1 or 1.0 - - union - { - struct tfe_http_req_spec req_spec; - struct tfe_http_resp_spec resp_spec; - }; - - unsigned int field_cnt; - uint64_t cont_len; - uint64_t cont_range_from; - uint64_t cont_range_to; - struct evbuffer * body; -}; - -struct tfe_http_session -{ - int session_id;//? - int major_version;//1:HTTP 1.x, 2:HTTP 2 - struct tfe_http_half * req; - struct tfe_http_half * resp;//value is NULL before response received. -}; - -struct http_field_name -{ - enum tfe_http_std_field field_id; - char * field_name; //Non-NULL when field_id isHTTP_UNKNOWN_FIELD. -}; - -const char * tfe_http_field_read(const struct tfe_http_half * half, const struct http_field_name * name); -int tfe_http_field_to_range(const char * field_value, long * range_from, long * range_to); -int tfe_http_field_to_digit(const char * field_value, long * digit); - -//******obsolete -//long tfe_http_read_num_field(const struct tfe_http_half* half, const struct http_field_name* name); - -//@Input param interator: NULL to get the first field. -//@Output param name: -//@return: field value. -const char * tfe_http_field_iterate(const struct tfe_http_half * half, void * interator, struct http_field_name * name); - -struct tfe_http_half * tfe_http_allow_write(const struct tfe_http_half * half); - -//@param value: NULL for delete -//@param name: Could be CHUNK/ENCODING -int tfe_http_field_write(struct tfe_http_half * half, const struct http_field_name * name, const char * value); - -//******obsolete - -//int tfe_http_field_read_func(const struct tfe_http_half* half, const char* name, char* value, size_t size); - enum http_ev_bit_number { REQ_HDR_BITNUM = 0, @@ -172,45 +102,221 @@ enum http_ev_bit_number RESP_BODY_END_BITNUM }; -#define EV_HTTP_REQ_HDR ((uint64_t)1<field_id == TFE_HTTP_UNKNOWN_FIELD) + { + __duplicated->field_id = TFE_HTTP_UNKNOWN_FIELD; + __duplicated->field_name = tfe_strdup(orig->field_name); + } + else + { + __duplicated->field_id = orig->field_id; + __duplicated->field_name = NULL; + } + + return __duplicated; +} + +static inline int http_field_name_compare(const struct http_field_name * lvalue, + const struct http_field_name * rvalue) +{ + if (lvalue->field_id != rvalue->field_id) + { + return (lvalue->field_id - rvalue->field_id); + } + + /* unknown field, compare field_name in string */ + if (lvalue->field_id == TFE_HTTP_UNKNOWN_FIELD) + { + return strcasecmp(lvalue->field_name, rvalue->field_name); + } + + /* field_id is equal, but not unknown, hit */ + return 0; +} + +static inline const char * tfe_http_field_read(const struct tfe_http_half * half, + const struct http_field_name * name) +{ + return half->ops->ops_http_field_read(half, name); +} + +static inline int tfe_http_field_write(struct tfe_http_half * half, + const struct http_field_name * name, const char * value) +{ + return half->ops->ops_http_field_write(half, name, value); +} + +static inline struct tfe_http_half * tfe_http_allow_write(const struct tfe_http_half * half) +{ + return half->ops->ops_http_allow_write(half); +} + +static inline const char * tfe_http_field_iterate(const struct tfe_http_half * half, + void ** interator, struct http_field_name * name) +{ + return half->ops->ops_http_field_iterate(half, interator, name); +} + +static inline int tfe_http_half_append_body(struct tfe_http_half * half, char * buff, size_t size, int flag) +{ + return half->ops->ops_append_body(half, buff, size, flag); +} + +static inline void tfe_http_half_free(struct tfe_http_half * half) +{ + return half->ops->ops_free(half); +} + +static inline struct tfe_http_session * tfe_http_session_allow_write(const struct tfe_http_session * session) +{ + return session->ops->ops_allow_write(session); +} + +static inline void tfe_http_session_detach(struct tfe_http_session * session) +{ + return session->ops->ops_detach(session); +} + +static inline void tfe_http_session_drop(struct tfe_http_session * session) +{ + return session->ops->ops_drop(session); +} + +static inline void tfe_http_session_passthrough(struct tfe_http_session * session) +{ + return session->ops->ops_passthrough(session); +} + +static inline void tfe_http_session_request_set(struct tfe_http_session * session, struct tfe_http_half * req) +{ + return session->ops->ops_request_set(session, req); +} + +static inline void tfe_http_session_response_set(struct tfe_http_session * session, struct tfe_http_half * resp) +{ + return session->ops->ops_response_set(session, resp); +} + +static inline struct tfe_http_half * tfe_http_session_request_create(struct tfe_http_session * session, + enum tfe_http_std_method method, const char * uri) +{ + return session->ops->ops_request_create(session, method, uri); +} + +static inline struct tfe_http_half * tfe_http_session_response_create(struct tfe_http_session * session, int resp_code) +{ + return session->ops->ops_response_create(session, resp_code); +} -struct tfe_http_half * tfe_http_request_create(int major_version, int method, const char * uri, const char * host); -struct tfe_http_half * tfe_http_response_create(int major_version, int resp_code); //@flag EV_HTTP_RESP_BODY_END, EV_HTTP_RESP_BODY_FULL, //suspend stream on EV_HTTP_REQ_BODY_BEGIN, resume when EV_HTTP_REQ_BODY_END. -int tfe_http_append_body(const struct tfe_http_half * half, char * buff, size_t size, int flag); -void tfe_http_half_free(struct tfe_http_half * half); -//@param half: ownership has been transfered to session, do NOT free half after setting. -void tfe_http_session_set_half(const struct tfe_http_session * session, struct tfe_http_half * half); /* handler_ @@ -233,3 +339,15 @@ rpc_finish_cb_ tfe_http_write_finish(); }; */ + + +/* TODO: transfer these declaration to ht_frame.h */ +struct ht_frame_session_ctx * http_frame_raise_session_begin(const tfe_stream * stream, + struct tfe_http_session * ht_session, unsigned int thread_id); + +void http_frame_raise_session_end(struct ht_frame_session_ctx * ss_ctx, struct tfe_stream * stream, + struct tfe_http_session * ht_session, unsigned int thread_id); + +void http_frame_raise_event(struct ht_frame_session_ctx * ht_frame, + const tfe_stream * stream, struct tfe_http_session * ht_session, enum tfe_http_event event, + const unsigned char * data, size_t datalen, unsigned int thread_id); diff --git a/common/include/tfe_plugin.h b/common/include/tfe_plugin.h index 805651e..3ebb98e 100644 --- a/common/include/tfe_plugin.h +++ b/common/include/tfe_plugin.h @@ -1,5 +1,7 @@ #pragma once + #include +#include struct tfe_proxy; struct tfe_thread_ctx; @@ -30,16 +32,20 @@ struct tfe_plugin /* SYMBOL & PROTOCOL */ const char * symbol; enum tfe_plugin_type type; - enum tfe_app_proto proto; /* PLUGIN INIT & DEINIT */ plugin_init_cb_t * on_init; plugin_deinit_cb_t * on_deinit; - /* PLUGIN STREAM ENTRIES */ + /* STREAM */ stream_open_cb_t * on_open; stream_data_cb_t * on_data; stream_close_cb_t * on_close; + + /* HTTP */ + http_session_begin_cb * on_session_begin; + http_session_data_cb * on_session_data; + http_session_end_cb * on_session_end; }; /* Register plugin */ @@ -58,3 +64,7 @@ static void __plugin_loader_##_symbol() \ _plugin.symbol = #_symbol; \ tfe_plugin_register(&_plugin); \ } + +#define TFE_PLUGIN_FOREACH(_p_info, _iterator) \ +for((_p_info) = tfe_plugin_iterate((_iterator)); (_p_info) != NULL; \ + (_p_info) = tfe_plugin_iterate((_iterator))) diff --git a/common/src/tfe_http.cpp b/common/src/tfe_http.cpp index 80e4edf..bb8d170 100644 --- a/common/src/tfe_http.cpp +++ b/common/src/tfe_http.cpp @@ -2,16 +2,7 @@ #include #include #include - -const char * tfe_http_field_read(const struct tfe_http_half * half, const struct http_field_name * name) -{ - return NULL; -} - -int tfe_http_field_write(struct tfe_http_half * half, const struct http_field_name * name, const char * value) -{ - return 0; -} +#include struct tfe_http_half * tfe_http_request_create(int major_version, int method, const char * uri, const char * host) { @@ -22,3 +13,67 @@ struct tfe_http_half * tfe_http_response_create(int major_version, int resp_code { return NULL; } + +struct ht_frame_session_ctx +{ + void ** pmes; + unsigned int nr_pmes; + struct tfe_plugin * preempt_plugin; +}; + +struct ht_frame_session_ctx * http_frame_raise_session_begin(const struct tfe_stream * stream, + struct tfe_http_session * ht_session, unsigned int thread_id) +{ + struct ht_frame_session_ctx * ss_ctx = ALLOC(struct ht_frame_session_ctx, 1); + ss_ctx->nr_pmes = tfe_plugin_total_counts(); + ss_ctx->pmes = ALLOC(void *, ss_ctx->nr_pmes); + + unsigned int __for_each_iterator = 0; + unsigned int __plugin_id = 0; + struct tfe_plugin * plugin_info_iter; + + TFE_PLUGIN_FOREACH(plugin_info_iter, &__for_each_iterator) + { + if (plugin_info_iter->on_session_begin == NULL) continue; + plugin_info_iter->on_session_begin(stream, ht_session, thread_id, &ss_ctx->pmes[__plugin_id]); + } + + return ss_ctx; +}; + +void http_frame_raise_session_end(struct ht_frame_session_ctx * ss_ctx, struct tfe_stream * stream, + struct tfe_http_session * ht_session, unsigned int thread_id) +{ + unsigned int __for_each_iterator = 0; + unsigned int __plugin_id = 0; + struct tfe_plugin * plugin_info_iter; + + TFE_PLUGIN_FOREACH(plugin_info_iter, &__for_each_iterator) + { + if (plugin_info_iter->on_session_end == NULL) continue; + plugin_info_iter->on_session_end(stream, ht_session, thread_id, &ss_ctx->pmes[__plugin_id]); + } + + free(ss_ctx->pmes); + free(ss_ctx); +} + +void http_frame_raise_event(struct ht_frame_session_ctx * ht_frame, + const struct tfe_stream * stream, struct tfe_http_session * ht_session, enum tfe_http_event event, + const unsigned char * data, size_t datalen, unsigned int thread_id) +{ + unsigned int __for_each_iterator = 0; + unsigned int __plugin_id = 0; + + struct tfe_plugin * plugin_info_iter; + TFE_PLUGIN_FOREACH(plugin_info_iter, &__for_each_iterator) + { + if (plugin_info_iter->on_session_data == NULL) + continue; + + plugin_info_iter->on_session_data(stream, ht_session, event, data, + datalen, thread_id, &ht_frame->pmes[__plugin_id]); + } + + return; +} diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index b98b893..bd9c376 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -17,6 +17,7 @@ target_link_libraries(tfe pthread dl MESA_field_stat) target_link_libraries(tfe -Wl,--whole-archive http -Wl,--no-whole-archive) +#target_link_libraries(tfe -Wl,--whole-archive decrypt-mirroring -Wl,--no-whole-archive) install(TARGETS tfe RUNTIME DESTINATION ./) diff --git a/plugin/business/decrypt-mirroring/src/decrypt_mirror_plugin.cpp b/plugin/business/decrypt-mirroring/src/decrypt_mirror_plugin.cpp index 90221a1..baa2400 100644 --- a/plugin/business/decrypt-mirroring/src/decrypt_mirror_plugin.cpp +++ b/plugin/business/decrypt-mirroring/src/decrypt_mirror_plugin.cpp @@ -42,7 +42,6 @@ void decrypt_mirror_deinit(struct tfe_proxy * proxy) struct tfe_plugin decrypt_mirror_spec={ .symbol=NULL, .type = TFE_PLUGIN_TYPE_BUSINESS, - .proto = APP_PROTO_HTTP1, //??? .on_init = decrypt_mirror_init, .on_deinit = decrypt_mirror_deinit, .on_open = decrypt_mirror_on_open_cb, diff --git a/plugin/protocol/http/include/internal/http_common.h b/plugin/protocol/http/include/internal/http_common.h index 70480b6..3feecb2 100644 --- a/plugin/protocol/http/include/internal/http_common.h +++ b/plugin/protocol/http/include/internal/http_common.h @@ -18,12 +18,15 @@ struct http_session_private struct tfe_http_session hs_public; TAILQ_ENTRY(http_session_private) next; struct http_connection_private * hc_private; + struct ht_frame_session_ctx * ht_frame; }; struct http_connection_private { /* ADDRESS */ struct tfe_stream_addr * layer_addr; + /* STREAM */ + struct tfe_stream * stream; /* SESSION LIST, REQUEST-RESPONSE PAIRS */ struct hs_private_list hs_private_list; /* IS PREEMPTED */ @@ -32,7 +35,15 @@ struct http_connection_private unsigned int session_id_counter; }; -enum http_half_status +TAILQ_HEAD(http_header_private_list, http_header_private); +struct http_header_private +{ + TAILQ_ENTRY(http_header_private) next; + struct http_field_name * field; + char * value; +}; + +enum hf_private_status { STATUS_INIT, STATUS_READING, @@ -53,6 +64,8 @@ struct http_half_private size_t parse_cursor; /* HTTP PARSER'S ERRNO */ enum http_errno parse_errno; + /* HEADER K-V */ + struct http_header_private_list header_list; /* UNDERLAY BUFFER */ int method_or_status; @@ -67,9 +80,9 @@ struct http_half_private struct evbuffer * evbuf_header_value; struct evbuffer * evbuf_body; - enum http_half_status status_header; - enum http_half_status status_body; - enum http_half_status status_message; + enum hf_private_status status_header; + enum hf_private_status status_body; + enum hf_private_status status_message; }; static inline struct http_half_private * to_hf_request_private(struct http_session_private * hs_private) @@ -88,3 +101,13 @@ static inline struct tfe_http_half * to_hf_public(struct http_half_private * hf_ { return &hf_private->hf_public; } + +static inline struct http_half_private * to_hf_private(struct tfe_http_half * hf_public) +{ + return container_of(hf_public, struct http_half_private, hf_public); +} + +static inline const struct http_half_private * to_hf_private(const struct tfe_http_half * hf_public) +{ + return container_of(hf_public, struct http_half_private, hf_public); +} diff --git a/plugin/protocol/http/src/http_entry.cpp b/plugin/protocol/http/src/http_entry.cpp index fe641c2..283655a 100644 --- a/plugin/protocol/http/src/http_entry.cpp +++ b/plugin/protocol/http/src/http_entry.cpp @@ -23,13 +23,12 @@ void http_plugin_deinit(struct tfe_proxy * proxy) return; } -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_session_private * __hs_private = ALLOC(struct http_session_private, 1); /* HS-PUBLIC */ - __hs_private->hs_public.major_version = 1; __hs_private->hs_public.req = hf_private_req != NULL ? to_hf_public(hf_private_req) : NULL; __hs_private->hs_public.resp = hf_private_req != NULL ? to_hf_public(hf_private_resp) : NULL; __hs_private->hs_public.session_id = hc_private->session_id_counter++; @@ -92,6 +91,16 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea __new_session: hf_private_request = hf_private_create(TFE_HTTP_REQUEST, 1, 0); hs_private = hs_private_create(hc_private, hf_private_request, NULL); + + /* Call business plugin */ + hs_private->ht_frame = http_frame_raise_session_begin(stream, &hs_private->hs_public, thread_id); + if(hs_private->ht_frame == NULL) + { + TFE_STREAM_LOG_ERROR(stream, "Failed at raising session begin event. "); + tfe_stream_detach(stream); + return ACTION_FORWARD_DATA; + } + TAILQ_INSERT_TAIL(&hc_private->hs_private_list, hs_private, next); __parse: @@ -113,10 +122,10 @@ __parse: return ACTION_FORWARD_DATA; } - assert(ret == 1); if (hf_private_request->status_header == STATUS_COMPLETE) { - printf("===== URI: %s\n", hf_private_request->hf_public.req_spec.uri); + http_frame_raise_event(hs_private->ht_frame, stream, &hs_private->hs_public, + EV_HTTP_REQ_HDR, NULL, 0, thread_id); } /* Touch a boundary, such as the end of HTTP headers, bodys, et al. @@ -195,7 +204,6 @@ static struct tfe_plugin __http_plugin_info = { .symbol = "HTTP", .type = TFE_PLUGIN_TYPE_PROTOCOL, - .proto = APP_PROTO_HTTP1, .on_init = http_plugin_init, .on_deinit = http_plugin_deinit, .on_open = http_connection_entry_open, diff --git a/plugin/protocol/http/src/http_half.cpp b/plugin/protocol/http/src/http_half.cpp index 1d08301..35c2011 100644 --- a/plugin/protocol/http/src/http_half.cpp +++ b/plugin/protocol/http/src/http_half.cpp @@ -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: