Deprecate gfe2_reloadable_flag_quic_donot_wake_up_stream_before_finish_reading_headers_v2.
PiperOrigin-RevId: 499616916
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 76eb89b..f43b662 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -399,6 +399,8 @@
"spdy/core/spdy_protocol.h",
"spdy/core/spdy_simple_arena.h",
"spdy/core/zero_copy_output_buffer.h",
+ "web_transport/mock_web_transport.h",
+ "web_transport/web_transport.h",
]
quiche_core_srcs = [
"balsa/balsa_enums.cc",
diff --git a/build/source_list.gni b/build/source_list.gni
index 78333b6..60ff738 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -399,6 +399,8 @@
"src/quiche/spdy/core/spdy_protocol.h",
"src/quiche/spdy/core/spdy_simple_arena.h",
"src/quiche/spdy/core/zero_copy_output_buffer.h",
+ "src/quiche/web_transport/mock_web_transport.h",
+ "src/quiche/web_transport/web_transport.h",
]
quiche_core_srcs = [
"src/quiche/balsa/balsa_enums.cc",
diff --git a/build/source_list.json b/build/source_list.json
index 3811e8b..c8683c8 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -397,7 +397,9 @@
"quiche/spdy/core/spdy_prefixed_buffer_reader.h",
"quiche/spdy/core/spdy_protocol.h",
"quiche/spdy/core/spdy_simple_arena.h",
- "quiche/spdy/core/zero_copy_output_buffer.h"
+ "quiche/spdy/core/zero_copy_output_buffer.h",
+ "quiche/web_transport/mock_web_transport.h",
+ "quiche/web_transport/web_transport.h"
],
"quiche_core_srcs": [
"quiche/balsa/balsa_enums.cc",
diff --git a/quiche/web_transport/mock_web_transport.h b/quiche/web_transport/mock_web_transport.h
new file mode 100644
index 0000000..93f3309
--- /dev/null
+++ b/quiche/web_transport/mock_web_transport.h
@@ -0,0 +1,76 @@
+// Copyright 2023 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Pre-defined mocks for the APIs in web_transport.h.
+
+#ifndef QUICHE_WEB_TRANSPORT_MOCK_WEB_TRANSPORT_H_
+#define QUICHE_WEB_TRANSPORT_MOCK_WEB_TRANSPORT_H_
+
+#include "quiche/common/platform/api/quiche_test.h"
+#include "quiche/web_transport/web_transport.h"
+
+namespace webtransport {
+namespace test {
+
+class QUICHE_NO_EXPORT MockStreamVisitor : public StreamVisitor {
+ MOCK_METHOD(void, OnCanRead, (), (override));
+ MOCK_METHOD(void, OnCanWrite, (), (override));
+ MOCK_METHOD(void, OnResetStreamReceived, (StreamErrorCode), (override));
+ MOCK_METHOD(void, OnStopSendingReceived, (StreamErrorCode), (override));
+ MOCK_METHOD(void, OnWriteSideInDataRecvdState, (), (override));
+};
+
+class QUICHE_NO_EXPORT MockStream : public Stream {
+ MOCK_METHOD(ReadResult, Read, (absl::Span<char> buffer), (override));
+ MOCK_METHOD(ReadResult, Read, (std::string * output), (override));
+ MOCK_METHOD(bool, Write, (absl::string_view data), (override));
+ MOCK_METHOD(bool, SendFin, (), (override));
+ MOCK_METHOD(bool, CanWrite, (), (const, override));
+ MOCK_METHOD(size_t, ReadableBytes, (), (const, override));
+ MOCK_METHOD(StreamId, GetStreamId, (), (const, override));
+ MOCK_METHOD(void, ResetWithUserCode, (StreamErrorCode error), (override));
+ MOCK_METHOD(void, SendStopSending, (StreamErrorCode error), (override));
+ MOCK_METHOD(void, ResetDueToInternalError, (), (override));
+ MOCK_METHOD(void, MaybeResetDueToStreamObjectGone, (), (override));
+ MOCK_METHOD(StreamVisitor*, visitor, (), (override));
+ MOCK_METHOD(void, SetVisitor, (std::unique_ptr<StreamVisitor> visitor),
+ (override));
+};
+
+class QUICHE_NO_EXPORT MockSessionVisitor : public SessionVisitor {
+ MOCK_METHOD(void, OnSessionReady, (const spdy::Http2HeaderBlock& headers),
+ (override));
+ MOCK_METHOD(void, OnSessionClosed,
+ (SessionErrorCode error_code, const std::string& error_message),
+ (override));
+ MOCK_METHOD(void, OnIncomingBidirectionalStreamAvailable, (), (override));
+ MOCK_METHOD(void, OnIncomingUnidirectionalStreamAvailable, (), (override));
+ MOCK_METHOD(void, OnDatagramReceived, (absl::string_view datagram),
+ (override));
+ MOCK_METHOD(void, OnCanCreateNewOutgoingBidirectionalStream, (), (override));
+ MOCK_METHOD(void, OnCanCreateNewOutgoingUnidirectionalStream, (), (override));
+};
+
+class QUICHE_NO_EXPORT MockSession : public Session {
+ public:
+ MOCK_METHOD(void, CloseSession,
+ (SessionErrorCode error_code, absl::string_view error_message),
+ (override));
+ MOCK_METHOD(Stream*, AcceptIncomingBidirectionalStream, (), (override));
+ MOCK_METHOD(Stream*, AcceptIncomingUnidirectionalStream, (), (override));
+ MOCK_METHOD(bool, CanOpenNextOutgoingBidirectionalStream, (), (override));
+ MOCK_METHOD(bool, CanOpenNextOutgoingUnidirectionalStream, (), (override));
+ MOCK_METHOD(Stream*, OpenOutgoingBidirectionalStream, (), (override));
+ MOCK_METHOD(Stream*, OpenOutgoingUnidirectionalStream, (), (override));
+ MOCK_METHOD(DatagramStatus, SendOrQueueDatagram, (absl::string_view datagram),
+ (override));
+ MOCK_METHOD(size_t, GetMaxDatagramSize, (), (const, override));
+ MOCK_METHOD(void, SetDatagramMaxTimeInQueue,
+ (absl::Duration max_time_in_queue), (override));
+};
+
+} // namespace test
+} // namespace webtransport
+
+#endif // QUICHE_WEB_TRANSPORT_MOCK_WEB_TRANSPORT_H_
diff --git a/quiche/web_transport/web_transport.h b/quiche/web_transport/web_transport.h
new file mode 100644
index 0000000..ce66db5
--- /dev/null
+++ b/quiche/web_transport/web_transport.h
@@ -0,0 +1,227 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header contains interfaces that abstract away different backing
+// protocols for WebTransport.
+
+#ifndef QUICHE_WEB_TRANSPORT_WEB_TRANSPORT_H_
+#define QUICHE_WEB_TRANSPORT_WEB_TRANSPORT_H_
+
+#include <cstddef>
+#include <memory>
+#include <string>
+
+// The dependencies of this API should be kept minimal and independent of
+// specific transport implementations.
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+#include "quiche/common/platform/api/quiche_export.h"
+#include "quiche/spdy/core/http2_header_block.h"
+
+namespace webtransport {
+
+// A numeric ID uniquely identifying a WebTransport stream. Note that by design,
+// those IDs are not available in the Web API, and the IDs do not necessarily
+// match between client and server perspective, since there may be a proxy
+// between them.
+using StreamId = uint32_t;
+// Application-specific error code used for resetting either the read or the
+// write half of the stream.
+using StreamErrorCode = uint8_t;
+// Application-specific error code used for closing a WebTransport session.
+using SessionErrorCode = uint32_t;
+
+// An outcome of a datagram send call.
+enum class DatagramStatusCode {
+ // Datagram has been successfully sent or placed into the datagram queue.
+ kSuccess,
+ // Datagram has not been sent since the underlying QUIC connection is blocked
+ // by the congestion control. Note that this can only happen if the queue is
+ // full.
+ kBlocked,
+ // Datagram has not been sent since it is too large to fit into a single
+ // UDP packet.
+ kTooBig,
+ // An unspecified internal error.
+ kInternalError,
+};
+
+// An outcome of a datagram send call, in both enum and human-readable form.
+struct QUICHE_EXPORT DatagramStatus {
+ explicit DatagramStatus(DatagramStatusCode code, std::string error_message)
+ : code(code), error_message(std::move(error_message)) {}
+
+ DatagramStatusCode code;
+ std::string error_message;
+};
+
+// The stream visitor is an application-provided object that gets notified about
+// events related to a WebTransport stream. The visitor object is owned by the
+// stream itself, meaning that if the stream is ever fully closed, the visitor
+// will be garbage-collected.
+class QUICHE_EXPORT StreamVisitor {
+ public:
+ virtual ~StreamVisitor() {}
+
+ // Called whenever the stream has readable data available.
+ virtual void OnCanRead() = 0;
+ // Called whenever the stream is not write-blocked and can accept new data.
+ virtual void OnCanWrite() = 0;
+
+ // Called when RESET_STREAM is received for the stream.
+ virtual void OnResetStreamReceived(StreamErrorCode error) = 0;
+ // Called when STOP_SENDING is received for the stream.
+ virtual void OnStopSendingReceived(StreamErrorCode error) = 0;
+ // Called when the write side of the stream is closed and all of the data sent
+ // has been acknowledged ("Data Recvd" state of RFC 9000). Primarily used by
+ // the state machine of the Web API.
+ virtual void OnWriteSideInDataRecvdState() = 0;
+};
+
+// A stream (either bidirectional or unidirectional) that is contained within a
+// WebTransport session.
+class QUICHE_EXPORT Stream {
+ public:
+ struct QUICHE_EXPORT ReadResult {
+ // Number of bytes actually read.
+ size_t bytes_read;
+ // Whether the FIN has been received; if true, no further data will arrive
+ // on the stream, and the stream object can be soon potentially garbage
+ // collected.
+ bool fin;
+ };
+
+ virtual ~Stream() {}
+
+ // Reads at most |buffer.size()| bytes into |buffer|.
+ [[nodiscard]] virtual ReadResult Read(absl::Span<char> buffer) = 0;
+ // Reads all available data and appends it to the end of |output|.
+ [[nodiscard]] virtual ReadResult Read(std::string* output) = 0;
+ // Writes |data| into the stream. WebTransport writes are all-or-nothing: the
+ // stream will either accept all of the data (potentially buffering some of
+ // it), or reject it. In the latter case, the method will return false, and
+ // the sender has to wait until OnCanWrite() is called.
+ [[nodiscard]] virtual bool Write(absl::string_view data) = 0;
+ // Sends the FIN on the stream. Returns true on success.
+ [[nodiscard]] virtual bool SendFin() = 0;
+
+ // Indicates whether it is possible to write into stream right now.
+ virtual bool CanWrite() const = 0;
+ // Indicates the number of bytes that can be read from the stream.
+ virtual size_t ReadableBytes() const = 0;
+
+ // An ID that is unique within the session. Those are not exposed to the user
+ // via the web API, but can be used internally for bookkeeping and
+ // diagnostics.
+ virtual StreamId GetStreamId() const = 0;
+
+ // Resets the read or the write side of the stream with the specified error
+ // code.
+ virtual void ResetWithUserCode(StreamErrorCode error) = 0;
+ virtual void SendStopSending(StreamErrorCode error) = 0;
+
+ // A general-purpose stream reset method that may be used when a specific
+ // error code is not available.
+ virtual void ResetDueToInternalError() = 0;
+ // If the stream has not been already reset, reset the stream. This is
+ // primarily used in the JavaScript API when the stream object has been
+ // garbage collected.
+ virtual void MaybeResetDueToStreamObjectGone() = 0;
+
+ virtual StreamVisitor* visitor() = 0;
+ virtual void SetVisitor(std::unique_ptr<StreamVisitor> visitor) = 0;
+};
+
+// Visitor that gets notified about events related to a WebTransport session.
+class QUICHE_EXPORT SessionVisitor {
+ public:
+ virtual ~SessionVisitor() {}
+
+ // Notifies the visitor when the session is ready to exchange application
+ // data.
+ virtual void OnSessionReady(const spdy::Http2HeaderBlock& headers) = 0;
+
+ // Notifies the visitor when the session has been closed.
+ virtual void OnSessionClosed(SessionErrorCode error_code,
+ const std::string& error_message) = 0;
+
+ // Notifies the visitor when a new stream has been received. The stream in
+ // question can be retrieved using AcceptIncomingBidirectionalStream() or
+ // AcceptIncomingUnidirectionalStream().
+ virtual void OnIncomingBidirectionalStreamAvailable() = 0;
+ virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
+
+ // Notifies the visitor when a new datagram has been received.
+ virtual void OnDatagramReceived(absl::string_view datagram) = 0;
+
+ // Notifies the visitor that a new outgoing stream can now be created.
+ virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
+ virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
+};
+
+// An abstract interface for a WebTransport session.
+//
+// *** AN IMPORTANT NOTE ABOUT STREAM LIFETIMES ***
+// Stream objects are managed internally by the underlying QUIC stack, and can
+// go away at any time due to the peer resetting the stream. Because of that,
+// any pointers to the stream objects returned by this class MUST NEVER be
+// retained long-term, except inside the stream visitor (the stream visitor is
+// owned by the stream object). If you need to store a reference to a stream,
+// consider one of the two following options:
+// (1) store a stream ID,
+// (2) store a weak pointer to the stream visitor, and then access the stream
+// via the said visitor (the visitor is guaranteed to be alive as long as
+// the stream is alive).
+class QUICHE_EXPORT Session {
+ public:
+ virtual ~Session() {}
+
+ // Closes the WebTransport session in question with the specified |error_code|
+ // and |error_message|.
+ virtual void CloseSession(SessionErrorCode error_code,
+ absl::string_view error_message) = 0;
+
+ // Return the earliest incoming stream that has been received by the session
+ // but has not been accepted. Returns nullptr if there are no incoming
+ // streams. See the class note regarding the lifetime of the returned stream
+ // object.
+ virtual Stream* AcceptIncomingBidirectionalStream() = 0;
+ virtual Stream* AcceptIncomingUnidirectionalStream() = 0;
+
+ // Returns true if flow control allows opening a new stream.
+ //
+ // IMPORTANT: See the class note regarding the lifetime of the returned stream
+ // object.
+ virtual bool CanOpenNextOutgoingBidirectionalStream() = 0;
+ virtual bool CanOpenNextOutgoingUnidirectionalStream() = 0;
+
+ // Opens a new WebTransport stream, or returns nullptr if that is not possible
+ // due to flow control. See the class note regarding the lifetime of the
+ // returned stream object.
+ //
+ // IMPORTANT: See the class note regarding the lifetime of the returned stream
+ // object.
+ virtual Stream* OpenOutgoingBidirectionalStream() = 0;
+ virtual Stream* OpenOutgoingUnidirectionalStream() = 0;
+
+ // Returns the WebTransport stream with the corresponding ID.
+ //
+ // IMPORTANT: See the class note regarding the lifetime of the returned stream
+ // object.
+ // TODO(vasilvv): implement this in a follow-up CL.
+ // virtual Stream* GetStreamById(StreamId id) = 0;
+
+ virtual DatagramStatus SendOrQueueDatagram(absl::string_view datagram) = 0;
+ // Returns a conservative estimate of the largest datagram size that the
+ // session would be able to send.
+ virtual uint64_t GetMaxDatagramSize() const = 0;
+ // Sets the largest duration that a datagram can spend in the queue before
+ // being silently dropped.
+ virtual void SetDatagramMaxTimeInQueue(absl::Duration max_time_in_queue) = 0;
+};
+
+} // namespace webtransport
+
+#endif // QUICHE_WEB_TRANSPORT_WEB_TRANSPORT_H_