From 154876a17b544f6190199c5bad311880fd4de6e9 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 6 Nov 2014 21:14:14 +0900 Subject: [PATCH] nghttpx: Apply TLS record length limit to DATA frame payload This is not obvious but it makes intermediaries flush and forward DATA frame boundary without excessive buffering. Since we have different TCP connections frontend and backend, this may not work. This is still experimental. --- src/shrpx_http2_upstream.cc | 11 +++++++++++ src/shrpx_spdy_upstream.cc | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index a90914de..dd6a1e27 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -1080,8 +1080,19 @@ ssize_t downstream_data_read_callback(nghttp2_session *session, auto downstream = static_cast(source->ptr); auto upstream = static_cast(downstream->get_upstream()); auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); + auto limit = handler->get_write_limit(); + + if(limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } + int nread = evbuffer_remove(body, buf, length); if(nread == -1) { ULOG(FATAL, upstream) << "evbuffer_remove() failed"; diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index e91e4e94..06c76eca 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -799,7 +799,19 @@ ssize_t spdy_data_read_callback(spdylay_session *session, auto downstream = static_cast(source->ptr); auto upstream = static_cast(downstream->get_upstream()); auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); + + auto limit = handler->get_write_limit(); + + if(limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } + int nread = evbuffer_remove(body, buf, length); if(nread == -1) { ULOG(FATAL, upstream) << "evbuffer_remove() failed";