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