Commit 4ab594b1 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

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.
parent 3f5e359e
...@@ -123,13 +123,6 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg) ...@@ -123,13 +123,6 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg)
CLOG(INFO, handler) << "SSL/TLS session reused"; 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() ...@@ -367,17 +360,38 @@ int ClientHandler::validate_next_proto()
upstream_ = std::move(http2_upstream); 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; return 0;
} else { } else {
#ifdef HAVE_SPDYLAY #ifdef HAVE_SPDYLAY
uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len); uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len);
if(version) { if(version) {
upstream_ = util::make_unique<SpdyUpstream>(version, this); upstream_ = util::make_unique<SpdyUpstream>(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; return 0;
} }
#endif // HAVE_SPDYLAY #endif // HAVE_SPDYLAY
if(next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) { if(next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) {
upstream_ = util::make_unique<HttpsUpstream>(this); upstream_ = util::make_unique<HttpsUpstream>(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; return 0;
} }
} }
...@@ -394,6 +408,14 @@ int ClientHandler::validate_next_proto() ...@@ -394,6 +408,14 @@ int ClientHandler::validate_next_proto()
CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1"; CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1";
} }
upstream_ = util::make_unique<HttpsUpstream>(this); upstream_ = util::make_unique<HttpsUpstream>(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; return 0;
} }
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment