diff options
| author | Lu <[email protected]> | 2018-07-20 20:01:07 +0800 |
|---|---|---|
| committer | Lu <[email protected]> | 2018-07-20 20:01:07 +0800 |
| commit | 0f197cd29e6a1d9b9be7323d0105f9a3100922c3 (patch) | |
| tree | f738e790071471807c85f19772221314d86bff17 /src | |
| parent | 5b9b1e38e9f71aedbfbec04bf5c42327d4b37194 (diff) | |
#11 增加HttpSession的追踪功能,在HttpSession析构时打印四元组、URL等信息,便于诊断问题。
增加全局线程号功能,启动多线程处理功能。
Diffstat (limited to 'src')
| -rw-r--r-- | src/http.h | 293 | ||||
| -rw-r--r-- | src/http1.cc | 86 | ||||
| -rw-r--r-- | src/httpscan.cc | 18 | ||||
| -rw-r--r-- | src/main.cc | 15 | ||||
| -rw-r--r-- | src/pxythrmgr.cc | 19 | ||||
| -rw-r--r-- | src/pxythrmgr.h | 1 | ||||
| -rw-r--r-- | src/util.h | 14 |
7 files changed, 274 insertions, 172 deletions
@@ -7,6 +7,7 @@ #include <string> #include <list> +#include "util.h" #include "easylogging++.h" class HttpConnection; @@ -37,6 +38,151 @@ private: connection_cb_t connection_close_cb_; }; +class HttpHeaders +{ +public: + HttpHeaders() = default; + virtual ~HttpHeaders() = default; + + using str_field_t = std::string; + using str_value_t = std::string; + + virtual void Add(const str_field_t & str_field, const str_value_t & str_value) = 0; + virtual void Set(const str_field_t & str_field, const str_value_t & str_value) = 0; + virtual void Remove(const str_field_t & str_field) = 0; + + using for_each_cb_t = std::function<bool(const str_field_t &, const str_value_t &)>; + + virtual bool ForEachHeader(for_each_cb_t cb) const = 0; + virtual bool ForEachValueOfHeader(const str_field_t & str_field, for_each_cb_t cb) const = 0; +}; + +class HttpRequest +{ +public: + HttpRequest() = default; + virtual ~HttpRequest() = default; + + /* URL读取、设置接口 */ + virtual const std::string & Url() const = 0; + virtual void Url(const std::string & url) = 0; + + virtual const std::string & Uri() const = 0; + virtual void Uri(const std::string & url) = 0; + + /* HttpHeaders */ + virtual HttpHeaders & Headers() = 0; + virtual const HttpHeaders & cHeaders() const = 0; + + /* Request Body */ + using body_content_t = std::vector<char>; + using body_content_ptr_t = std::unique_ptr<body_content_t>; + + /* Body读取、设置接口 */ + virtual const body_content_t * Body() const = 0; + virtual void Body(body_content_ptr_t body) = 0; + + /* Body的Stolen接口 */ + virtual body_content_ptr_t StolenBody() = 0; + + /* Bypass,标记本请求为直通 + * 当请求标记为直通时,转发数据,不再调用业务处理函数 */ + virtual bool Bypass() = 0; + virtual void Bypass(bool is_bypass) = 0; + + /* ReadOnly,标记本请求为只读。 + * 当一个请求为只读请求时,业务不应修改它的内容,底层处理Readonly的请求时,应直接转发不缓存 */ + virtual bool ReadOnly() = 0; + virtual void ReadOnly(bool is_readonly) = 0; + + /* Forward,标记本请求应被转发到对端 + * 当请求标记为不转发时,该请求被丢弃 */ + virtual bool Forward() = 0; + virtual void Forward(bool is_forward) = 0; + + /* 完整标记,该请求是否已经完整可用 */ + enum section_t + { + kSectionHeader, kSectionBody, kSecionMessage + }; + virtual bool Complete(section_t section) = 0; + + /* HTTP版本 */ + using version_t = std::tuple<short, short>; + virtual version_t Version() = 0; + + /* 构建接口,根据结构化数据构建HTTP请求头部 */ + virtual void Construct() = 0; + + /* 调试接口 */ + virtual std::string DumpToString() = 0; +}; + +class HttpResponse +{ +public: + enum section_t + { + kSectionHeader, + kSectionBody, + kSectionMessage, + kSectionMax + }; + + enum section_state_t + { + kStateBegin, + kStateReading, + kStateComplete, + kStateStream, + kStateCalled, + kStateStolen + }; + +public: + HttpResponse() = default; + virtual ~HttpResponse() = default; + + /* 响应码 */ + virtual int ResponseCode() = 0; + virtual void ResponseCode(int cde) = 0; + + /* HttpHeaders */ + virtual HttpHeaders & Headers() = 0; + virtual const HttpHeaders & cHeaders() const = 0; + + /* Request Body */ + using body_content_t = std::vector<char>; + using body_content_ptr_t = std::unique_ptr<body_content_t>; + + /* Body读取、设置接口 */ + virtual const std::vector<const body_content_t *> Body() const = 0; + virtual void Body(std::vector<body_content_ptr_t> body) = 0; + virtual std::vector<body_content_ptr_t> StolenBody() = 0; + + /* ReadOnly,标记本请求为只读。 + * 当一个请求为只读请求时,业务不应修改它的内容,底层处理Readonly的请求时,应直接转发不缓存 */ + virtual bool ReadOnly() = 0; + virtual void ReadOnly(bool is_readonly) = 0; + + /* Forward,标记本请求应被转发到对端 + * 当请求标记为不转发时,该请求被丢弃 */ + virtual bool Forward() = 0; + virtual void Forward(bool is_forward) = 0; + + /* Bypass,标记本应答为直通 + * 当应答标记为直通时,转发数据,不再调用业务处理函数 */ + virtual bool Bypass() = 0; + virtual void Bypass(bool is_bypass) = 0; + + virtual section_state_t SectionState(section_t section) = 0; + /* 构建指令,根据Object构建对应的Memory */ + virtual void Construct() = 0; + + /* 调试接口 */ + virtual std::string DumpToString() = 0; +}; + class HttpConnection { public: @@ -67,7 +213,7 @@ class HttpSession { public: explicit HttpSession(HttpConnection & connection) : http_connection_(connection) {} - virtual ~HttpSession() = default; + virtual ~HttpSession() { __dump_session(); } using http_session_cb_t = std::function<void(HttpSession &)>; @@ -191,145 +337,22 @@ private: if (cb_tag == kCallbackTagRepeat) cb_tag = kCallBackTagOnlyOnce; } } -}; - -class HttpHeaders -{ -public: - HttpHeaders() = default; - virtual ~HttpHeaders() = default; - - using str_field_t = std::string; - using str_value_t = std::string; - - virtual void Add(const str_field_t & str_field, const str_value_t & str_value) = 0; - virtual void Set(const str_field_t & str_field, const str_value_t & str_value) = 0; - virtual void Remove(const str_field_t & str_field) = 0; - - using for_each_cb_t = std::function<bool(const str_field_t &, const str_value_t &)>; - - virtual bool ForEachHeader(for_each_cb_t cb) const = 0; - virtual bool ForEachValueOfHeader(const str_field_t & str_field, for_each_cb_t cb) const = 0; -}; - -class HttpRequest -{ -public: - HttpRequest() = default; - virtual ~HttpRequest() = default; - - /* URL读取、设置接口 */ - virtual const std::string & Url() const = 0; - virtual void Url(const std::string & url) = 0; - - virtual const std::string & Uri() const = 0; - virtual void Uri(const std::string & url) = 0; - - /* HttpHeaders */ - virtual HttpHeaders & Headers() = 0; - virtual const HttpHeaders & cHeaders() const = 0; - - /* Request Body */ - using body_content_t = std::vector<char>; - using body_content_ptr_t = std::unique_ptr<body_content_t>; - - /* Body读取、设置接口 */ - virtual const body_content_t * Body() const = 0; - virtual void Body(body_content_ptr_t body) = 0; - - /* Body的Stolen接口 */ - virtual body_content_ptr_t StolenBody() = 0; - - /* Bypass,标记本请求为直通 - * 当请求标记为直通时,转发数据,不再调用业务处理函数 */ - virtual bool Bypass() = 0; - virtual void Bypass(bool is_bypass) = 0; - - /* ReadOnly,标记本请求为只读。 - * 当一个请求为只读请求时,业务不应修改它的内容,底层处理Readonly的请求时,应直接转发不缓存 */ - virtual bool ReadOnly() = 0; - virtual void ReadOnly(bool is_readonly) = 0; - - /* Forward,标记本请求应被转发到对端 - * 当请求标记为不转发时,该请求被丢弃 */ - virtual bool Forward() = 0; - virtual void Forward(bool is_forward) = 0; - - /* 完整标记,该请求是否已经完整可用 */ - enum section_t - { - kSectionHeader, kSectionBody, kSecionMessage - }; - virtual bool Complete(section_t section) = 0; - - /* HTTP版本 */ - using version_t = std::tuple<short, short>; - virtual version_t Version() = 0; - - /* 构建接口,根据结构化数据构建HTTP请求头部 */ - virtual void Construct() = 0; -}; -class HttpResponse -{ -public: - enum section_t + void __dump_session() { - kSectionHeader, - kSectionBody, - kSectionMessage, - kSectionMax - }; + auto str_src_addr = sockaddr_to_string(http_connection_.SockAddrSource()); + auto str_dst_addr = sockaddr_to_string(http_connection_.SockAddrDest()); - enum section_state_t - { - kStateBegin, - kStateReading, - kStateComplete, - kStateStream, - kStateCalled, - kStateStolen - }; + auto str_request = request_->DumpToString(); + auto str_response = response_->DumpToString(); -public: - HttpResponse() = default; - virtual ~HttpResponse() = default; + std::string status{}; + if (NeedToDrop()) status += "DROP"; + if (NeedToBypass()) status += "BYPASS"; - /* 响应码 */ - virtual int ResponseCode() = 0; - virtual void ResponseCode(int cde) = 0; - - /* HttpHeaders */ - virtual HttpHeaders & Headers() = 0; - virtual const HttpHeaders & cHeaders() const = 0; - - /* Request Body */ - using body_content_t = std::vector<char>; - using body_content_ptr_t = std::unique_ptr<body_content_t>; - - /* Body读取、设置接口 */ - virtual const std::vector<const body_content_t *> Body() const = 0; - virtual void Body(std::vector<body_content_ptr_t> body) = 0; - virtual std::vector<body_content_ptr_t> StolenBody() = 0; - - /* ReadOnly,标记本请求为只读。 - * 当一个请求为只读请求时,业务不应修改它的内容,底层处理Readonly的请求时,应直接转发不缓存 */ - virtual bool ReadOnly() = 0; - virtual void ReadOnly(bool is_readonly) = 0; - - /* Forward,标记本请求应被转发到对端 - * 当请求标记为不转发时,该请求被丢弃 */ - virtual bool Forward() = 0; - virtual void Forward(bool is_forward) = 0; - - /* Bypass,标记本应答为直通 - * 当应答标记为直通时,转发数据,不再调用业务处理函数 */ - virtual bool Bypass() = 0; - virtual void Bypass(bool is_bypass) = 0; - - virtual section_state_t SectionState(section_t section) = 0; - /* 构建指令,根据Object构建对应的Memory */ - virtual void Construct() = 0; + CLOG(DEBUG, "HttpSessionTrace") << str_src_addr << str_dst_addr + << str_request << str_response << status; + } }; std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version); diff --git a/src/http1.cc b/src/http1.cc index 7b31ae2..b51635c 100644 --- a/src/http1.cc +++ b/src/http1.cc @@ -209,6 +209,8 @@ public: void Bypass(bool is_bypass) override {} + std::string DumpToString() override; + private: /* Http Version */ short major_version_{1}; @@ -356,7 +358,7 @@ ssize_t Http1Request::ConstructFromMemory(const char * buf, size_t buflen) /* 解析失败 */ if(sz_parsed && parser_->http_errno > 0) { - throw invalid_input_format(string_format("Failed at http parsing: errcode=%u, %s, %s", + throw std::runtime_error(string_format("Failed at http parsing: errcode=%u, %s, %s", parser_->http_errno, http_errno_name(static_cast<http_errno>(parser_->http_errno)), http_errno_description(static_cast<http_errno>(parser_->http_errno)))); } @@ -417,6 +419,11 @@ void Http1Request::Construct() return; } +std::string Http1Request::DumpToString() +{ + return string_format("HTTP/%d.%d %s", major_version_, minor_version_, str_url_.c_str()); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HTTP Response Parser Implementation for HTTP 1.0/1.1 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -565,8 +572,10 @@ public: } } + std::string DumpToString() override; + private: - int resp_code_; + int resp_code_{-1}; short resp_version_major_{1}; short resp_version_minor_{1}; @@ -604,6 +613,10 @@ private: Http1Headers headers_{}; std::string last_header_field_{}; + /* Headers For Debug */ + std::string content_type; + std::string content_length; + /* Parser & Raw Content * 该原始内容,等价于本结构体的序列化后的结果,因此,输入的、未经解析的字节数据,不应该保留在这个位置 */ std::unique_ptr<struct http_parser> parser_{new struct http_parser}; @@ -702,6 +715,20 @@ int Http1ResponseParserCallbacks::CallbackOnHeaderComplete(http_parser * parser) /* Flush Last HTTP Resp Header-Value */ resp_ptr->headers_.ConstructByHttpParserComplete(); + + /* Lookup Content-Type and Content-Length */ + resp_ptr->headers_.ForEachValueOfHeader("Content-Type", [resp_ptr](const std::string & f, const std::string &v) + { + resp_ptr->content_type = v; + return false; + }); + + resp_ptr->headers_.ForEachValueOfHeader("Content-Length", [resp_ptr](const std::string & f, const std::string &v) + { + resp_ptr->content_length = v; + return false; + }); + return 0; } @@ -787,7 +814,7 @@ ssize_t Http1Response::ConstructFromMemory(const char * buf, size_t buflen) /* 解析错误 */ if (sz_parsed && parser_->http_errno > 0) { - throw invalid_input_format(string_format("Failed at http parsing: errcode=%u, %s, %s", + throw std::runtime_error(string_format("Failed at http parsing: errcode=%u, %s, %s", parser_->http_errno, http_errno_name(static_cast<http_errno>(parser_->http_errno)), http_errno_description(static_cast<http_errno>(parser_->http_errno)))); } @@ -889,6 +916,11 @@ evbuffer_unique_ptr_t Http1Response::StolenEvBuf() return std::move(evbuf_content_raw_); } +std::string Http1Response::DumpToString() +{ + return {std::to_string(resp_code_) + " " + content_type + " " + content_length}; +} + int Http1Connection::on_connection_close(pxy_conn_ctx_t * conn_ctx, struct bufferevent * bev) { return 0; @@ -905,25 +937,34 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t * conn_ctx, pxy_c 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) + ssize_t forward_len = 0; + try + { + forward_len = request.ConstructFromEvBuf(downstream_evbuf); + } + catch (std::runtime_error & err) { - LOG(DEBUG) << "ctx = " << conn_ctx << " " - << "RequestConstructFromEvBuf Failed, connection turns to passthrough"; + auto str_src_addr = sockaddr_to_string(SockAddrSource()); + auto str_dst_addr = sockaddr_to_string(SockAddrDest()); + LOG(ERROR) << str_src_addr << str_dst_addr << "PASSTHROUGH" << err.what(); + conn_ctx->passthrough = 1; + return 0; + } + + if (forward_len < 0) + { conn_ctx->passthrough = 1; return 0; } if (request.Complete(HttpRequest::kSectionHeader)) { - LOG(DEBUG) << std::addressof(http_session) << "CallRequestHeaderCallback"; http_session->CallRequestHeaderCallback(); } if (request.Complete(HttpRequest::kSectionBody) && request.Body() != nullptr) { - LOG(DEBUG) << std::addressof(http_session) << "CallRequestBodyCallback"; http_session->CallRequestBodyCallback(); } @@ -946,12 +987,18 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_ pxy_conn_desc_t * conn_other) { auto * session = last_uncomplete_session(kDirectionResponse); - assert(session != nullptr); - - auto & response = dynamic_cast<Http1Response &>(session->response()); auto * downstream_evbuf = bufferevent_get_input(conn_this->bev); auto * upstream_evbuf = bufferevent_get_output(conn_other->bev); + if (session == nullptr) + { + LOG(WARNING) << "Found standlone HTTP response, Ignore it."; + LOG(WARNING) << hexdump("upstream recieve buffer", upstream_evbuf); + return 0; + } + + auto & response = dynamic_cast<Http1Response &>(session->response()); + /* 检查Bypass和Drop标记,该标记可能由请求侧设置 * 设置任何一个,即不调用上层业务函数,直接解析到消息结束 */ if (session->NeedToBypass() || session->NeedToDrop()) @@ -959,12 +1006,23 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_ response.Bypass(true); } - ssize_t forward_len = response.ConstructFromEvBuf(downstream_evbuf); - if (forward_len <= 0) + ssize_t forward_len = 0; + try { + forward_len = response.ConstructFromEvBuf(downstream_evbuf); + } + catch (std::runtime_error & err) + { + auto str_src_addr = sockaddr_to_string(SockAddrSource()); + auto str_dst_addr = sockaddr_to_string(SockAddrDest()); + + LOG(ERROR) << str_src_addr << str_dst_addr << "PASSTHROUGH" << err.what(); + conn_ctx->passthrough = 1; return 0; } + if (forward_len <= 0) return 0; + if (response.SectionState(response.kSectionHeader) == response.kStateComplete) { session->CallResponseHeaderCallback(); diff --git a/src/httpscan.cc b/src/httpscan.cc index 8f3a20c..991d6c9 100644 --- a/src/httpscan.cc +++ b/src/httpscan.cc @@ -134,7 +134,8 @@ void HttpScanSession::ScanRequestHeader(HttpSession * http_session_ctx) /* 扫描IP地址 */ nr_maat_scan_result_ = Maat_scan_addr(httpscan_module_ref_.maat_feather_ref, httpscan_module_ref_.table_id_ctrl_ip, sapp_tuple4_ptr.get(), - maat_scan_result_, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + maat_scan_result_, MAAT_SCAN_RESULT_, + &maat_scan_mid_, tfe_thread_current_thread_id()); /* 以下所有扫描命中后,配置callback tag为repeat,在本函数返回后,再次调用RequestHeader处理回调 * 函数,执行命中动作 */ @@ -153,7 +154,8 @@ void HttpScanSession::ScanRequestHeader(HttpSession * http_session_ctx) 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); + maat_scan_result_, dummy, MAAT_SCAN_RESULT_, + &maat_scan_mid_, tfe_thread_current_thread_id()); if (nr_maat_scan_result_ > 0) { @@ -184,7 +186,8 @@ void HttpScanSession::ScanRequestHeader(HttpSession * http_session_ctx) 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_, tfe_thread_current_thread_id()); if (nr_maat_scan_result_ > 0) { @@ -215,7 +218,7 @@ void HttpScanSession::ScanRequestBody(HttpSession * http_session_ctx) nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, httpscan_module_ref_.table_id_ctrl_http_req_body, CHARSET_UTF8, body_content_raw, (int) body_content_length, - maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, tfe_thread_current_thread_id()); if (nr_maat_scan_result_ > 0) { @@ -311,7 +314,7 @@ HttpScanSession::scan_result_t HttpScanSession::scan_headers(const HttpHeaders & nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, table_id, MAAT_DEFAULT_CHARSET_, value.c_str(), (int) value.length(), maat_scan_result_, __dummy, - MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + MAAT_SCAN_RESULT_, &maat_scan_mid_, tfe_thread_current_thread_id()); if (nr_maat_scan_result_ > 0) { @@ -336,7 +339,8 @@ HttpScanSession::scan_result_t HttpScanSession::scan_body(const char * data, siz int __dummy[MAAT_SCAN_RESULT_]; nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, - table_id, CHARSET_UTF8, data, (int) len, maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0); + table_id, CHARSET_UTF8, data, (int) len, maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, + &maat_scan_mid_, tfe_thread_current_thread_id()); if (nr_maat_scan_result_ > 0) return scan_result_t::kScanResultHit; @@ -357,7 +361,7 @@ HttpScanSession::scan_result_t HttpScanSession::scan_bypass_content_type(const H content_type = value; return false; }); - if (content_type.find("text") == 0) + if (content_type.find("text") != 0) { return scan_result_t::kScanResultHit; } diff --git a/src/main.cc b/src/main.cc index 8440962..bd9fbfd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -293,13 +293,14 @@ main(int argc, char *argv[]) event_enable_debug_logging(0); START_EASYLOGGINGPP(argc, argv); + el::Loggers::configureFromGlobal("conf/logger.conf"); el::Loggers::addFlag(el::LoggingFlag::MultiLoggerSupport); el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); - el::Loggers::reconfigureAllLoggers(el::ConfigurationType::SubsecondPrecision, "6"); el::Loggers::getLogger("structLogger"); el::Loggers::getLogger("conntrace"); el::Loggers::getLogger("HttpScanTrace"); + el::Loggers::getLogger("HttpSessionTrace"); if (nat_getdefaultname()) { @@ -917,8 +918,8 @@ main(int argc, char *argv[]) g_tfe_instance->http_module = std::make_unique<Http>(); g_tfe_instance->http_scan_module = std::make_unique<HttpScan>(g_tfe_instance, g_tfe_config); - g_tfe_instance->stat_module = tfe_stat_create("conf/tfe.conf"); + if (g_tfe_instance->stat_module == NULL) { log_err_printf("Failed to create stat module, exited."); @@ -963,16 +964,6 @@ main(int argc, char *argv[]) goto out_sslreinit_failed; } -#if 0 - /* Post-privdrop/chroot/detach initialization, thread spawning */ - if (log_init(opts, proxy, clisock[1], clisock[2]) == -1) { - fprintf(stderr, "%s: failed to init log facility: %s\n", - argv0, strerror(errno)); - goto out_log_failed; - } - -#endif - if (cachemgr_init() == -1) { log_err_printf("Failed to init cache manager.\n"); goto out_cachemgr_failed; diff --git a/src/pxythrmgr.cc b/src/pxythrmgr.cc index 39d2086..b3357b3 100644 --- a/src/pxythrmgr.cc +++ b/src/pxythrmgr.cc @@ -62,6 +62,8 @@ struct tfe_thread_ctx ~tfe_thread_ctx(); }; +__thread int __currect_thread_id; + tfe_thread_ctx::tfe_thread_ctx(int thread_id, bool en_dns_base) : thread_id(thread_id), running(false) { evbase = event_base_new(); @@ -120,14 +122,16 @@ static void *__tfe_thrmgr_thread_entry(void *arg) struct event *ev; ev = event_new(ctx->evbase, -1, EV_PERSIST, __dummy_event_handler, NULL); - if (!ev) - return NULL; + if (!ev) return NULL; evtimer_add(ev, &timer_delay); ctx->running = 1; + + __currect_thread_id = ctx->thread_id; + LOG(INFO) << string_format("EventThread %d is running...", __currect_thread_id); + event_base_dispatch(ctx->evbase); event_free(ev); - return NULL; } @@ -211,7 +215,7 @@ int tfe_thread_manager_attach(tfe_thread_manager_ctx *ctx, for (unsigned thread_id = 1; thread_id < ctx->nr_thread; thread_id++) { - if (min_load > ctx->thr_ctx[min_thread_id]->load) + if (min_load > ctx->thr_ctx[thread_id]->load) { min_load = ctx->thr_ctx[thread_id]->load; min_thread_id = thread_id; @@ -222,6 +226,8 @@ int tfe_thread_manager_attach(tfe_thread_manager_ctx *ctx, *dnsbase = ctx->thr_ctx[min_thread_id]->dnsbase; ctx->thr_ctx[min_thread_id]->load++; + + LOG(DEBUG) << "new connection attached to the thread, thread id =" << min_thread_id; return min_thread_id; } @@ -235,4 +241,9 @@ void tfe_thread_manager_detach(tfe_thread_manager_ctx *ctx, int thread_id) ctx->thr_ctx[thread_id]->load--; } +int tfe_thread_current_thread_id() +{ + return __currect_thread_id; +} + /* vim: set noet ft=c: */
\ No newline at end of file diff --git a/src/pxythrmgr.h b/src/pxythrmgr.h index 782ead2..94bfe90 100644 --- a/src/pxythrmgr.h +++ b/src/pxythrmgr.h @@ -48,6 +48,7 @@ int tfe_thread_manager_attach(tfe_thread_manager_ctx *, struct event_base **, struct evdns_base **) WUNRES; void tfe_thread_manager_detach(tfe_thread_manager_ctx *, int); +int tfe_thread_current_thread_id(); #endif /* !PXYTHRMGR_H */ @@ -245,3 +245,17 @@ static std::string hexdump(const char * title, const void * buf, unsigned int le return str_ret; } + +extern "C" +{ +#include <event2/buffer.h> +} + +static std::string hexdump(const char * title, struct evbuffer * evbuf) +{ + auto buffer_len = evbuffer_get_length(evbuf); + auto buffer_ptr = std::unique_ptr<char[]>(new char[buffer_len]); + + evbuffer_copyout(evbuf, buffer_ptr.get(), buffer_len); + return hexdump(title, buffer_ptr.get(), (unsigned int)buffer_len); +}
\ No newline at end of file |
