Support draft-07 version of WebTransport. See <https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-07.html#name-changes-between-draft-versi> for the draft version changelog. This CL makes QUICHE capable of negotiating draft-07, and enforces the parameter constraints related to draft-07; specifically, the requirement to explicitly support extended CONNECT and HTTP datagrams (it also de-supports pre-RFC datagrams SETTINGS codepoint for the new version only). Of non-backwards-compatible changes, our code is still missing WEBTRANSPORT_STREAMS position enforcement, and MAX_SESSIONS support. PiperOrigin-RevId: 542260756
diff --git a/quiche/quic/core/http/http_constants.cc b/quiche/quic/core/http/http_constants.cc index e585535..4bd8d62 100644 --- a/quiche/quic/core/http/http_constants.cc +++ b/quiche/quic/core/http/http_constants.cc
@@ -20,6 +20,7 @@ RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM_DRAFT04); RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM); RETURN_STRING_LITERAL(SETTINGS_WEBTRANS_DRAFT00); + RETURN_STRING_LITERAL(SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07); RETURN_STRING_LITERAL(SETTINGS_ENABLE_CONNECT_PROTOCOL); RETURN_STRING_LITERAL(SETTINGS_ENABLE_METADATA); }
diff --git a/quiche/quic/core/http/http_constants.h b/quiche/quic/core/http/http_constants.h index feec521..a8b5fd3 100644 --- a/quiche/quic/core/http/http_constants.h +++ b/quiche/quic/core/http/http_constants.h
@@ -42,8 +42,9 @@ SETTINGS_H3_DATAGRAM_DRAFT04 = 0xffd277, // RFC 9297. SETTINGS_H3_DATAGRAM = 0x33, - // draft-ietf-webtrans-http3-00 + // draft-ietf-webtrans-http3 SETTINGS_WEBTRANS_DRAFT00 = 0x2b603742, + SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07 = 0xc671706a, // draft-ietf-httpbis-h3-websockets SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08, SETTINGS_ENABLE_METADATA = 0x4d44,
diff --git a/quiche/quic/core/http/quic_spdy_session.cc b/quiche/quic/core/http/quic_spdy_session.cc index 0e18ebb..44fff6c 100644 --- a/quiche/quic/core/http/quic_spdy_session.cc +++ b/quiche/quic/core/http/quic_spdy_session.cc
@@ -16,6 +16,7 @@ #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "quiche/quic/core/http/http_constants.h" #include "quiche/quic/core/http/http_decoder.h" #include "quiche/quic/core/http/http_frames.h" @@ -64,6 +65,8 @@ // Only used for Google QUIC, not IETF QUIC. constexpr uint64_t kHpackEncoderDynamicTableSizeLimit = 16384; +constexpr QuicStreamCount kDefaultMaxWebTransportSessions = 16; + #define ENDPOINT \ (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ") @@ -537,7 +540,19 @@ } } if (WillNegotiateWebTransport()) { - settings_.values[SETTINGS_WEBTRANS_DRAFT00] = 1; + WebTransportHttp3VersionSet versions = + LocallySupportedWebTransportVersions(); + if (versions.IsSet(WebTransportHttp3Version::kDraft02)) { + settings_.values[SETTINGS_WEBTRANS_DRAFT00] = 1; + } + if (versions.IsSet(WebTransportHttp3Version::kDraft07)) { + QUICHE_BUG_IF( + WT_enabled_extended_connect_disabled, + perspective() == Perspective::IS_SERVER && !allow_extended_connect()) + << "WebTransport enabled, but extended CONNECT is not"; + settings_.values[SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07] = + kDefaultMaxWebTransportSessions; + } } if (allow_extended_connect()) { settings_.values[SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; @@ -889,7 +904,14 @@ } } -bool QuicSpdySession::ShouldNegotiateWebTransport() { return false; } +bool QuicSpdySession::ShouldNegotiateWebTransport() const { + return LocallySupportedWebTransportVersions().Any(); +} + +WebTransportHttp3VersionSet +QuicSpdySession::LocallySupportedWebTransportVersions() const { + return WebTransportHttp3VersionSet(); +} bool QuicSpdySession::WillNegotiateWebTransport() { return LocalHttpDatagramSupport() != HttpDatagramSupport::kNone && @@ -1019,6 +1041,10 @@ } } + if (!ValidateWebTransportSettingsConsistency()) { + return false; + } + // This is the last point in the connection when we can receive new SETTINGS // values (ALPS and settings from the session ticket come before, and only one // SETTINGS frame per connection is allowed). Notify all the streams that are @@ -1040,6 +1066,40 @@ return true; } +bool QuicSpdySession::ValidateWebTransportSettingsConsistency() { + // Only apply the following checks to draft-07 or later. + absl::optional<WebTransportHttp3Version> version = + NegotiatedWebTransportVersion(); + if (!version.has_value() || *version == WebTransportHttp3Version::kDraft02) { + return true; + } + + if (!allow_extended_connect_) { + CloseConnectionWithDetails( + QUIC_HTTP_INVALID_SETTING_VALUE, + "Negotiated use of WebTransport over HTTP/3 (draft-07 or later), but " + "failed to negotiate extended CONNECT"); + return false; + } + + if (http_datagram_support_ == HttpDatagramSupport::kDraft04) { + CloseConnectionWithDetails( + QUIC_HTTP_INVALID_SETTING_VALUE, + "WebTransport over HTTP/3 version draft-07 and beyond requires the " + "RFC version of HTTP datagrams"); + return false; + } + + if (http_datagram_support_ != HttpDatagramSupport::kRfc) { + CloseConnectionWithDetails( + QUIC_HTTP_INVALID_SETTING_VALUE, + "WebTransport over HTTP/3 requires HTTP datagrams support"); + return false; + } + + return true; +} + absl::optional<std::string> QuicSpdySession::OnSettingsFrameViaAlps( const SettingsFrame& frame) { QUICHE_DCHECK(VersionUsesHttp3(transport_version())); @@ -1216,14 +1276,32 @@ break; } QUIC_DVLOG(1) << ENDPOINT - << "SETTINGS_ENABLE_WEBTRANSPORT received with value " + << "SETTINGS_ENABLE_WEBTRANSPORT(02) received with value " << value; if (!VerifySettingIsZeroOrOne(id, value)) { return false; } - peer_supports_webtransport_ = (value == 1); - if (perspective() == Perspective::IS_CLIENT && value == 1) { - allow_extended_connect_ = true; + if (value == 1) { + peer_web_transport_versions_.Set(WebTransportHttp3Version::kDraft02); + if (perspective() == Perspective::IS_CLIENT) { + allow_extended_connect_ = true; + } + } + break; + case SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07: + if (!WillNegotiateWebTransport()) { + break; + } + QUIC_DVLOG(1) + << ENDPOINT + << "SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07 received with value " + << value; + if (value > 0) { + peer_web_transport_versions_.Set(WebTransportHttp3Version::kDraft07); + if (perspective() == Perspective::IS_CLIENT) { + max_webtransport_sessions_[WebTransportHttp3Version::kDraft07] = + value; + } } break; default: @@ -1699,7 +1777,15 @@ bool QuicSpdySession::SupportsWebTransport() { return WillNegotiateWebTransport() && SupportsH3Datagram() && - peer_supports_webtransport_ && allow_extended_connect_; + NegotiatedWebTransportVersion().has_value() && allow_extended_connect_; +} + +absl::optional<WebTransportHttp3Version> +QuicSpdySession::SupportedWebTransportVersion() { + if (!SupportsWebTransport()) { + return absl::nullopt; + } + return NegotiatedWebTransportVersion(); } bool QuicSpdySession::SupportsH3Datagram() const {
diff --git a/quiche/quic/core/http/quic_spdy_session.h b/quiche/quic/core/http/quic_spdy_session.h index 74ecd4f..627e226 100644 --- a/quiche/quic/core/http/quic_spdy_session.h +++ b/quiche/quic/core/http/quic_spdy_session.h
@@ -29,6 +29,7 @@ #include "quiche/quic/core/quic_stream_priority.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" +#include "quiche/quic/core/quic_utils.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/spdy/core/http2_frame_decoder_adapter.h" @@ -124,6 +125,26 @@ // version. }; +// Versions of WebTransport over HTTP/3 protocol extension. +enum class WebTransportHttp3Version : uint8_t { + // <https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-02.html> + // The first version to be ever publicly shipped in Chrome. Sometimes referred + // to as "draft-00", since draft-02 was backwards-compatible with draft-00. + kDraft02, + // <https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-07.html> + // See the changelog in the appendix for differences between draft-02 and + // draft-07. + kDraft07, +}; +using WebTransportHttp3VersionSet = BitMask<WebTransportHttp3Version, uint8_t>; + +// Note that by default, WebTransport is not enabled. Thus, those are the +// versions primarily used in the tools and unit tests. +inline constexpr WebTransportHttp3VersionSet + kDefaultSupportedWebTransportVersions = + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02, + WebTransportHttp3Version::kDraft07}); + QUIC_EXPORT_PRIVATE std::string HttpDatagramSupportToString( HttpDatagramSupport http_datagram_support); QUIC_EXPORT_PRIVATE std::ostream& operator<<( @@ -396,6 +417,10 @@ // Indicates whether the HTTP/3 session supports WebTransport. bool SupportsWebTransport(); + // If SupportsWebTransport() is true, returns the version of WebTransport + // currently in use (which is the highest version supported by both peers). + absl::optional<WebTransportHttp3Version> SupportedWebTransportVersion(); + // Indicates whether both the peer and us support HTTP/3 Datagrams. bool SupportsH3Datagram() const; @@ -473,7 +498,9 @@ // Indicates whether the underlying backend can accept and process // WebTransport sessions over HTTP/3. - virtual bool ShouldNegotiateWebTransport(); + virtual WebTransportHttp3VersionSet LocallySupportedWebTransportVersions() + const; + bool ShouldNegotiateWebTransport() const; // Returns true if there are open HTTP requests. bool ShouldKeepConnectionAlive() const override; @@ -565,6 +592,16 @@ bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value); + // Computes the highest WebTransport version supported by both peers. + absl::optional<WebTransportHttp3Version> NegotiatedWebTransportVersion() + const { + return (LocallySupportedWebTransportVersions() & + peer_web_transport_versions_) + .Max(); + } + + bool ValidateWebTransportSettingsConsistency(); + std::unique_ptr<QpackEncoder> qpack_encoder_; std::unique_ptr<QpackDecoder> qpack_decoder_; @@ -643,8 +680,8 @@ // draft is in use for this session. HttpDatagramSupport http_datagram_support_ = HttpDatagramSupport::kNone; - // Whether the peer has indicated WebTransport support. - bool peer_supports_webtransport_ = false; + // WebTransport protocol versions supported by the peer. + WebTransportHttp3VersionSet peer_web_transport_versions_; // Whether the SETTINGS frame has been received on the control stream. bool settings_received_ = false; @@ -661,6 +698,13 @@ // On the server side, if true, advertise and accept extended CONNECT method. // On the client side, true if the peer advertised extended CONNECT. bool allow_extended_connect_; + + // Since WebTransport is versioned by renumbering + // SETTINGS_WEBTRANSPORT_MAX_SESSIONS, the max sessions value depends on the + // version we end up picking. This is only stored on the client, as the + // server cannot initiate WebTransport sessions. + absl::flat_hash_map<WebTransportHttp3Version, QuicStreamCount> + max_webtransport_sessions_; }; } // namespace quic
diff --git a/quiche/quic/core/http/quic_spdy_session_test.cc b/quiche/quic/core/http/quic_spdy_session_test.cc index cf95ec7..ba1b6e3 100644 --- a/quiche/quic/core/http/quic_spdy_session_test.cc +++ b/quiche/quic/core/http/quic_spdy_session_test.cc
@@ -379,8 +379,19 @@ GetEncryptionLevelToSendApplicationData()); } - bool ShouldNegotiateWebTransport() override { return supports_webtransport_; } - void set_supports_webtransport(bool value) { supports_webtransport_ = value; } + WebTransportHttp3VersionSet LocallySupportedWebTransportVersions() + const override { + return locally_supported_web_transport_versions_; + } + void set_supports_webtransport(bool value) { + locally_supported_web_transport_versions_ = + value ? kDefaultSupportedWebTransportVersions + : WebTransportHttp3VersionSet(); + } + void set_locally_supported_web_transport_versions( + WebTransportHttp3VersionSet versions) { + locally_supported_web_transport_versions_ = std::move(versions); + } HttpDatagramSupport LocalHttpDatagramSupport() override { return local_http_datagram_support_; @@ -400,7 +411,7 @@ StrictMock<TestCryptoStream> crypto_stream_; bool writev_consumes_all_data_; - bool supports_webtransport_ = false; + WebTransportHttp3VersionSet locally_supported_web_transport_versions_; HttpDatagramSupport local_http_datagram_support_ = HttpDatagramSupport::kNone; }; @@ -539,10 +550,16 @@ testing::Mock::VerifyAndClearExpectations(connection_); } - void ReceiveWebTransportSettings() { + void ReceiveWebTransportSettings(WebTransportHttp3VersionSet versions = + kDefaultSupportedWebTransportVersions) { SettingsFrame settings; - settings.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; - settings.values[SETTINGS_WEBTRANS_DRAFT00] = 1; + settings.values[SETTINGS_H3_DATAGRAM] = 1; + if (versions.IsSet(WebTransportHttp3Version::kDraft02)) { + settings.values[SETTINGS_WEBTRANS_DRAFT00] = 1; + } + if (versions.IsSet(WebTransportHttp3Version::kDraft07)) { + settings.values[SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07] = 16; + } settings.values[SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; std::string data = std::string(1, kControlStream) + HttpEncoder::SerializeSettingsFrame(settings); @@ -3453,34 +3470,84 @@ /*expected_support=*/HttpDatagramSupport::kRfc, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, WebTransportSetting) { + +TEST_P(QuicSpdySessionTestClient, WebTransportSettingDraft02OnlyBothSides) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); - session_.set_supports_webtransport(true); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); + session_.set_locally_supported_web_transport_versions( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02})); EXPECT_FALSE(session_.SupportsWebTransport()); - - StrictMock<MockHttp3DebugVisitor> debug_visitor; - // Note that this does not actually fill out correct settings because the - // settings are filled in at the construction time. - EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_)); - session_.set_debug_visitor(&debug_visitor); CompleteHandshake(); - - EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(_)); - EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_)); - ReceiveWebTransportSettings(); + ReceiveWebTransportSettings( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02})); EXPECT_TRUE(session_.ShouldProcessIncomingRequests()); EXPECT_TRUE(session_.SupportsWebTransport()); + EXPECT_EQ(session_.SupportedWebTransportVersion(), + WebTransportHttp3Version::kDraft02); +} + +TEST_P(QuicSpdySessionTestClient, WebTransportSettingDraft07OnlyBothSides) { + if (!version().UsesHttp3()) { + return; + } + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); + session_.set_locally_supported_web_transport_versions( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft07})); + + EXPECT_FALSE(session_.SupportsWebTransport()); + CompleteHandshake(); + ReceiveWebTransportSettings( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft07})); + EXPECT_TRUE(session_.ShouldProcessIncomingRequests()); + EXPECT_TRUE(session_.SupportsWebTransport()); + EXPECT_EQ(session_.SupportedWebTransportVersion(), + WebTransportHttp3Version::kDraft07); +} + +TEST_P(QuicSpdySessionTestClient, WebTransportSettingBothDraftsBothSides) { + if (!version().UsesHttp3()) { + return; + } + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); + session_.set_locally_supported_web_transport_versions( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02, + WebTransportHttp3Version::kDraft07})); + + EXPECT_FALSE(session_.SupportsWebTransport()); + CompleteHandshake(); + ReceiveWebTransportSettings( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02, + WebTransportHttp3Version::kDraft07})); + EXPECT_TRUE(session_.ShouldProcessIncomingRequests()); + EXPECT_TRUE(session_.SupportsWebTransport()); + EXPECT_EQ(session_.SupportedWebTransportVersion(), + WebTransportHttp3Version::kDraft07); +} + +TEST_P(QuicSpdySessionTestClient, WebTransportSettingVersionMismatch) { + if (!version().UsesHttp3()) { + return; + } + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); + session_.set_locally_supported_web_transport_versions( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft07})); + + EXPECT_FALSE(session_.SupportsWebTransport()); + CompleteHandshake(); + ReceiveWebTransportSettings( + WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02})); + EXPECT_FALSE(session_.SupportsWebTransport()); + EXPECT_EQ(session_.SupportedWebTransportVersion(), absl::nullopt); } TEST_P(QuicSpdySessionTestClient, WebTransportSettingSetToZero) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3510,7 +3577,7 @@ if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3527,7 +3594,7 @@ if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3560,7 +3627,7 @@ if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3601,7 +3668,7 @@ if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3637,7 +3704,7 @@ return; } SetQuicReloadableFlag(quic_act_upon_invalid_header, true); - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kRfcAndDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport());
diff --git a/quiche/quic/core/http/quic_spdy_stream_test.cc b/quiche/quic/core/http/quic_spdy_stream_test.cc index 5e78cfb..024eefd 100644 --- a/quiche/quic/core/http/quic_spdy_stream_test.cc +++ b/quiche/quic/core/http/quic_spdy_stream_test.cc
@@ -297,8 +297,14 @@ return &crypto_stream_; } - bool ShouldNegotiateWebTransport() override { return enable_webtransport_; } - void EnableWebTransport() { enable_webtransport_ = true; } + WebTransportHttp3VersionSet LocallySupportedWebTransportVersions() + const override { + return locally_supported_webtransport_versions_; + } + void EnableWebTransport(WebTransportHttp3VersionSet versions = + kDefaultSupportedWebTransportVersions) { + locally_supported_webtransport_versions_ = versions; + } HttpDatagramSupport LocalHttpDatagramSupport() override { return local_http_datagram_support_; @@ -308,7 +314,7 @@ } private: - bool enable_webtransport_ = false; + WebTransportHttp3VersionSet locally_supported_webtransport_versions_; HttpDatagramSupport local_http_datagram_support_ = HttpDatagramSupport::kNone; StrictMock<TestCryptoStream> crypto_stream_; };
diff --git a/quiche/quic/core/quic_utils.h b/quiche/quic/core/quic_utils.h index 52108aa..4c3fdc9 100644 --- a/quiche/quic/core/quic_utils.h +++ b/quiche/quic/core/quic_utils.h
@@ -11,9 +11,11 @@ #include <string> #include <type_traits> +#include "absl/numeric/bits.h" #include "absl/numeric/int128.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "absl/types/span.h" #include "quiche/quic/core/crypto/quic_random.h" #include "quiche/quic/core/frames/quic_frame.h" @@ -253,12 +255,28 @@ constexpr void ClearAll() { mask_ = 0; } + // Returns true if any of the bits is set. + bool Any() const { return mask_ != 0; } + + // Returns the highest bit set, or nullopt if the mask is all zeroes. + absl::optional<Index> Max() const { + if (!Any()) { + return absl::nullopt; + } + return static_cast<Index>(NumBits() - absl::countl_zero(mask_) - 1); + } + static constexpr size_t NumBits() { return 8 * sizeof(Mask); } friend bool operator==(const BitMask& lhs, const BitMask& rhs) { return lhs.mask_ == rhs.mask_; } + // Bitwise AND that can act as a set intersection between two bit masks. + BitMask<Index, Mask> operator&(const BitMask<Index, Mask>& rhs) const { + return BitMask<Index, Mask>(mask_ & rhs.mask_); + } + std::string DebugString() const { return absl::StrCat("0x", absl::Hex(mask_)); } @@ -266,6 +284,8 @@ constexpr Mask mask() const { return mask_; } private: + explicit constexpr BitMask(Mask mask) : mask_(mask) {} + template <typename Bit> static constexpr std::enable_if_t<std::is_enum_v<Bit>, Mask> MakeMask( Bit bit) {
diff --git a/quiche/quic/core/quic_utils_test.cc b/quiche/quic/core/quic_utils_test.cc index 29401fb..239812f 100644 --- a/quiche/quic/core/quic_utils_test.cc +++ b/quiche/quic/core/quic_utils_test.cc
@@ -278,8 +278,10 @@ TEST(QuicBitMaskTest, Integer) { BitMask<int> mask({1, 3}); + EXPECT_EQ(mask.Max(), 3); mask.Set(3); mask.Set({5, 7, 9}); + EXPECT_EQ(mask.Max(), 9); EXPECT_FALSE(mask.IsSet(0)); EXPECT_TRUE(mask.IsSet(1)); EXPECT_FALSE(mask.IsSet(2)); @@ -315,6 +317,24 @@ EXPECT_TRUE(std::is_trivially_copyable<BitMask<int>>::value); } +TEST(QuicBitMaskTest, Any) { + BitMask<int> mask; + EXPECT_FALSE(mask.Any()); + mask.Set(3); + EXPECT_TRUE(mask.Any()); + mask.Set(2); + EXPECT_TRUE(mask.Any()); + mask.ClearAll(); + EXPECT_FALSE(mask.Any()); +} + +TEST(QuicBitMaskTest, And) { + using Mask = BitMask<int>; + EXPECT_EQ(Mask({1, 3, 6}) & Mask({3, 5, 6}), Mask({3, 6})); + EXPECT_EQ(Mask({1, 2, 4}) & Mask({3, 5}), Mask({})); + EXPECT_EQ(Mask({1, 2, 3, 4, 5}) & Mask({}), Mask({})); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quiche/quic/test_tools/quic_spdy_session_peer.cc b/quiche/quic/test_tools/quic_spdy_session_peer.cc index dd99a05..4da7254 100644 --- a/quiche/quic/test_tools/quic_spdy_session_peer.cc +++ b/quiche/quic/test_tools/quic_spdy_session_peer.cc
@@ -112,8 +112,8 @@ // static void QuicSpdySessionPeer::EnableWebTransport(QuicSpdySession* session) { QUICHE_DCHECK(session->WillNegotiateWebTransport()); - SetHttpDatagramSupport(session, HttpDatagramSupport::kDraft04); - session->peer_supports_webtransport_ = true; + SetHttpDatagramSupport(session, HttpDatagramSupport::kRfc); + session->peer_web_transport_versions_ = kDefaultSupportedWebTransportVersions; } } // namespace test
diff --git a/quiche/quic/tools/quic_simple_client_session.cc b/quiche/quic/tools/quic_simple_client_session.cc index ab44f5f..4bb27ae 100644 --- a/quiche/quic/tools/quic_simple_client_session.cc +++ b/quiche/quic/tools/quic_simple_client_session.cc
@@ -46,12 +46,14 @@ return stream; } -bool QuicSimpleClientSession::ShouldNegotiateWebTransport() { - return enable_web_transport_; +WebTransportHttp3VersionSet +QuicSimpleClientSession::LocallySupportedWebTransportVersions() const { + return enable_web_transport_ ? kDefaultSupportedWebTransportVersions + : WebTransportHttp3VersionSet(); } HttpDatagramSupport QuicSimpleClientSession::LocalHttpDatagramSupport() { - return enable_web_transport_ ? HttpDatagramSupport::kDraft04 + return enable_web_transport_ ? HttpDatagramSupport::kRfcAndDraft04 : HttpDatagramSupport::kNone; }
diff --git a/quiche/quic/tools/quic_simple_client_session.h b/quiche/quic/tools/quic_simple_client_session.h index 9d1b4c7..4850647 100644 --- a/quiche/quic/tools/quic_simple_client_session.h +++ b/quiche/quic/tools/quic_simple_client_session.h
@@ -38,7 +38,8 @@ bool drop_response_body, bool enable_web_transport); std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override; - bool ShouldNegotiateWebTransport() override; + WebTransportHttp3VersionSet LocallySupportedWebTransportVersions() + const override; HttpDatagramSupport LocalHttpDatagramSupport() override; void CreateContextForMultiPortPath( std::unique_ptr<MultiPortPathContextObserver> context_observer) override;
diff --git a/quiche/quic/tools/quic_simple_server_session.h b/quiche/quic/tools/quic_simple_server_session.h index bceb4e5..5585214 100644 --- a/quiche/quic/tools/quic_simple_server_session.h +++ b/quiche/quic/tools/quic_simple_server_session.h
@@ -66,8 +66,11 @@ return quic_simple_server_backend_; } - bool ShouldNegotiateWebTransport() override { - return quic_simple_server_backend_->SupportsWebTransport(); + WebTransportHttp3VersionSet LocallySupportedWebTransportVersions() + const override { + return quic_simple_server_backend_->SupportsWebTransport() + ? kDefaultSupportedWebTransportVersions + : WebTransportHttp3VersionSet(); } HttpDatagramSupport LocalHttpDatagramSupport() override { if (ShouldNegotiateWebTransport()) {