nghttpx: Handle connection flow control for DATA not sent to frontend

This commit is contained in:
Tatsuhiro Tsujikawa 2014-07-02 23:20:45 +09:00
parent 797edae4d4
commit acb3d4dcfc
2 changed files with 23 additions and 0 deletions

View File

@ -57,6 +57,7 @@ Http2Session::Http2Session(event_base *evbase, SSL_CTX *ssl_ctx)
wrbev_(nullptr), wrbev_(nullptr),
rdbev_(nullptr), rdbev_(nullptr),
settings_timerev_(nullptr), settings_timerev_(nullptr),
recv_ign_window_size_(0),
fd_(-1), fd_(-1),
state_(DISCONNECTED), state_(DISCONNECTED),
notified_(false), notified_(false),
@ -668,6 +669,7 @@ int Http2Session::submit_window_update(Http2DownstreamConnection *dconn,
stream_id = dconn->get_downstream()->get_downstream_stream_id(); stream_id = dconn->get_downstream()->get_downstream_stream_id();
} else { } else {
stream_id = 0; stream_id = 0;
recv_ign_window_size_ = 0;
} }
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE,
stream_id, amount); 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)); (nghttp2_session_get_stream_user_data(session, stream_id));
if(!sd || !sd->dconn) { if(!sd || !sd->dconn) {
http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
http2session->handle_ign_data_chunk(len);
return 0; return 0;
} }
auto downstream = sd->dconn->get_downstream(); auto downstream = sd->dconn->get_downstream();
if(!downstream || downstream->get_downstream_stream_id() != stream_id) { if(!downstream || downstream->get_downstream_stream_id() != stream_id) {
http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
http2session->handle_ign_data_chunk(len);
return 0; return 0;
} }
@ -1113,6 +1117,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session,
rv = upstream->on_downstream_body(downstream, data, len, false); rv = upstream->on_downstream_body(downstream, data, len, false);
if(rv != 0) { if(rv != 0) {
http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR); http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
http2session->handle_ign_data_chunk(len);
downstream->set_response_state(Downstream::MSG_RESET); downstream->set_response_state(Downstream::MSG_RESET);
} }
call_downstream_readcb(http2session, downstream); call_downstream_readcb(http2session, downstream);
@ -1454,4 +1459,19 @@ SSL* Http2Session::get_ssl() const
return ssl_; 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 } // namespace shrpx

View File

@ -108,6 +108,8 @@ public:
SSL* get_ssl() const; SSL* get_ssl() const;
int handle_ign_data_chunk(size_t len);
enum { enum {
// Disconnected // Disconnected
DISCONNECTED, DISCONNECTED,
@ -138,6 +140,7 @@ private:
bufferevent *wrbev_; bufferevent *wrbev_;
bufferevent *rdbev_; bufferevent *rdbev_;
event *settings_timerev_; event *settings_timerev_;
int32_t recv_ign_window_size_;
// fd_ is used for proxy connection and no TLS connection. For // fd_ is used for proxy connection and no TLS connection. For
// direct or TLS connection, it may be -1 even after connection is // direct or TLS connection, it may be -1 even after connection is
// established. Use bufferevent_getfd(bev_) to get file descriptor // established. Use bufferevent_getfd(bev_) to get file descriptor