From acb3d4dcfc4d479d8d03f83f2fa42e41ed880505 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 2 Jul 2014 23:20:45 +0900 Subject: [PATCH] nghttpx: Handle connection flow control for DATA not sent to frontend --- src/shrpx_http2_session.cc | 20 ++++++++++++++++++++ src/shrpx_http2_session.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 3de70cc4..81bba699 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -57,6 +57,7 @@ Http2Session::Http2Session(event_base *evbase, SSL_CTX *ssl_ctx) wrbev_(nullptr), rdbev_(nullptr), settings_timerev_(nullptr), + recv_ign_window_size_(0), fd_(-1), state_(DISCONNECTED), notified_(false), @@ -668,6 +669,7 @@ int Http2Session::submit_window_update(Http2DownstreamConnection *dconn, stream_id = dconn->get_downstream()->get_downstream_stream_id(); } else { stream_id = 0; + recv_ign_window_size_ = 0; } rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, stream_id, amount); @@ -1101,11 +1103,13 @@ int on_data_chunk_recv_callback(nghttp2_session *session, (nghttp2_session_get_stream_user_data(session, stream_id)); if(!sd || !sd->dconn) { http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); + http2session->handle_ign_data_chunk(len); return 0; } auto downstream = sd->dconn->get_downstream(); if(!downstream || downstream->get_downstream_stream_id() != stream_id) { http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); + http2session->handle_ign_data_chunk(len); return 0; } @@ -1113,6 +1117,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, rv = upstream->on_downstream_body(downstream, data, len, false); if(rv != 0) { http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); + http2session->handle_ign_data_chunk(len); downstream->set_response_state(Downstream::MSG_RESET); } call_downstream_readcb(http2session, downstream); @@ -1454,4 +1459,19 @@ SSL* Http2Session::get_ssl() const return ssl_; } +int Http2Session::handle_ign_data_chunk(size_t len) +{ + int32_t window_size; + + recv_ign_window_size_ += len; + + window_size = nghttp2_session_get_effective_local_window_size(session_); + + if(recv_ign_window_size_ >= window_size / 2) { + submit_window_update(nullptr, recv_ign_window_size_); + } + + return 0; +} + } // namespace shrpx diff --git a/src/shrpx_http2_session.h b/src/shrpx_http2_session.h index 85b9e697..9a5d6a9a 100644 --- a/src/shrpx_http2_session.h +++ b/src/shrpx_http2_session.h @@ -108,6 +108,8 @@ public: SSL* get_ssl() const; + int handle_ign_data_chunk(size_t len); + enum { // Disconnected DISCONNECTED, @@ -138,6 +140,7 @@ private: bufferevent *wrbev_; bufferevent *rdbev_; event *settings_timerev_; + int32_t recv_ign_window_size_; // fd_ is used for proxy connection and no TLS connection. For // direct or TLS connection, it may be -1 even after connection is // established. Use bufferevent_getfd(bev_) to get file descriptor