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_;