diff options
| author | Lu <[email protected]> | 2018-06-19 20:22:36 +0800 |
|---|---|---|
| committer | Lu <[email protected]> | 2018-06-19 20:22:36 +0800 |
| commit | cd3eca7a277db00302675149b1416ba330de8065 (patch) | |
| tree | 7991ff9995be555ea17094838a5b43b8b6a980c7 | |
| parent | 1e11d48dadf8a1c8b948228ef15a386c213df1c1 (diff) | |
HttpRedirect功能测试通过
| -rw-r--r-- | .idea/deployment.xml | 3 | ||||
| -rw-r--r-- | src/http.h | 69 | ||||
| -rw-r--r-- | src/http1.cc | 213 | ||||
| -rw-r--r-- | src/httpaction.cc | 31 | ||||
| -rw-r--r-- | src/httpscan.cc | 82 | ||||
| -rw-r--r-- | src/httpscan.h | 2 | ||||
| -rw-r--r-- | src/main.cc | 2 | ||||
| -rw-r--r-- | src/pxyconn.cc | 9 |
8 files changed, 257 insertions, 154 deletions
diff --git a/.idea/deployment.xml b/.idea/deployment.xml index 5984ae4..973b3f5 100644 --- a/.idea/deployment.xml +++ b/.idea/deployment.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="PublishConfigData" autoUpload="Always" serverName="192.168.10.8"> + <component name="PublishConfigData" autoUpload="Always" serverName="192.168.10.8" uploadOnCheckin="c2739693-9faa-43db-93c3-ffb0f69c0233"> <serverData> <paths name="192.168.10.8"> <serverdata> @@ -23,6 +23,7 @@ </serverdata> </paths> </serverData> + <option name="myUploadOnCheckinName" value="192.168.10.8" /> <option name="myAutoUpload" value="ALWAYS" /> </component> </project>
\ No newline at end of file @@ -48,6 +48,8 @@ public: /* 四元组信息获取 */ virtual const struct sockaddr * SockAddrSource() const = 0; virtual const struct sockaddr * SockAddrDest() const = 0; + + virtual void Write(std::unique_ptr<HttpSession> http_session) = 0; virtual void Close() = 0; protected: @@ -79,11 +81,6 @@ public: HttpConnection & connection() const { return http_connection_; } - void context(const std::shared_ptr<void> & ctx) - { context_ = ctx; } - const std::shared_ptr<void> & context() - { return context_; } - virtual void SetRequestHeaderCallback(http_session_cb_t cb) { request_header_cb_ = cb; } virtual void SetRequestBodyCallback(http_session_cb_t cb) @@ -94,13 +91,34 @@ public: { response_body_cb_ = cb; } virtual void CallRequestHeaderCallback() - { request_header_cb_(*this); } + { __call_session_callback(request_header_cb_, tag_request_header_cb_); } virtual void CallRequestBodyCallback() - { request_body_cb_(*this); } + { __call_session_callback(request_body_cb_, tag_request_body_cb_); } virtual void CallResponseHeaderCallback() - { response_header_cb_(*this); } + { __call_session_callback(response_header_cb_, tag_response_header_cb_); } virtual void CallResponseBodyCallback() - { response_body_cb_(*this); } + { __call_session_callback(response_body_cb_, tag_response_body_cb_); } + + enum CallbackTag + { + kCallbackTagIgnore, + kCallBackTagOnce, + kCallbackTagRepeat + }; + + virtual void SetRequestHeaderTag(enum CallbackTag tag) + { tag_request_header_cb_ = tag; } + virtual void SetRequestBodyTag(enum CallbackTag tag) + { tag_request_body_cb_ = tag; } + virtual void SetResponseHeaderTag(enum CallbackTag tag) + { tag_response_header_cb_ = tag; } + virtual void SetResponseBodyTag(enum CallbackTag tag) + { tag_response_body_cb_ = tag; } + + virtual void DropMe() + { need_to_drop_ = true; } + virtual bool NeedToDrop() + { return need_to_drop_; } protected: HttpConnection & http_connection_; @@ -113,6 +131,26 @@ protected: http_session_cb_t request_body_cb_{nullptr}; http_session_cb_t response_header_cb_{nullptr}; http_session_cb_t response_body_cb_{nullptr}; + + /* Call tag */ + enum CallbackTag tag_request_header_cb_{kCallBackTagOnce}; + enum CallbackTag tag_request_body_cb_{kCallBackTagOnce}; + enum CallbackTag tag_response_header_cb_{kCallBackTagOnce}; + enum CallbackTag tag_response_body_cb_{kCallBackTagOnce}; + + /* Drop tag */ + bool need_to_drop_{false}; + +private: + void __call_session_callback(const http_session_cb_t & cb, enum CallbackTag & cb_tag) + { + while (cb_tag != kCallbackTagIgnore) + { + cb(*this); + if (cb_tag == kCallBackTagOnce) cb_tag = kCallbackTagIgnore; + if (cb_tag == kCallbackTagRepeat) cb_tag = kCallBackTagOnce; + } + } }; class HttpRequest @@ -176,15 +214,16 @@ public: }; std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version); -std::unique_ptr<HttpResponse> HttpResponseFactory(int primary_version, int second_version); +std::unique_ptr<HttpResponse> HttpResponseFactory(short major_version, short minor_version); #include "pxyconn.h" class Http1Connection : public HttpConnection { public: - Http1Connection(const struct sockaddr_storage & source, const struct sockaddr_storage & dest) - : sockaddr_source_(source), sockaddr_dest_(dest) + Http1Connection(struct bufferevent * bev_downstream, struct bufferevent * bev_upstream, + const struct sockaddr_storage & source, const struct sockaddr_storage & dest) + : bev_downstream_(bev_downstream), bev_upstream_(bev_upstream), sockaddr_source_(source), sockaddr_dest_(dest) {} ~Http1Connection() = default; @@ -200,6 +239,8 @@ public: int on_connection_read_response(pxy_conn_ctx_t * conn_ctx, struct bufferevent * bev); int on_connection_close(pxy_conn_ctx_t * conn_ctx, struct bufferevent * bev); + void Write(std::unique_ptr<HttpSession> http_session) override; + const sockaddr * SockAddrSource() const override; const sockaddr * SockAddrDest() const override; @@ -217,6 +258,10 @@ private: /* connection info */ struct sockaddr_storage sockaddr_source_; struct sockaddr_storage sockaddr_dest_; + + /* upstream bev */ + struct bufferevent * bev_upstream_; + struct bufferevent * bev_downstream_; }; #endif //TFE_HTTP_H diff --git a/src/http1.cc b/src/http1.cc index a43474f..895b7d4 100644 --- a/src/http1.cc +++ b/src/http1.cc @@ -29,8 +29,8 @@ public: Http1Request(); virtual ~Http1Request() = default; - virtual ssize_t ConstructFromMemory(const char *buf, size_t buflen); - virtual ssize_t ConstructFromEvBuf(struct evbuffer *evbuf_ptr); + virtual ssize_t ConstructFromMemory(const char * buf, size_t buflen); + virtual ssize_t ConstructFromEvBuf(struct evbuffer * evbuf_ptr); virtual evbuffer_unique_ptr_t StolenEvbuf() { return std::move(evbuf_content_raw_); } @@ -48,10 +48,10 @@ public: bool Complete() override { return request_complete_; } - const std::string &Url() const override; - void Url(const std::string &url) override; - const std::string &HeaderValue(const std::string &field) override; - void HeaderValue(const std::string &field, const std::string &value) override; + const std::string & Url() const override; + void Url(const std::string & url) override; + const std::string & HeaderValue(const std::string & field) override; + void HeaderValue(const std::string & field, const std::string & value) override; private: std::string str_uri{}; @@ -74,25 +74,27 @@ Http1Request::Http1Request() http_parser_init(parser_.get(), HTTP_REQUEST); } -ssize_t Http1Request::ConstructFromMemory(const char *buf, size_t buflen) +ssize_t Http1Request::ConstructFromMemory(const char * buf, size_t buflen) { - static http_data_cb __http_parser_cb_on_uri = [](http_parser *parser, const char *at, size_t length) -> int + static http_data_cb __http_parser_cb_on_uri = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Request *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Request *>(parser->data); __ptr_this->str_uri = std::string(at, at + length); return 0; }; - static http_data_cb __http_parser_cb_on_header_field = [](http_parser *parser, const char *at, size_t length) -> int + static http_data_cb + __http_parser_cb_on_header_field = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Request *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Request *>(parser->data); __ptr_this->str_last_header_field_ = std::string(at, at + length); return 0; }; - static http_data_cb __http_parser_cb_on_header_value = [](http_parser *parser, const char *at, size_t length) -> int + static http_data_cb + __http_parser_cb_on_header_value = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Request *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Request *>(parser->data); __ptr_this->str_headers[__ptr_this->str_last_header_field_] = std::string(at, at + length); /* 对于Host字段,合成URL */ @@ -104,24 +106,24 @@ ssize_t Http1Request::ConstructFromMemory(const char *buf, size_t buflen) return 0; }; - static http_cb __http_parser_cb_on_message_complete = [](http_parser *parser) -> int + static http_cb __http_parser_cb_on_message_complete = [](http_parser * parser) -> int { - auto *__ptr_this = reinterpret_cast<Http1Request *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Request *>(parser->data); __ptr_this->request_complete_ = true; return 0; }; static struct http_parser_settings __parser_setting = - { - nullptr, /* on_message_begin */ - __http_parser_cb_on_uri, /* on_url */ - nullptr, /* on_status */ - __http_parser_cb_on_header_field, /* on_header_field */ - __http_parser_cb_on_header_value, /* on_header_value */ - __http_parser_cb_on_message_complete, /* on_headers_complete */ - nullptr, /* on_body */ - nullptr /* on_message_complete */ - }; + { + nullptr, /* on_message_begin */ + __http_parser_cb_on_uri, /* on_url */ + nullptr, /* on_status */ + __http_parser_cb_on_header_field, /* on_header_field */ + __http_parser_cb_on_header_value, /* on_header_value */ + __http_parser_cb_on_message_complete, /* on_headers_complete */ + nullptr, /* on_body */ + nullptr /* on_message_complete */ + }; parser_->data = this; size_t sz_parsed = http_parser_execute(parser_.get(), &__parser_setting, buf, buflen); @@ -137,10 +139,10 @@ ssize_t Http1Request::ConstructFromMemory(const char *buf, size_t buflen) return sz_parsed; } -ssize_t Http1Request::ConstructFromEvBuf(struct evbuffer *evbuf_ptr) +ssize_t Http1Request::ConstructFromEvBuf(struct evbuffer * evbuf_ptr) { /* 展平输入的Buffer为线性空间 */ - auto *__data_ptr = (const char *) (evbuffer_pullup(evbuf_ptr, -1)); + auto * __data_ptr = (const char *) (evbuffer_pullup(evbuf_ptr, -1)); size_t __data_len = evbuffer_get_length(evbuf_ptr); /* 解析输入的Buffer */ @@ -148,7 +150,7 @@ ssize_t Http1Request::ConstructFromEvBuf(struct evbuffer *evbuf_ptr) if (forward_len < 0) return forward_len; /* 已解析的部分,从原Buffer中抽离出来 */ - struct evbuffer *reserved_buffer = evbuffer_new(); + struct evbuffer * reserved_buffer = evbuffer_new(); evbuffer_remove_buffer(evbuf_ptr, reserved_buffer, static_cast<size_t>(forward_len)); /* 保存在上下文中 */ @@ -158,10 +160,10 @@ ssize_t Http1Request::ConstructFromEvBuf(struct evbuffer *evbuf_ptr) void Http1Request::ForEachHeader(HttpRequest::for_each_header_cb_t cb) { - for (auto &__iterate : str_headers) + for (auto & __iterate : str_headers) { - const std::string &__key = __iterate.first; - const std::string &__value = __iterate.second; + const std::string & __key = __iterate.first; + const std::string & __value = __iterate.second; cb(__key, __value); } @@ -169,22 +171,22 @@ void Http1Request::ForEachHeader(HttpRequest::for_each_header_cb_t cb) return; } -const std::string &Http1Request::Url() const +const std::string & Http1Request::Url() const { return str_uri; } -void Http1Request::Url(const std::string &url) +void Http1Request::Url(const std::string & url) { str_uri = url; } -const std::string &Http1Request::HeaderValue(const std::string &field) +const std::string & Http1Request::HeaderValue(const std::string & field) { return str_headers[field]; } -void Http1Request::HeaderValue(const std::string &field, const std::string &value) +void Http1Request::HeaderValue(const std::string & field, const std::string & value) { str_headers[field] = value; } @@ -193,12 +195,12 @@ void Http1Request::HeaderValue(const std::string &field, const std::string &valu // HTTP Response Parser Implementation for HTTP 1.0/1.1 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static const char *informational_phrases[] = { +static const char * informational_phrases[] = { /* 100 */ "Continue", /* 101 */ "Switching Protocols" }; -static const char *success_phrases[] = { +static const char * success_phrases[] = { /* 200 */ "OK", /* 201 */ "Created", /* 202 */ "Accepted", @@ -208,7 +210,7 @@ static const char *success_phrases[] = { /* 206 */ "Partial Content" }; -static const char *redirection_phrases[] = { +static const char * redirection_phrases[] = { /* 300 */ "Multiple Choices", /* 301 */ "Moved Permanently", /* 302 */ "Found", @@ -218,7 +220,7 @@ static const char *redirection_phrases[] = { /* 307 */ "Temporary Redirect" }; -static const char *client_error_phrases[] = { +static const char * client_error_phrases[] = { /* 400 */ "Bad Request", /* 401 */ "Unauthorized", /* 402 */ "Payment Required", @@ -239,7 +241,7 @@ static const char *client_error_phrases[] = { /* 417 */ "Expectation Failed" }; -static const char *server_error_phrases[] = { +static const char * server_error_phrases[] = { /* 500 */ "Internal Server Error", /* 501 */ "Not Implemented", /* 502 */ "Bad Gateway", @@ -248,7 +250,7 @@ static const char *server_error_phrases[] = { /* 505 */ "HTTP Version not supported" }; -const char *__resp_code_to_str(int resp_code) +const char * __resp_code_to_str(int resp_code) { if (resp_code >= 101 && resp_code <= 102) return informational_phrases[resp_code - 101]; if (resp_code >= 200 && resp_code <= 206) return success_phrases[resp_code - 200]; @@ -262,11 +264,11 @@ const char *__resp_code_to_str(int resp_code) class Http1Response : public HttpResponse { public: - Http1Response(); + Http1Response(short major_version, short minor_version); virtual ~Http1Response() = default; - virtual ssize_t ConstructFromMemory(const char *buf, size_t buflen); - virtual ssize_t ConstructFromEvBuf(struct evbuffer *evbuf_len); + virtual ssize_t ConstructFromMemory(const char * buf, size_t buflen); + virtual ssize_t ConstructFromEvBuf(struct evbuffer * evbuf_len); evbuffer_unique_ptr_t StolenEvBuf() { return std::move(evbuf_content_raw_); } @@ -284,14 +286,14 @@ public: { return parse_complete_; } virtual void Construct() final; void ResponseCode(int code) override; - const std::string &HeaderValue(const std::string &field) override; - void HeaderValue(const std::string &field, const std::string &value) override; + const std::string & HeaderValue(const std::string & field) override; + void HeaderValue(const std::string & field, const std::string & value) override; void ForEachHeader(for_each_header_cb_t cb) override; private: int resp_code_; - short resp_version_major_; - short resp_version_minor_; + short resp_version_major_{1}; + short resp_version_minor_{1}; std::map<std::string, std::string> str_headers{}; std::string str_last_header_field_{}; @@ -304,38 +306,39 @@ private: evbuffer_unique_ptr_t evbuf_content_raw_{nullptr}; }; -Http1Response::Http1Response() +Http1Response::Http1Response(short major_version, short minor_version) : resp_version_major_(major_version), + resp_version_minor_(minor_version) { http_parser_init(parser_.get(), HTTP_RESPONSE); } -ssize_t Http1Response::ConstructFromMemory(const char *buf, size_t buflen) +ssize_t Http1Response::ConstructFromMemory(const char * buf, size_t buflen) { struct http_parser_settings __parser_setting{nullptr}; - __parser_setting.on_status = [](http_parser *parser, const char *at, size_t length) -> int + __parser_setting.on_status = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Response *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Response *>(parser->data); return 0; }; - __parser_setting.on_header_field = [](http_parser *parser, const char *at, size_t length) -> int + __parser_setting.on_header_field = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Response *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Response *>(parser->data); __ptr_this->str_last_header_field_ = std::string(at, at + length); return 0; }; - __parser_setting.on_header_value = [](http_parser *parser, const char *at, size_t length) -> int + __parser_setting.on_header_value = [](http_parser * parser, const char * at, size_t length) -> int { - auto *__ptr_this = reinterpret_cast<Http1Response *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Response *>(parser->data); __ptr_this->str_headers[__ptr_this->str_last_header_field_] = std::string(at, at + length); return 0; }; - __parser_setting.on_message_complete = [](http_parser *parser) -> int + __parser_setting.on_message_complete = [](http_parser * parser) -> int { - auto *__ptr_this = reinterpret_cast<Http1Response *>(parser->data); + auto * __ptr_this = reinterpret_cast<Http1Response *>(parser->data); __ptr_this->parse_complete_ = true; return 0; }; @@ -354,10 +357,10 @@ ssize_t Http1Response::ConstructFromMemory(const char *buf, size_t buflen) return sz_parsed; } -ssize_t Http1Response::ConstructFromEvBuf(struct evbuffer *evbuf_ptr) +ssize_t Http1Response::ConstructFromEvBuf(struct evbuffer * evbuf_ptr) { /* 展平输入的Buffer为线性空间 */ - auto *__data_ptr = (const char *) (evbuffer_pullup(evbuf_ptr, -1)); + auto * __data_ptr = (const char *) (evbuffer_pullup(evbuf_ptr, -1)); size_t __data_len = evbuffer_get_length(evbuf_ptr); /* 解析输入的Buffer */ @@ -365,7 +368,7 @@ ssize_t Http1Response::ConstructFromEvBuf(struct evbuffer *evbuf_ptr) if (forward_len < 0) return forward_len; /* 已解析的部分,从原Buffer中抽离出来 */ - struct evbuffer *reserved_buffer = evbuffer_new(); + struct evbuffer * reserved_buffer = evbuffer_new(); evbuffer_remove_buffer(evbuf_ptr, reserved_buffer, static_cast<size_t>(forward_len)); /* 保存在上下文中 */ @@ -377,23 +380,27 @@ void Http1Response::Construct() { /* 新申请EvBuffer */ evbuffer_unique_ptr_t evbuf_construct = evbuffer_unique_ptr_t(evbuffer_new()); - struct evbuffer *evbuf_ptr = evbuf_construct.get(); + struct evbuffer * evbuf_ptr = evbuf_construct.get(); /* 应答第一行 */ evbuffer_add_printf(evbuf_ptr, "HTTP/%d.%d %d %s\r\n", resp_version_major_, resp_version_minor_, resp_code_, __resp_code_to_str(resp_code_)); /* 应答头部 */ - for (const auto &__iterate : str_headers) + for (const auto & __iterate : str_headers) { - const auto &__header_field = __iterate.first; - const auto &__header_value = __iterate.second; + const auto & __header_field = __iterate.first; + const auto & __header_value = __iterate.second; evbuffer_add_printf(evbuf_ptr, "%s:%s\r\n", __header_field.c_str(), __header_value.c_str()); } + /* 结尾行 */ + evbuffer_add_printf(evbuf_ptr, "\r\n"); + /* TODO: 消息体的构建 */ evbuf_content_raw_ = std::move(evbuf_construct); + parse_complete_ = true; } void Http1Response::ResponseCode(int code) @@ -401,12 +408,12 @@ void Http1Response::ResponseCode(int code) resp_code_ = code; } -const std::string &Http1Response::HeaderValue(const std::string &field) +const std::string & Http1Response::HeaderValue(const std::string & field) { return str_headers[field]; } -void Http1Response::HeaderValue(const std::string &field, const std::string &value) +void Http1Response::HeaderValue(const std::string & field, const std::string & value) { str_headers[field] = value; } @@ -416,26 +423,28 @@ void Http1Response::ForEachHeader(HttpResponse::for_each_header_cb_t cb) return; } -int Http1Connection::on_connection_close(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev) +int Http1Connection::on_connection_close(pxy_conn_ctx_t * conn_ctx, struct bufferevent * bev) { return 0; } -int Http1Connection::on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_conn_desc_t *conn_this, - pxy_conn_desc_t *conn_other) +int Http1Connection::on_connection_read_request(pxy_conn_ctx_t * conn_ctx, pxy_conn_desc_t * conn_this, + pxy_conn_desc_t * conn_other) { /* Get the last session */ auto & http_session = last_uncomplete_session(); auto & request = dynamic_cast<Http1Request &>(http_session.request()); - auto *downstream_evbuf = bufferevent_get_input(conn_this->bev); - auto *upstream_evbuf = bufferevent_get_output(conn_other->bev); + auto * downstream_evbuf = bufferevent_get_input(conn_this->bev); + auto * upstream_evbuf = bufferevent_get_output(conn_other->bev); ssize_t forward_len = request.ConstructFromEvBuf(downstream_evbuf); if (forward_len < 0) { - LOG(DEBUG) << "RequestConstructFromEvBuf Failed, connection turns to passthrough"; + LOG(DEBUG) << "ctx = " << conn_ctx << " " + << "RequestConstructFromEvBuf Failed, connection turns to passthrough"; + conn_ctx->passthrough = 1; return 0; } @@ -450,18 +459,15 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_co { http_session.CallRequestHeaderCallback(); http_session.CallRequestBodyCallback(); + } - /* 转发请求 */ - if (request.Forward()) - { - auto stolen_raw_evbuf = request.StolenEvbuf(); - evbuffer_add_buffer(upstream_evbuf, stolen_raw_evbuf.release()); - } - + if (http_session.NeedToDrop()) + { + drop_last_session(); return 0; } - if (request.ReadOnly()) + if (request.ReadOnly() || request.Complete()) { evbuffer_add_buffer(upstream_evbuf, request.StolenEvbuf().release()); return 0; @@ -470,12 +476,12 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_co return 0; } -int Http1Connection::on_connection_read_response(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev) +int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, struct bufferevent * bev) { return 0; } -HttpSession &Http1Connection::create_new_session() +HttpSession & Http1Connection::create_new_session() { /* Create new session, set a new request */ auto __http_session = std::unique_ptr<HttpSession>(new HttpSession(*this)); @@ -489,7 +495,7 @@ HttpSession &Http1Connection::create_new_session() return *http_sessions_.back(); } -HttpSession &Http1Connection::last_uncomplete_session() +HttpSession & Http1Connection::last_uncomplete_session() { if (http_sessions_.cbegin() == http_sessions_.cend()) return create_new_session(); @@ -516,14 +522,34 @@ void Http1Connection::drop_first_session() http_sessions_.pop_front(); } -const sockaddr *Http1Connection::SockAddrSource() const +const sockaddr * Http1Connection::SockAddrSource() const +{ + return (const sockaddr *) &sockaddr_source_; +} + +const sockaddr * Http1Connection::SockAddrDest() const { - return (const sockaddr *)&sockaddr_source_; + return (const sockaddr *) &sockaddr_dest_; } -const sockaddr *Http1Connection::SockAddrDest() const +void Http1Connection::Write(std::unique_ptr<HttpSession> http_session) { - return (const sockaddr *)&sockaddr_dest_; + auto & http1_request = dynamic_cast<Http1Request &>(http_session->request()); + auto & http1_response = dynamic_cast<Http1Response &>(http_session->response()); + + if (http1_request.Complete()) + { + auto stolen_buffer = http1_request.StolenEvbuf(); + bufferevent_write_buffer(bev_upstream_, stolen_buffer.release()); + } + + if (http1_response.Complete()) + { + auto stolen_buffer = http1_response.StolenEvBuf(); + bufferevent_write_buffer(bev_downstream_, stolen_buffer.release()); + } + + return; } std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version) @@ -537,13 +563,12 @@ std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_ return nullptr; } -std::unique_ptr<HttpResponse> HttpResponseFactory(int primary_version, int second_version) +std::unique_ptr<HttpResponse> HttpResponseFactory(short major_version, short minor_version) { - if (primary_version == 1 && second_version == 0) - return std::move(std::make_unique<Http1Response>()); - if (primary_version == 1 && second_version == 1) - return std::move(std::make_unique<Http1Response>()); + if (major_version == 1 && minor_version == 0) + return std::move(std::make_unique<Http1Response>(major_version, minor_version)); + if (major_version == 1 && minor_version == 1) + return std::move(std::make_unique<Http1Response>(major_version, minor_version)); - assert(0); return nullptr; }
\ No newline at end of file diff --git a/src/httpaction.cc b/src/httpaction.cc index 897d4a1..0552c39 100644 --- a/src/httpaction.cc +++ b/src/httpaction.cc @@ -104,17 +104,32 @@ void HttpActionRedirect::Construct(const std::string &str_kv) void HttpActionRedirect::do_redirect_action(HttpSession *session) { + + auto & http_connection = session->connection(); + /* 创建新的HttpResponse */ - auto http_response = HttpResponseFactory(1, 1); + auto http_session = std::make_unique<HttpSession>(http_connection); + http_session->request(HttpRequestFactory(1, 0)); + http_session->response(HttpResponseFactory(1, 0)); /* 构建Redirect Response */ - http_response->ResponseCode(resp_code_); - http_response->HeaderValue("Location", resp_location_); - http_response->Construct(); - - /* 丢弃当前的HTTP Request,替换该请求对应的应答 */ - session->request().Forward(false); - session->response(std::move(http_response)); + auto & http_response = http_session->response(); + http_response.ResponseCode(resp_code_); + http_response.HeaderValue("Location", resp_location_); + http_response.Construct(); + + /* 写新构建的HttpSession */ + http_connection.Write(std::move(http_session)); + + /* 禁用后续的调用流程 */ + session->SetRequestHeaderTag(HttpSession::kCallbackTagIgnore); + session->SetRequestBodyTag(HttpSession::kCallbackTagIgnore); + session->SetResponseHeaderTag(HttpSession::kCallbackTagIgnore); + session->SetResponseBodyTag(HttpSession::kCallbackTagIgnore); + + /* 丢弃当前的HTTP Session */ + session->DropMe(); + return; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/httpscan.cc b/src/httpscan.cc index a2e9a34..407e1ba 100644 --- a/src/httpscan.cc +++ b/src/httpscan.cc @@ -21,14 +21,14 @@ #include "compat.h" #include "logger.h" -static int __maat_table_register_or_throw(Maat_feather_t feather, const char *str_table) +static int __maat_table_register_or_throw(Maat_feather_t feather, const char * str_table) { int table_id = Maat_table_register(feather, str_table); if (table_id < 0) throw std::runtime_error("Failed at register maat table " + std::string(str_table)); return table_id; } -HttpScan::HttpScan(struct tfe_instance *instance, struct tfe_config *config) +HttpScan::HttpScan(struct tfe_instance * instance, struct tfe_config * config) : maat_feather_ref(instance->maat_feather) { table_id_ctrl_ip = __maat_table_register_or_throw(maat_feather_ref, "PXY_CTRL_IP"); @@ -39,22 +39,22 @@ HttpScan::HttpScan(struct tfe_instance *instance, struct tfe_config *config) table_id_ctrl_http_res_body = __maat_table_register_or_throw(maat_feather_ref, "PXY_CTRL_HTTP_RES_BODY"); auto & http_module = instance->http_module; - http_module->SetHttpConnectionNewCallback([this](Http &ht, HttpConnection &ct) -> void + http_module->SetHttpConnectionNewCallback([this](Http & ht, HttpConnection & ct) -> void { this->handlerConnectionCreate(ct); }); - http_module->SetHttpConnectionCloseCallback([this](Http &ht, HttpConnection &ct) -> void + http_module->SetHttpConnectionCloseCallback([this](Http & ht, HttpConnection & ct) -> void { this->handlerConnectionClose(ct); }); } -void HttpScan::handlerConnectionCreate(HttpConnection &ct) +void HttpScan::handlerConnectionCreate(HttpConnection & ct) { /* 新Session的创建处理函数 */ auto __shared_this_ptr = shared_from_this(); - ct.SetSessionNewCallback([__shared_this_ptr](HttpSession &session) -> void + ct.SetSessionNewCallback([__shared_this_ptr](HttpSession & session) -> void { /* 创建HttpScan的Session Ctx */ auto __scan_ctx = std::make_shared<HttpScanSession>(*__shared_this_ptr); @@ -64,25 +64,25 @@ void HttpScan::handlerConnectionCreate(HttpConnection &ct) * 这样,回调时始终保持__scan_ctx的引用计数大于等于1, * 避免在回调过程中变更回调函数导致ctx析构。 */ - session.SetRequestHeaderCallback([__scan_ctx](HttpSession &session) + session.SetRequestHeaderCallback([__scan_ctx](HttpSession & session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx_stack->ScanRequestHeader(&session); }); - session.SetRequestBodyCallback([__scan_ctx](HttpSession &session) + session.SetRequestBodyCallback([__scan_ctx](HttpSession & session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanRequestBody(&session); }); - session.SetResponseHeaderCallback([__scan_ctx](HttpSession &session) + session.SetResponseHeaderCallback([__scan_ctx](HttpSession & session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanResponseHeader(&session); }); - session.SetResponseBodyCallback([__scan_ctx](HttpSession &session) + session.SetResponseBodyCallback([__scan_ctx](HttpSession & session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanResponseBody(&session); @@ -93,7 +93,7 @@ void HttpScan::handlerConnectionCreate(HttpConnection &ct) ct.SetSessionCloseCallback(nullptr); } -void HttpScan::handlerConnectionClose(HttpConnection &ct) +void HttpScan::handlerConnectionClose(HttpConnection & ct) { return; } @@ -108,7 +108,7 @@ int HttpScan::connection_bypass_do_action() return 0; } -HttpScanSession::HttpScanSession(const HttpScan &httpscan_module) : +HttpScanSession::HttpScanSession(const HttpScan & httpscan_module) : httpscan_module_ref_(httpscan_module) { } @@ -118,15 +118,15 @@ HttpScanSession::~HttpScanSession() if (maat_scan_mid_ != nullptr) Maat_clean_status(&maat_scan_mid_); } -void HttpScanSession::ScanRequestHeader(HttpSession *http_session_ctx) +void HttpScanSession::ScanRequestHeader(HttpSession * http_session_ctx) { - auto &http_request = http_session_ctx->request(); + auto & http_request = http_session_ctx->request(); int dummy[MAAT_SCAN_RESULT_]; /* 扫描IP地址,获取连接对应的四元组 */ - const auto &connection = http_session_ctx->connection(); - const auto *sockaddr_src = connection.SockAddrSource(); - const auto *sockaddr_dst = connection.SockAddrDest(); + const auto & connection = http_session_ctx->connection(); + const auto * sockaddr_src = connection.SockAddrSource(); + const auto * sockaddr_dst = connection.SockAddrDest(); /* 转换为Sapp中的四元组结构体 */ auto sapp_tuple4_ptr = sockaddr_to_sapp_ipaddr(sockaddr_src, sockaddr_dst); @@ -136,64 +136,78 @@ void HttpScanSession::ScanRequestHeader(HttpSession *http_session_ctx) httpscan_module_ref_.table_id_ctrl_ip, sapp_tuple4_ptr.get(), maat_scan_result_, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + /* 以下所有扫描命中后,配置callback tag为repeat,在本函数返回后,再次调用RequestHeader处理回调 + * 函数,执行命中动作 */ if (nr_maat_scan_result_ > 0) + { + http_session_ctx->SetRequestHeaderTag(HttpSession::kCallbackTagRepeat); return hit_config_and_do_action(http_session_ctx); + } else if (nr_maat_scan_result_ == -1) + { return hit_scan_error(); + } /* 扫描HTTP URL */ - const auto &__url = http_request.Url(); + const auto & __url = http_request.Url(); nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, httpscan_module_ref_.table_id_ctrl_http_url, CHARSET_UTF8, __url.c_str(), (int) __url.length(), maat_scan_result_, dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); if (nr_maat_scan_result_ > 0) + { + http_session_ctx->SetRequestHeaderTag(HttpSession::kCallbackTagRepeat); return hit_config_and_do_action(http_session_ctx); + } else if (nr_maat_scan_result_ == -1) + { return hit_scan_error(); + } /* 未命中HTTP URL,继续扫描其他HTTP头部字段 */ - http_request.ForEachHeader([this, http_session_ctx](const std::string &field, const std::string &value) + http_request.ForEachHeader([this, http_session_ctx](const std::string & field, const std::string & value) { /* 增强字符串表,设置区域字段,即Header字段 */ int ret = Maat_set_scan_status(httpscan_module_ref_.maat_feather_ref, &maat_scan_mid_, MAAT_SET_SCAN_DISTRICT, field.c_str(), (int) field.length()); /* 设置失败 */ - if (ret < 0) - return hit_scan_error(); - + if (ret < 0) return hit_scan_error(); int __dummy[MAAT_SCAN_RESULT_]; nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, httpscan_module_ref_.table_id_ctrl_http_req_hdr, MAAT_DEFAULT_CHARSET_, - value.c_str(), (int) value.length(), - maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + value.c_str(), (int) value.length(), maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); if (nr_maat_scan_result_ > 0) + { + http_session_ctx->SetRequestHeaderTag(HttpSession::kCallbackTagRepeat); return hit_config_and_do_action(http_session_ctx); + } else if (nr_maat_scan_result_ == -1) + { return hit_scan_error(); + } }); } -void HttpScanSession::ScanRequestBody(HttpSession *http_session_ctx) +void HttpScanSession::ScanRequestBody(HttpSession * http_session_ctx) { return; } -void HttpScanSession::ScanResponseHeader(HttpSession *http_session_ctx) +void HttpScanSession::ScanResponseHeader(HttpSession * http_session_ctx) { return; } -void HttpScanSession::ScanResponseBody(HttpSession *http_session_ctx) +void HttpScanSession::ScanResponseBody(HttpSession * http_session_ctx) { return; } -void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) +void HttpScanSession::hit_config_and_do_action(HttpSession * http_session_ctx) { /* 判断命中数量,若为多命中,选择优先级最高的动作执行 */ enum HttpActionType action_type = HttpActionType::kActionMax; @@ -205,9 +219,9 @@ void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) if (maat_scan_result_[i].action <= action_type) do_action_id = i; } - Maat_rule_t *hit_maat_rule = &maat_scan_result_[do_action_id]; + Maat_rule_t * hit_maat_rule = &maat_scan_result_[do_action_id]; auto __action_type = (enum HttpActionType) hit_maat_rule->action; - const char *__action_string = hit_maat_rule->service_defined; + const char * __action_string = hit_maat_rule->service_defined; /* 创建HttpAction的对象 */ auto action_object = HttpActionFactory(__action_type, __action_string); @@ -217,25 +231,25 @@ void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) action_object->service_id(hit_maat_rule->service_id); /* 替换HttpSession的事件处理函数,以后的事件由HttpAction处理 */ - http_session_ctx->SetRequestHeaderCallback([action_object](HttpSession &session) + http_session_ctx->SetRequestHeaderCallback([action_object](HttpSession & session) { auto __action_object = action_object; __action_object->OnRequestHeader(&session); }); - http_session_ctx->SetRequestBodyCallback([action_object](HttpSession &session) + http_session_ctx->SetRequestBodyCallback([action_object](HttpSession & session) { auto __action_object = action_object; __action_object->OnRequestBody(&session); }); - http_session_ctx->SetResponseHeaderCallback([action_object](HttpSession &session) + http_session_ctx->SetResponseHeaderCallback([action_object](HttpSession & session) { auto __action_object = action_object; __action_object->OnResponseHeader(&session); }); - http_session_ctx->SetResponseBodyCallback([action_object](HttpSession &session) + http_session_ctx->SetResponseBodyCallback([action_object](HttpSession & session) { auto __action_object = action_object; __action_object->OnResponseBody(&session); diff --git a/src/httpscan.h b/src/httpscan.h index f2892eb..529e0d1 100644 --- a/src/httpscan.h +++ b/src/httpscan.h @@ -84,6 +84,8 @@ private: Maat_rule_t maat_scan_result_[MAAT_SCAN_RESULT_]; /* 扫描命中数量 */ int nr_maat_scan_result_{0}; + /* 命中结果后,重新调用上层的处理函数 */ + bool need_to_recall_event_cb_{false}; }; #endif //TFE_HTTPSCAN_H diff --git a/src/main.cc b/src/main.cc index 98190f4..74c1e96 100644 --- a/src/main.cc +++ b/src/main.cc @@ -288,7 +288,7 @@ main(int argc, char *argv[]) opts = tfe_config_new(); g_tfe_config = opts; - event_enable_debug_logging(1); + event_enable_debug_logging(0); el::Loggers::getLogger("conntrace"); if (nat_getdefaultname()) diff --git a/src/pxyconn.cc b/src/pxyconn.cc index a0457a6..1abaa87 100644 --- a/src/pxyconn.cc +++ b/src/pxyconn.cc @@ -1356,7 +1356,9 @@ void * __http1_connection_ctx_setup(pxy_conn_ctx_t * ctx) const auto & __source_address = ctx->spec->listen_addr; const auto & __dest_address = ctx->spec->connect_addr; - auto __http1_connection_ctx = std::make_unique<Http1Connection>(__source_address, __dest_address); + auto __http1_connection_ctx = std::make_unique<Http1Connection>( + ctx->src.bev, ctx->dst.bev, __source_address, __dest_address); + auto __http_scan_ctx = std::make_shared<HttpScan>(g_tfe_instance, g_tfe_config); __http_scan_ctx->handlerConnectionCreate(*__http1_connection_ctx); @@ -1971,9 +1973,9 @@ static void pxy_fd_readcb(evutil_socket_t fd, short what, void * arg) { pxy_conn_ctx_t * ctx = (pxy_conn_ctx_t *) arg; - CLOG(DEBUG, "conntrace") << string_format("ctx = %p, fd = %d is readable", fd, what, ctx); + CLOG(DEBUG, "conntrace") << string_format("ctx = %p, fd = %d is readable", ctx, fd); CLOG(DEBUG, "conntrace") << string_format("ctx = %p, ctx->spec->http = %d, ctx->spec->ssl = %d, ctx->passthrough = %d", - ctx, ctx->spec->http, ctx->spec->ssl, ctx->passthrough); + ctx, ctx->spec->http, ctx->spec->ssl, ctx->passthrough); /* for SSL, peek ClientHello and parse SNI from it */ if (ctx->spec->ssl && !ctx->passthrough /*&& ctx->ev*/) @@ -1992,7 +1994,6 @@ static void pxy_fd_readcb(evutil_socket_t fd, short what, void * arg) if (n == 0) { - return; } |
