Add QpackStreams into QuicSpdySession.
Currently our QuicStreamIdManager is still in a gQUIC style, which doesn't support creating static streams later in a session. Thus in this CL, all QPACK send streams are created right at QuicSpdySession initialization.
For the same reason, QPACK stream types are sent on the wire once handshake is confirmed. In the future we can delay it until we send data on those streams.
gfe-relnote: v99 only, not used in prod.
PiperOrigin-RevId: 263776677
Change-Id: If710bde79ea2698f68710d7ac36ca6b039556260
diff --git a/quic/core/qpack/qpack_receive_stream.cc b/quic/core/qpack/qpack_receive_stream.cc
index d5f35fb..5920398 100644
--- a/quic/core/qpack/qpack_receive_stream.cc
+++ b/quic/core/qpack/qpack_receive_stream.cc
@@ -7,8 +7,10 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
namespace quic {
-QpackReceiveStream::QpackReceiveStream(PendingStream* pending)
- : QuicStream(pending, READ_UNIDIRECTIONAL, /*is_static=*/true) {}
+QpackReceiveStream::QpackReceiveStream(PendingStream* pending,
+ QpackStreamReceiver* receiver)
+ : QuicStream(pending, READ_UNIDIRECTIONAL, /*is_static=*/true),
+ receiver_(receiver) {}
void QpackReceiveStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
// TODO(renjietang) Change the error code to H/3 specific
@@ -18,4 +20,15 @@
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
+void QpackReceiveStream::OnDataAvailable() {
+ iovec iov;
+ while (!reading_stopped() && sequencer()->GetReadableRegion(&iov)) {
+ DCHECK(!sequencer()->IsClosed());
+
+ receiver_->Decode(QuicStringPiece(
+ reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
+ sequencer()->MarkConsumed(iov.iov_len);
+ }
+}
+
} // namespace quic
diff --git a/quic/core/qpack/qpack_receive_stream.h b/quic/core/qpack/qpack_receive_stream.h
index db18f7c..0613871 100644
--- a/quic/core/qpack/qpack_receive_stream.h
+++ b/quic/core/qpack/qpack_receive_stream.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_RECEIVE_STREAM_H_
#define QUICHE_QUIC_CORE_QPACK_QPACK_RECEIVE_STREAM_H_
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -18,7 +19,7 @@
public:
// Construct receive stream from pending stream, the |pending| object needs
// to be deleted after the construction.
- explicit QpackReceiveStream(PendingStream* pending);
+ QpackReceiveStream(PendingStream* pending, QpackStreamReceiver* receiver);
QpackReceiveStream(const QpackReceiveStream&) = delete;
QpackReceiveStream& operator=(const QpackReceiveStream&) = delete;
~QpackReceiveStream() override = default;
@@ -27,9 +28,13 @@
// closed before connection.
void OnStreamReset(const QuicRstStreamFrame& frame) override;
- // Implementation of QuicStream. Unimplemented yet.
- // TODO(bnc): Feed data to QPACK.
- void OnDataAvailable() override {}
+ // Implementation of QuicStream.
+ void OnDataAvailable() override;
+
+ void SetUnblocked() { sequencer()->SetUnblocked(); }
+
+ private:
+ QpackStreamReceiver* receiver_;
};
} // namespace quic
diff --git a/quic/core/qpack/qpack_receive_stream_test.cc b/quic/core/qpack/qpack_receive_stream_test.cc
index 63c8baf..8bcfb27 100644
--- a/quic/core/qpack/qpack_receive_stream_test.cc
+++ b/quic/core/qpack/qpack_receive_stream_test.cc
@@ -62,7 +62,7 @@
GetParam().version.transport_version,
QuicUtils::InvertPerspective(perspective())),
&session_);
- auto qpack_receive = QuicMakeUnique<QpackReceiveStream>(pending);
+ auto qpack_receive = QuicMakeUnique<QpackReceiveStream>(pending, nullptr);
qpack_receive_stream_ = qpack_receive.get();
session_.RegisterStaticStream(std::move(qpack_receive), false);
delete pending;
diff --git a/quic/core/qpack/qpack_send_stream.cc b/quic/core/qpack/qpack_send_stream.cc
index 34bba65..fe25f26 100644
--- a/quic/core/qpack/qpack_send_stream.cc
+++ b/quic/core/qpack/qpack_send_stream.cc
@@ -36,4 +36,13 @@
WriteOrBufferData(data, false, nullptr);
}
+void QpackSendStream::SendStreamType() {
+ char type[sizeof(http3_stream_type_)];
+ QuicDataWriter writer(QUIC_ARRAYSIZE(type), type);
+ writer.WriteVarInt62(http3_stream_type_);
+ WriteOrBufferData(QuicStringPiece(writer.data(), writer.length()), false,
+ nullptr);
+ stream_type_sent_ = true;
+}
+
} // namespace quic
diff --git a/quic/core/qpack/qpack_send_stream.h b/quic/core/qpack/qpack_send_stream.h
index 136a7cc..e7e4be3 100644
--- a/quic/core/qpack/qpack_send_stream.h
+++ b/quic/core/qpack/qpack_send_stream.h
@@ -42,6 +42,10 @@
// before the first instruction so that the peer can open an qpack stream.
void WriteStreamData(QuicStringPiece data) override;
+ // TODO(b/112770235): Remove this method once QuicStreamIdManager supports
+ // creating HTTP/3 unidirectional streams dynamically.
+ void SendStreamType();
+
private:
const uint64_t http3_stream_type_;
bool stream_type_sent_;