summaryrefslogtreecommitdiff
path: root/decoders/http/http_decoder_half.h
diff options
context:
space:
mode:
Diffstat (limited to 'decoders/http/http_decoder_half.h')
-rw-r--r--decoders/http/http_decoder_half.h263
1 files changed, 163 insertions, 100 deletions
diff --git a/decoders/http/http_decoder_half.h b/decoders/http/http_decoder_half.h
index f525f78..6daf32c 100644
--- a/decoders/http/http_decoder_half.h
+++ b/decoders/http/http_decoder_half.h
@@ -1,109 +1,172 @@
#pragma once
+#include <stdint.h>
#include <stddef.h>
#include "stellar/session.h"
#include "stellar/http.h"
-#include "http_content_decompress.h"
-#include "http_decoder_result_queue.h"
-#include <llhttp.h>
+#include "llhttp.h"
+#include "uthash/utarray.h"
+#include "http_decoder_decompress.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define HTTP_HEADER_FIELD_RESERVE_NUM (16)
+
+#define HTTP_HEADER_FIELD_NAME_HOST "Host"
+#define HTTP_HEADER_FIELD_NAME_USER_AGENT "User-Agent"
+#define HTTP_HEADER_FIELD_NAME_REFERER "Referer"
+#define HTTP_HEADER_FIELD_NAME_COOKIE "Cookie"
+#define HTTP_HEADER_FIELD_NAME_SET_COOKIE "Set-Cookie"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_TYPE "Content-Type"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_LENGTH "Content-Length"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_ENCODING "Content-Encoding"
+#define HTTP_HEADER_FIELD_NAME_TRANSFER_ENCODING "Transfer-Encoding"
+
+ enum http_event
+ {
+ __HTTP_EVENT_RESERVED = 0,
+ HTTP_EVENT_REQ_INIT = 1 << 1,
+ HTTP_EVENT_REQ_LINE = 1 << 2,
+ HTTP_EVENT_REQ_HDR = 1 << 3,
+ HTTP_EVENT_REQ_HDR_END = 1 << 4,
+ HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5,
+ HTTP_EVENT_REQ_BODY_DATA = 1 << 6,
+ HTTP_EVENT_REQ_BODY_END = 1 << 7,
+ HTTP_EVENT_REQ_END = 1 << 8,
+
+ HTTP_EVENT_RES_INIT = 1 << 9,
+ HTTP_EVENT_RES_LINE = 1 << 10,
+ HTTP_EVENT_RES_HDR = 1 << 11,
+ HTTP_EVENT_RES_HDR_END = 1 << 12,
+ HTTP_EVENT_RES_BODY_BEGIN = 1 << 13,
+ HTTP_EVENT_RES_BODY_DATA = 1 << 14,
+ HTTP_EVENT_RES_BODY_END = 1 << 15,
+ HTTP_EVENT_RES_END = 1 << 16,
+ };
+
+ struct http_body
+ {
+ char *body;
+ size_t body_sz;
+ size_t offset; // accumulated
+ int is_finished;
+ };
#ifndef hstring
#include <bits/types/struct_iovec.h>
-typedef struct iovec hstring;
+ typedef struct iovec hstring;
#endif
-// only one http event is fired at a time
-enum http_event
-{
- HTTP_EVENT_REQ_INIT = 1 << 1,
- HTTP_EVENT_REQ_LINE = 1 << 2,
- HTTP_EVENT_REQ_HDR = 1 << 3,
- HTTP_EVENT_REQ_HDR_END = 1 << 4,
- HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5,
- HTTP_EVENT_REQ_BODY_DATA = 1 << 6,
- HTTP_EVENT_REQ_BODY_END = 1 << 7,
- HTTP_EVENT_REQ_END = 1 << 8,
-
- HTTP_EVENT_RES_INIT = 1 << 9,
- HTTP_EVENT_RES_LINE = 1 << 10,
- HTTP_EVENT_RES_HDR = 1 << 11,
- HTTP_EVENT_RES_HDR_END = 1 << 12,
- HTTP_EVENT_RES_BODY_BEGIN = 1 << 13,
- HTTP_EVENT_RES_BODY_DATA = 1 << 14,
- HTTP_EVENT_RES_BODY_END = 1 << 15,
- HTTP_EVENT_RES_END = 1 << 16,
-};
-
-struct http_event_context
-{
- struct http_decoder_exdata *ref_httpd_ctx;
- nmx_pool_t *ref_mempool;
- struct session *ref_session;
- struct http_decoder_result_queue *ref_queue;
-};
-
-struct http_decoder_half;
-struct http_decoder_half_data;
-struct http_decoder_env;
-
-typedef void http_event_cb(enum http_event event, struct http_decoder_half_data **data,
- struct http_event_context *ev_ctx, void *httpd_plugin_env);
-
-struct http_decoder_half *
-http_decoder_half_new(struct http_decoder_exdata *hd_ctx, nmx_pool_t *mempool, http_event_cb *event_cb,
- enum llhttp_type http_type, int decompress_switch, struct http_decoder_env *httpd_env, long long start_seq);
-
-void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half);
-
-void http_decoder_half_reinit(struct http_decoder_half *half,
- struct http_decoder_result_queue *queue,
- nmx_pool_t *mempool, struct session *sess);
-
-int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len);
-
-long long http_decoder_half_trans_count(struct http_decoder_half *half);
-
-// http decoder half data API
-struct http_decoder_half_data *
-http_decoder_half_data_new(nmx_pool_t *mempool);
-
-void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_data *data);
-
-int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
- struct http_request_line *line);
-
-int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data,
- struct http_response_line *line);
-
-int http_decoder_half_data_get_header(const struct http_decoder_half_data *data,
- const char *name, size_t name_len, struct http_header_field *hdr_res);
-
-int http_decoder_half_data_iter_header(struct http_decoder_half_data *data,
- struct http_header_field *header);
-int http_decoder_half_data_reset_header_iter(struct http_decoder_half_data *req_data);
-int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data);
-
-int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len);
-
-int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len);
-void http_half_get_lastest_decompress_buffer(struct http_decoder_half_data *data, hstring *decompress_body);
-void http_half_decompress_buffer_free(struct http_decoder_half_data *data, hstring *decompress_body);
-void http_decoder_half_data_dump(struct http_decoder_half *half);
-
-void http_decoder_get_host_feed_url(struct http_decoder_half *half);
-void http_decoder_get_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool);
-int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstring *url);
-void http_decoder_join_url(struct http_decoder_half_data *hfdata,
- nmx_pool_t *mempool,
- const struct http_header_field *host_hdr);
-int http_decoder_join_url_finally(struct http_event_context *ev_ctx,
- struct http_decoder_half_data *hfdata,
- nmx_pool_t *mempool);
-int http_half_data_get_url(struct http_decoder_half_data *res_data, const char **url_val, size_t *url_len);
-int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data);
-
-void http_half_data_update_commit_index(struct http_decoder_half_data *half_data);
-void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata *exdata);
-void http_half_update_state(struct http_decoder_half_data *hf_data, enum http_event state);
-int http_half_data_get_total_parsed_header_count(struct http_decoder_half_data *half_data);
-void http_half_get_max_transaction_seq(struct http_decoder_exdata *exdata, long long *max_req_seq, long long *max_res_seq);
-enum http_content_encoding http_half_data_get_content_encoding(struct http_decoder_half_data *hf_data); \ No newline at end of file
+ struct http_half_data
+ {
+ enum flow_type flow_dir;
+ uint32_t transaction_seq; // seq of this half flow, is last http_lalf->transaction_num value
+ union
+ {
+ struct http_request_line req_line;
+ struct http_status_line status_line;
+ };
+
+ /* headers */
+ struct http_buffer *cached_header_buffer; // maybe null
+ hstring joint_url; // malloc, need be free
+ enum http_content_encoding content_encoding_type;
+ int transfer_encoding_is_chunked; // -1: not set, 0: false, 1: true
+ UT_array *ut_filed_array; // inner struct, need to transform to header->field_array
+ struct http_header header;
+
+ /* body */
+ struct http_body raw_body;
+ struct http_content_decompress *decompress;
+ struct http_body decompress_body;
+ };
+
+ struct http_half_parser
+ {
+ llhttp_t llhttp_parser;
+ llhttp_settings_t settings;
+ struct http_half *half_ref; // used in llhttp callback context to get flow
+ };
+
+ enum http_stage
+ {
+ HTTP_STAGE_INIT = 0,
+ HTTP_STAGE_PENDING = 1, /* body without Content-Length, no Chunk-Encoding */
+ HTTP_STAGE_HEADER_PARTIAL = 2,
+ HTTP_STAGE_BODY = 3,
+ };
+
+ struct http_stage_shaper
+ {
+ enum http_stage stage;
+ char *data;
+ size_t data_len;
+ long long remain_content_length;
+ const char *headers_start; // the first header field name
+ const char *headers_end; // the last char of \r\n\r\n
+ struct http_buffer *headers_cache; /* ownership move to struct http_decoder_half_data when headers completed */
+ };
+
+ struct http_half_buffer
+ {
+ int is_malloc; // need free
+ int ref_count; // +1 when push a new message
+ char *buffer;
+ size_t buffer_size;
+ };
+
+ enum http_half_llhttp_stage_type
+ {
+ LLHTTP_STAGE_MESSAGE_BEGIN = 0,
+ LLHTTP_STAGE_URI,
+ LLHTTP_STAGE_METHOD,
+ LLHTTP_STAGE_STATUS,
+ LLHTTP_STAGE_VERSION,
+ LLHTTP_STAGE_HEADER_FIELD,
+ LLHTTP_STAGE_HEADER_FIELD_COMPLETE,
+ LLHTTP_STAGE_HEADER_VALUE,
+ LLHTTP_STAGE_HEADER_VALUE_COMPLETE,
+ LLHTTP_STAGE_HEADERS_COMPLETE,
+ LLHTTP_STAGE_BODY,
+ LLHTTP_STAGE_MESSAGE_COMPLETE,
+ __LLHTTP_STAGE_MAX,
+ };
+
+ struct http_half_llhttp_stage
+ {
+ const char *first_header_name_ptr;
+ const char *last_header_value_complete_ptr; /* at + length + 4 \r\n\r\n) */
+ const char *last_headers_complete_ptr;
+ enum http_half_llhttp_stage_type llhttp_last_stage;
+ uint8_t llhttp_cb_count[__LLHTTP_STAGE_MAX];
+ };
+
+ struct http_half
+ {
+ struct session *sess_ref;
+ struct http *http_env_ref;
+
+ uint32_t transaction_num; // accumulated of all flows in this session
+ enum http_event event;
+ // struct http_stage_shaper shaper;
+
+ struct http_half_parser parser;
+ struct http_half_data *flow_data; // malloc when every transaction start, ownership move to message when message completed
+
+ struct http_buffer *cached_header_buffer;
+ struct http_half_llhttp_stage half_stage;
+ };
+ void http_half_free(struct http_half *half);
+ void http_half_data_free(struct http_half_data *half_data);
+ void http_flow_parser_init(struct http_half_parser *flow_parser, enum llhttp_type type);
+ void http_flow_body_decompress(struct http_half_data *flow_data, const char *zipdata, size_t zipdatalen);
+ void http_event_handler(struct http_half *half, enum http_event event, struct http *httpd_env);
+ int http_flow_stage_shaping(struct http_half *half, const char *newdata, size_t newdata_len);
+ int http_half_flow_process(struct http_half *half, const char *newdata, size_t newdata_len);
+ int http_get_header_field_count(struct http_half_data *flow_data);
+ void http_flow_append_header_filed(struct http_half_data *flow_data, const char *at, size_t length);
+ void http_flow_append_header_value(struct http_half_data *flow_data, const char *at, size_t length);
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file