Write push promise on request streams.

This CL migrates push promise from headers stream to request streams, and HTTP/3 push promise format is used in v99.

gfe-relnote: v99 only, not used in prod.
PiperOrigin-RevId: 260185991
Change-Id: I676cb4ebb71f72b321934c91d77ce4911f1d7225
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 50332ee..b57ad72 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -520,15 +520,27 @@
     return;
   }
 
-  SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
-                                 std::move(headers));
-  // PUSH_PROMISE must not be the last frame sent out, at least followed by
-  // response headers.
-  push_promise.set_fin(false);
+  if (!VersionHasStreamType(connection()->transport_version())) {
+    SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
+                                   std::move(headers));
+    // PUSH_PROMISE must not be the last frame sent out, at least followed by
+    // response headers.
+    push_promise.set_fin(false);
 
-  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
-  headers_stream()->WriteOrBufferData(
-      QuicStringPiece(frame.data(), frame.size()), false, nullptr);
+    SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+    headers_stream()->WriteOrBufferData(
+        QuicStringPiece(frame.data(), frame.size()), false, nullptr);
+    return;
+  }
+
+  // Encode header list.
+  std::string encoded_headers =
+      qpack_encoder_->EncodeHeaderList(original_stream_id, &headers);
+  PushPromiseFrame frame;
+  frame.push_id = promised_stream_id;
+  frame.headers = encoded_headers;
+  QuicSpdyStream* stream = GetSpdyDataStream(original_stream_id);
+  stream->WritePushPromise(frame);
 }
 
 void QuicSpdySession::SendMaxHeaderListSize(size_t value) {
@@ -693,6 +705,11 @@
 void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
   QUIC_DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
                 << header_list.DebugString();
+  // This code path is only executed for push promise in IETF QUIC.
+  if (VersionUsesQpack(connection()->transport_version())) {
+    DCHECK(promised_stream_id_ !=
+           QuicUtils::GetInvalidStreamId(connection()->transport_version()));
+  }
   if (promised_stream_id_ ==
       QuicUtils::GetInvalidStreamId(connection()->transport_version())) {
     OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);