From 4ab594b144ed02c2fff55682a9251269d88813c0 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 19 Jun 2014 22:40:24 +0900 Subject: [PATCH] nghttpx: Fix connection preface is not read by upstream_http2_connhd_readcb It seems that if readcb is not set before SSL/TLS handshake, the incoming data already available when eventcb (BEV_EVENT_CONNECTED event) is fired is not further notified after setting new readcb. We knew this fact and call upstream->on_read() in eventcb, but it is wrong for HTTP/2. We have to call upstream_http2_connhd_readcb to check connection preface. Otherwise, we consume it by nghttp2 session and it is treated as unknown frame and connection preface is not detected properly. --- src/shrpx_client_handler.cc | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 2227ba42..51d97aa8 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -123,13 +123,6 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg) CLOG(INFO, handler) << "SSL/TLS session reused"; } } - // At this point, input buffer is already filled with some - // bytes. The read callback is not called until new data - // come. So consume input buffer here. - if(handler->get_upstream()->on_read() != 0) { - delete handler; - return; - } } } } @@ -367,17 +360,38 @@ int ClientHandler::validate_next_proto() upstream_ = std::move(http2_upstream); + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + upstream_http2_connhd_readcb(bev_, this); + return 0; } else { #ifdef HAVE_SPDYLAY uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len); if(version) { upstream_ = util::make_unique(version, this); + + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + if(upstream_->on_read() != 0) { + return -1; + } + return 0; } #endif // HAVE_SPDYLAY if(next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) { upstream_ = util::make_unique(this); + + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + if(upstream_->on_read() != 0) { + return -1; + } + return 0; } } @@ -394,6 +408,14 @@ int ClientHandler::validate_next_proto() CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1"; } upstream_ = util::make_unique(this); + + // At this point, input buffer is already filled with some bytes. + // The read callback is not called until new data come. So consume + // input buffer here. + if(upstream_->on_read() != 0) { + return -1; + } + return 0; } if(LOG_ENABLED(INFO)) {