From fe6ccd16da67f0ec0b00a6aa16ff419f78208f82 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 5 Mar 2016 19:11:36 +0900 Subject: [PATCH] nghttpx: Change read timeout reset timing --- src/shrpx_client_handler.cc | 29 ++++++++++++++++++++++++----- src/shrpx_client_handler.h | 2 ++ src/shrpx_http2_upstream.cc | 3 +++ src/shrpx_https_upstream.cc | 14 +++++++++++--- src/shrpx_spdy_upstream.cc | 9 ++++++++- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 46540d42..3326e885 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -114,8 +114,6 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) { int ClientHandler::noop() { return 0; } int ClientHandler::read_clear() { - ev_timer_again(conn_.loop, &conn_.rt); - for (;;) { if (rb_.rleft() && on_read() != 0) { return -1; @@ -124,6 +122,10 @@ int ClientHandler::read_clear() { rb_.reset(); } else if (rb_.wleft() == 0) { conn_.rlimit.stopw(); + if (reset_conn_rtimer_required_) { + reset_conn_rtimer_required_ = false; + ev_timer_again(conn_.loop, &conn_.rt); + } return 0; } @@ -134,6 +136,10 @@ int ClientHandler::read_clear() { auto nread = conn_.read_clear(rb_.last, rb_.wleft()); if (nread == 0) { + if (reset_conn_rtimer_required_) { + reset_conn_rtimer_required_ = false; + ev_timer_again(conn_.loop, &conn_.rt); + } return 0; } @@ -208,8 +214,6 @@ int ClientHandler::tls_handshake() { } int ClientHandler::read_tls() { - ev_timer_again(conn_.loop, &conn_.rt); - ERR_clear_error(); for (;;) { @@ -221,6 +225,11 @@ int ClientHandler::read_tls() { rb_.reset(); } else if (rb_.wleft() == 0) { conn_.rlimit.stopw(); + if (reset_conn_rtimer_required_) { + reset_conn_rtimer_required_ = false; + ev_timer_again(conn_.loop, &conn_.rt); + } + return 0; } @@ -231,6 +240,11 @@ int ClientHandler::read_tls() { auto nread = conn_.read_tls(rb_.last, rb_.wleft()); if (nread == 0) { + if (reset_conn_rtimer_required_) { + reset_conn_rtimer_required_ = false; + ev_timer_again(conn_.loop, &conn_.rt); + } + return 0; } @@ -391,7 +405,8 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, faddr_(faddr), worker_(worker), left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN), - should_close_after_write_(false) { + should_close_after_write_(false), + reset_conn_rtimer_required_(false) { ++worker_->get_worker_stat()->num_connections; @@ -497,6 +512,10 @@ void ClientHandler::reset_upstream_write_timeout(ev_tstamp t) { } } +void ClientHandler::signal_reset_upstream_conn_rtimer() { + reset_conn_rtimer_required_ = true; +} + int ClientHandler::validate_next_proto() { const unsigned char *next_proto = nullptr; unsigned int next_proto_len; diff --git a/src/shrpx_client_handler.h b/src/shrpx_client_handler.h index 7d6ace81..ec353576 100644 --- a/src/shrpx_client_handler.h +++ b/src/shrpx_client_handler.h @@ -86,6 +86,7 @@ public: struct ev_loop *get_loop() const; void reset_upstream_read_timeout(ev_tstamp t); void reset_upstream_write_timeout(ev_tstamp t); + void signal_reset_upstream_conn_rtimer(); int validate_next_proto(); const std::string &get_ipaddr() const; const std::string &get_port() const; @@ -161,6 +162,7 @@ private: // The number of bytes of HTTP/2 client connection header to read size_t left_connhd_len_; bool should_close_after_write_; + bool reset_conn_rtimer_required_; ReadBuf rb_; }; diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index dfeb2217..9d42fe3a 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -411,6 +411,9 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, verbose_on_frame_recv_callback(session, frame, user_data); } auto upstream = static_cast(user_data); + auto handler = upstream->get_client_handler(); + + handler->signal_reset_upstream_conn_rtimer(); switch (frame->hd.type) { case NGHTTP2_DATA: { diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 0af9a97e..49c9848e 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -247,6 +247,11 @@ int htp_hdrs_completecb(http_parser *htp) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "HTTP request headers completed"; } + + auto handler = upstream->get_client_handler(); + + handler->signal_reset_upstream_conn_rtimer(); + auto downstream = upstream->get_downstream(); auto &req = downstream->request(); @@ -323,7 +328,7 @@ int htp_hdrs_completecb(http_parser *htp) { req.authority = host->value; } - if (upstream->get_client_handler()->get_ssl()) { + if (handler->get_ssl()) { req.scheme = "https"; } else { req.scheme = "http"; @@ -336,7 +341,6 @@ int htp_hdrs_completecb(http_parser *htp) { downstream->set_request_state(Downstream::HEADER_COMPLETE); #ifdef HAVE_MRUBY - auto handler = upstream->get_client_handler(); auto worker = handler->get_worker(); auto mruby_ctx = worker->get_mruby_context(); @@ -355,7 +359,7 @@ int htp_hdrs_completecb(http_parser *htp) { } rv = downstream->attach_downstream_connection( - upstream->get_client_handler()->get_downstream_connection(downstream)); + handler->get_downstream_connection(downstream)); if (rv != 0) { downstream->set_request_state(Downstream::CONNECT_FAIL); @@ -377,6 +381,10 @@ namespace { int htp_bodycb(http_parser *htp, const char *data, size_t len) { int rv; auto upstream = static_cast(htp->data); + auto handler = upstream->get_client_handler(); + + handler->signal_reset_upstream_conn_rtimer(); + auto downstream = upstream->get_downstream(); rv = downstream->push_upload_data_chunk( reinterpret_cast(data), len); diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index 1a2341a8..e15444a4 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -143,6 +143,10 @@ namespace { void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { auto upstream = static_cast(user_data); + auto handler = upstream->get_client_handler(); + + handler->signal_reset_upstream_conn_rtimer(); + switch (type) { case SPDYLAY_SYN_STREAM: { if (LOG_ENABLED(INFO)) { @@ -281,7 +285,6 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, downstream->set_request_state(Downstream::HEADER_COMPLETE); #ifdef HAVE_MRUBY - auto handler = upstream->get_client_handler(); auto worker = handler->get_worker(); auto mruby_ctx = worker->get_mruby_context(); @@ -419,6 +422,10 @@ void on_data_recv_callback(spdylay_session *session, uint8_t flags, auto upstream = static_cast(user_data); auto downstream = static_cast( spdylay_session_get_stream_user_data(session, stream_id)); + auto handler = upstream->get_client_handler(); + + handler->signal_reset_upstream_conn_rtimer(); + if (downstream && (flags & SPDYLAY_DATA_FLAG_FIN)) { if (!downstream->validate_request_recv_body_length()) { upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR);