Refactor part of OgHttp2Session request stream creation and HEADERS frame-sending into their own methods. This refactoring will facilitate conditional request stream creation and HEADERS frame-sending based on the peer's advertised SETTINGS_MAX_CONCURRENT_STREAMS. PiperOrigin-RevId: 398512316
diff --git a/http2/adapter/oghttp2_session.cc b/http2/adapter/oghttp2_session.cc index 50aa063..d7ce5e0 100644 --- a/http2/adapter/oghttp2_session.cc +++ b/http2/adapter/oghttp2_session.cc
@@ -1,9 +1,12 @@ #include "http2/adapter/oghttp2_session.h" #include <tuple> +#include <utility> +#include "absl/memory/memory.h" #include "absl/strings/escaping.h" #include "http2/adapter/oghttp2_util.h" +#include "spdy/core/spdy_protocol.h" namespace http2 { namespace adapter { @@ -481,21 +484,8 @@ // TODO(birenroy): return an error for the incorrect perspective const Http2StreamId stream_id = next_stream_id_; next_stream_id_ += 2; - // Convert headers to header block, create headers frame. - auto frame = - absl::make_unique<spdy::SpdyHeadersIR>(stream_id, ToHeaderBlock(headers)); - // Add data source and user data to stream state - auto iter = CreateStream(stream_id); - write_scheduler_.MarkStreamReady(stream_id, false); - if (data_source == nullptr) { - frame->set_fin(true); - iter->second.half_closed_local = true; - } else { - iter->second.outbound_body = std::move(data_source); - } - iter->second.user_data = user_data; - // Enqueue headers frame - EnqueueFrame(std::move(frame)); + StartRequest(stream_id, ToHeaderBlock(headers), std::move(data_source), + user_data); return stream_id; } @@ -508,11 +498,8 @@ QUICHE_LOG(ERROR) << "Unable to find stream " << stream_id; return -501; // NGHTTP2_ERR_INVALID_ARGUMENT } - // Convert headers to header block, create headers frame - auto frame = - absl::make_unique<spdy::SpdyHeadersIR>(stream_id, ToHeaderBlock(headers)); - if (data_source == nullptr) { - frame->set_fin(true); + const bool end_stream = data_source == nullptr; + if (end_stream) { if (iter->second.half_closed_remote) { visitor_.OnCloseStream(stream_id, Http2ErrorCode::NO_ERROR); } @@ -523,7 +510,7 @@ iter->second.outbound_body = std::move(data_source); write_scheduler_.MarkStreamReady(stream_id, false); } - EnqueueFrame(std::move(frame)); + SendHeaders(stream_id, ToHeaderBlock(headers), end_stream); return 0; } @@ -832,6 +819,15 @@ absl::make_unique<spdy::SpdyWindowUpdateIR>(stream_id, update_delta)); } +void OgHttp2Session::SendHeaders(Http2StreamId stream_id, + spdy::SpdyHeaderBlock headers, + bool end_stream) { + auto frame = + absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(headers)); + frame->set_fin(end_stream); + EnqueueFrame(std::move(frame)); +} + void OgHttp2Session::SendTrailers(Http2StreamId stream_id, spdy::SpdyHeaderBlock trailers) { auto frame = @@ -885,5 +881,21 @@ return iter; } +void OgHttp2Session::StartRequest(Http2StreamId stream_id, + spdy::SpdyHeaderBlock headers, + std::unique_ptr<DataFrameSource> data_source, + void* user_data) { + auto iter = CreateStream(stream_id); + write_scheduler_.MarkStreamReady(stream_id, false); + const bool end_stream = data_source == nullptr; + if (end_stream) { + iter->second.half_closed_local = true; + } else { + iter->second.outbound_body = std::move(data_source); + } + iter->second.user_data = user_data; + SendHeaders(stream_id, std::move(headers), end_stream); +} + } // namespace adapter } // namespace http2
diff --git a/http2/adapter/oghttp2_session.h b/http2/adapter/oghttp2_session.h index ccb0b68..d5973a5 100644 --- a/http2/adapter/oghttp2_session.h +++ b/http2/adapter/oghttp2_session.h
@@ -5,6 +5,7 @@ #include <list> #include "http2/adapter/data_source.h" +#include "http2/adapter/http2_protocol.h" #include "http2/adapter/http2_session.h" #include "http2/adapter/http2_util.h" #include "http2/adapter/http2_visitor_interface.h" @@ -14,6 +15,7 @@ #include "common/platform/api/quiche_export.h" #include "spdy/core/http2_frame_decoder_adapter.h" #include "spdy/core/spdy_framer.h" +#include "spdy/core/spdy_header_block.h" namespace http2 { namespace adapter { @@ -219,6 +221,9 @@ bool SendMetadata(Http2StreamId stream_id, MetadataSequence& sequence); + void SendHeaders(Http2StreamId stream_id, spdy::SpdyHeaderBlock headers, + bool end_stream); + void SendTrailers(Http2StreamId stream_id, spdy::SpdyHeaderBlock trailers); // Encapsulates the RST_STREAM NO_ERROR behavior described in RFC 7540 @@ -228,9 +233,16 @@ // Performs flow control accounting for data sent by the peer. void MarkDataBuffered(Http2StreamId stream_id, size_t bytes); - // Creates a stream and returns an iterator pointing to it. + // Creates a stream for `stream_id` if not already present and returns an + // iterator pointing to it. StreamStateMap::iterator CreateStream(Http2StreamId stream_id); + // Creates a stream for `stream_id`, stores the `data_source` and `user_data` + // in the stream state, and sends the `headers`. + void StartRequest(Http2StreamId stream_id, spdy::SpdyHeaderBlock headers, + std::unique_ptr<DataFrameSource> data_source, + void* user_data); + // Receives events when inbound frames are parsed. Http2VisitorInterface& visitor_;