Unexport quic_transport. QuicTransport has been deprecated and removed in favor of WebTransport over HTTP/3. We still have some internal users relying on it, but there is no reason to make this code available as a part of public QUICHE repository anymore. PiperOrigin-RevId: 441441658
diff --git a/quiche/quic/quic_transport/README.md b/quiche/quic/quic_transport/README.md deleted file mode 100644 index e2f0849..0000000 --- a/quiche/quic/quic_transport/README.md +++ /dev/null
@@ -1,7 +0,0 @@ -# QuicTransport - -The files in this directory implement QuicTransport protocol as described in -<https://tools.ietf.org/html/draft-vvv-webtransport-quic>. - -Design doc: -https://docs.google.com/document/d/1UgviRBnZkMUq4OKcsAJvIQFX6UCXeCbOtX_wMgwD_es/edit#
diff --git a/quiche/quic/quic_transport/quic_transport_client_session.cc b/quiche/quic/quic_transport/quic_transport_client_session.cc deleted file mode 100644 index e96647a..0000000 --- a/quiche/quic/quic_transport/quic_transport_client_session.cc +++ /dev/null
@@ -1,260 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_client_session.h" - -#include <cstdint> -#include <limits> -#include <memory> -#include <string> -#include <utility> - -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "quiche/quic/core/quic_constants.h" -#include "quiche/quic/core/quic_crypto_client_stream.h" -#include "quiche/quic/core/quic_data_writer.h" -#include "quiche/quic/core/quic_error_codes.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -namespace quic { - -QuicTransportClientSession::QuicTransportClientSession( - QuicConnection* connection, Visitor* owner, const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, const GURL& url, - QuicCryptoClientConfig* crypto_config, url::Origin origin, - WebTransportVisitor* visitor, - std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer) - : QuicSession(connection, owner, config, supported_versions, - /*num_expected_unidirectional_static_streams*/ 0, - std::move(datagram_observer)), - url_(url), - origin_(origin), - visitor_(visitor) { - for (const ParsedQuicVersion& version : supported_versions) { - QUIC_BUG_IF(quic_bug_12035_1, version.handshake_protocol != PROTOCOL_TLS1_3) - << "QuicTransport requires TLS 1.3 handshake"; - } - crypto_stream_ = std::make_unique<QuicCryptoClientStream>( - QuicServerId(url.host(), url.EffectiveIntPort()), this, - crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config, - /*proof_handler=*/this, /*has_application_state = */ true); -} - -void QuicTransportClientSession::OnAlpnSelected(absl::string_view alpn) { - // Defense in-depth: ensure the ALPN selected is the desired one. - if (alpn != QuicTransportAlpn()) { - QUIC_BUG(quic_bug_10881_1) - << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn; - connection()->CloseConnection( - QUIC_INTERNAL_ERROR, "QuicTransport negotiated non-QuicTransport ALPN", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - - alpn_received_ = true; -} - -QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) { - QUIC_DVLOG(1) << "Creating incoming QuicTransport stream " << id; - QuicTransportStream* stream = CreateStream(id); - if (stream->type() == BIDIRECTIONAL) { - incoming_bidirectional_streams_.push_back(stream); - visitor_->OnIncomingBidirectionalStreamAvailable(); - } else { - incoming_unidirectional_streams_.push_back(stream); - visitor_->OnIncomingUnidirectionalStreamAvailable(); - } - return stream; -} - -void QuicTransportClientSession::SetDefaultEncryptionLevel( - EncryptionLevel level) { - QuicSession::SetDefaultEncryptionLevel(level); - if (level == ENCRYPTION_FORWARD_SECURE) { - SendClientIndication(); - } -} - -void QuicTransportClientSession::OnTlsHandshakeComplete() { - QuicSession::OnTlsHandshakeComplete(); - SendClientIndication(); -} - -QuicTransportStream* -QuicTransportClientSession::AcceptIncomingBidirectionalStream() { - if (incoming_bidirectional_streams_.empty()) { - return nullptr; - } - QuicTransportStream* stream = incoming_bidirectional_streams_.front(); - incoming_bidirectional_streams_.pop_front(); - return stream; -} - -QuicTransportStream* -QuicTransportClientSession::AcceptIncomingUnidirectionalStream() { - if (incoming_unidirectional_streams_.empty()) { - return nullptr; - } - QuicTransportStream* stream = incoming_unidirectional_streams_.front(); - incoming_unidirectional_streams_.pop_front(); - return stream; -} - -QuicTransportStream* -QuicTransportClientSession::OpenOutgoingBidirectionalStream() { - if (!CanOpenNextOutgoingBidirectionalStream()) { - QUIC_BUG(quic_bug_10881_2) - << "Attempted to open a stream in violation of flow control"; - return nullptr; - } - return CreateStream(GetNextOutgoingBidirectionalStreamId()); -} - -QuicTransportStream* -QuicTransportClientSession::OpenOutgoingUnidirectionalStream() { - if (!CanOpenNextOutgoingUnidirectionalStream()) { - QUIC_BUG(quic_bug_10881_3) - << "Attempted to open a stream in violation of flow control"; - return nullptr; - } - return CreateStream(GetNextOutgoingUnidirectionalStreamId()); -} - -QuicTransportStream* QuicTransportClientSession::CreateStream(QuicStreamId id) { - auto stream = std::make_unique<QuicTransportStream>(id, this, this); - QuicTransportStream* stream_ptr = stream.get(); - ActivateStream(std::move(stream)); - return stream_ptr; -} - -std::string QuicTransportClientSession::SerializeClientIndication() { - std::string serialized_origin = origin_.Serialize(); - if (serialized_origin.size() > std::numeric_limits<uint16_t>::max()) { - QUIC_BUG(quic_bug_10881_4) << "Client origin too long"; - connection()->CloseConnection( - QUIC_INTERNAL_ERROR, "Client origin too long", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return ""; - } - QUIC_DLOG(INFO) << "Sending client indication with origin " - << serialized_origin; - - std::string path = url_.PathForRequest(); - if (path.size() > std::numeric_limits<uint16_t>::max()) { - connection()->CloseConnection( - QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, "Requested URL path too long", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return ""; - } - - constexpr size_t kPrefixSize = - sizeof(QuicTransportClientIndicationKeys) + sizeof(uint16_t); - const size_t buffer_size = - 2 * kPrefixSize + serialized_origin.size() + path.size(); - if (buffer_size > std::numeric_limits<uint16_t>::max()) { - connection()->CloseConnection( - QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, - "Client indication size limit exceeded", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return ""; - } - - std::string buffer; - buffer.resize(buffer_size); - QuicDataWriter writer(buffer.size(), &buffer[0]); - bool success = - writer.WriteUInt16( - static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin)) && - writer.WriteUInt16(serialized_origin.size()) && - writer.WriteStringPiece(serialized_origin) && - writer.WriteUInt16( - static_cast<uint16_t>(QuicTransportClientIndicationKeys::kPath)) && - writer.WriteUInt16(path.size()) && writer.WriteStringPiece(path); - QUIC_BUG_IF(quic_bug_10881_5, !success) - << "Failed to serialize client indication"; - QUIC_BUG_IF(quic_bug_12035_2, writer.length() != buffer.length()) - << "Serialized client indication has length different from expected"; - return buffer; -} - -void QuicTransportClientSession::SendClientIndication() { - if (!crypto_stream_->encryption_established()) { - QUIC_BUG(quic_bug_10881_6) - << "Client indication may only be sent once the encryption is " - "established."; - connection()->CloseConnection( - QUIC_INTERNAL_ERROR, "Attempted to send client indication unencrypted", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - if (ready_) { - QUIC_BUG(quic_bug_10881_7) << "Client indication may only be sent once."; - connection()->CloseConnection( - QUIC_INTERNAL_ERROR, "Attempted to send client indication twice", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - - auto client_indication_owned = std::make_unique<ClientIndication>( - /*stream_id=*/GetNextOutgoingUnidirectionalStreamId(), this, - /*is_static=*/false, WRITE_UNIDIRECTIONAL); - QUIC_BUG_IF(quic_bug_12035_3, - client_indication_owned->id() != ClientIndicationStream()) - << "Client indication stream is " << client_indication_owned->id() - << " instead of expected " << ClientIndicationStream(); - ClientIndication* client_indication = client_indication_owned.get(); - ActivateStream(std::move(client_indication_owned)); - - client_indication->WriteOrBufferData(SerializeClientIndication(), - /*fin=*/true, nullptr); - client_indication_sent_ = true; - - // Defense in depth: never set the ready bit unless ALPN has been confirmed. - if (!alpn_received_) { - QUIC_BUG(quic_bug_10881_8) - << "ALPN confirmation missing after handshake complete"; - connection()->CloseConnection( - QUIC_INTERNAL_ERROR, - "ALPN confirmation missing after handshake complete", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - - // Don't set the ready bit if we closed the connection due to any error - // beforehand. - if (!connection()->connected()) { - return; - } - - ready_ = true; - visitor_->OnSessionReady(spdy::SpdyHeaderBlock()); -} - -void QuicTransportClientSession::OnMessageReceived(absl::string_view message) { - visitor_->OnDatagramReceived(message); -} - -void QuicTransportClientSession::OnCanCreateNewOutgoingStream( - bool unidirectional) { - if (unidirectional) { - visitor_->OnCanCreateNewOutgoingUnidirectionalStream(); - } else { - visitor_->OnCanCreateNewOutgoingBidirectionalStream(); - } -} - -void QuicTransportClientSession::OnProofValid( - const QuicCryptoClientConfig::CachedState& /*cached*/) {} - -void QuicTransportClientSession::OnProofVerifyDetailsAvailable( - const ProofVerifyDetails& /*verify_details*/) {} - -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_client_session.h b/quiche/quic/quic_transport/quic_transport_client_session.h deleted file mode 100644 index e537ffb..0000000 --- a/quiche/quic/quic_transport/quic_transport_client_session.h +++ /dev/null
@@ -1,172 +0,0 @@ -// Copyright (c) 2019 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. - -#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_CLIENT_SESSION_H_ -#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_CLIENT_SESSION_H_ - -#include <cstdint> -#include <memory> - -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "url/origin.h" -#include "quiche/quic/core/crypto/quic_crypto_client_config.h" -#include "quiche/quic/core/quic_config.h" -#include "quiche/quic/core/quic_connection.h" -#include "quiche/quic/core/quic_crypto_client_stream.h" -#include "quiche/quic/core/quic_crypto_stream.h" -#include "quiche/quic/core/quic_datagram_queue.h" -#include "quiche/quic/core/quic_error_codes.h" -#include "quiche/quic/core/quic_server_id.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/core/quic_stream.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/core/web_transport_interface.h" -#include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/quic_transport/quic_transport_session_interface.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" -#include "quiche/common/platform/api/quiche_mem_slice.h" - -namespace quic { - -// A client session for the QuicTransport protocol. -class QUIC_EXPORT_PRIVATE QuicTransportClientSession - : public QuicSession, - public WebTransportSession, - public QuicTransportSessionInterface, - public QuicCryptoClientStream::ProofHandler { - public: - QuicTransportClientSession( - QuicConnection* connection, Visitor* owner, const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, const GURL& url, - QuicCryptoClientConfig* crypto_config, url::Origin origin, - WebTransportVisitor* visitor, - std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer); - - std::vector<std::string> GetAlpnsToOffer() const override { - return std::vector<std::string>({QuicTransportAlpn()}); - } - void OnAlpnSelected(absl::string_view alpn) override; - bool alpn_received() const { return alpn_received_; } - - void CryptoConnect() { crypto_stream_->CryptoConnect(); } - - bool ShouldKeepConnectionAlive() const override { return true; } - - QuicCryptoStream* GetMutableCryptoStream() override { - return crypto_stream_.get(); - } - const QuicCryptoStream* GetCryptoStream() const override { - return crypto_stream_.get(); - } - - // Returns true once the encryption has been established and the client - // indication has been sent. No application data will be read or written - // before the connection is ready. Once the connection becomes ready, this - // method will never return false. - bool IsSessionReady() const override { return ready_; } - - QuicStream* CreateIncomingStream(QuicStreamId id) override; - QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override { - QUIC_BUG(quic_bug_10890_1) - << "QuicTransportClientSession::CreateIncomingStream(" - "PendingStream) not implemented"; - return nullptr; - } - - void SetDefaultEncryptionLevel(EncryptionLevel level) override; - void OnTlsHandshakeComplete() override; - void OnMessageReceived(absl::string_view message) override; - - // 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. - QuicTransportStream* AcceptIncomingBidirectionalStream() override; - QuicTransportStream* AcceptIncomingUnidirectionalStream() override; - - bool CanOpenNextOutgoingBidirectionalStream() override { - return QuicSession::CanOpenNextOutgoingBidirectionalStream(); - } - bool CanOpenNextOutgoingUnidirectionalStream() override { - return QuicSession::CanOpenNextOutgoingUnidirectionalStream(); - } - QuicTransportStream* OpenOutgoingBidirectionalStream() override; - QuicTransportStream* OpenOutgoingUnidirectionalStream() override; - - MessageStatus SendOrQueueDatagram(quiche::QuicheMemSlice datagram) override { - return datagram_queue()->SendOrQueueDatagram(std::move(datagram)); - } - void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) override { - datagram_queue()->SetMaxTimeInQueue(max_time_in_queue); - } - - // For unit tests. - using QuicSession::datagram_queue; - - // QuicCryptoClientStream::ProofHandler implementation. - void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; - void OnProofVerifyDetailsAvailable( - const ProofVerifyDetails& verify_details) override; - - void CloseSession(WebTransportSessionError /*error_code*/, - absl::string_view error_message) override { - connection()->CloseConnection( - QUIC_NO_ERROR, std::string(error_message), - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - } - - QuicByteCount GetMaxDatagramSize() const override { - return GetGuaranteedLargestMessagePayload(); - } - - protected: - class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream { - public: - using QuicStream::QuicStream; - - // This method should never be called, since the stream is client-initiated - // unidirectional. - void OnDataAvailable() override { - QUIC_BUG(quic_bug_10890_2) << "Received data on a write-only stream"; - } - }; - - // Creates and activates a QuicTransportStream for the given ID. - QuicTransportStream* CreateStream(QuicStreamId id); - - // Serializes the client indication as described in - // https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2 - std::string SerializeClientIndication(); - // Creates the client indication stream and sends the client indication on it. - void SendClientIndication(); - - void OnCanCreateNewOutgoingStream(bool unidirectional) override; - - std::unique_ptr<QuicCryptoClientStream> crypto_stream_; - GURL url_; - url::Origin origin_; - WebTransportVisitor* visitor_; // not owned - bool client_indication_sent_ = false; - bool alpn_received_ = false; - bool ready_ = false; - - // Contains all of the streams that has been received by the session but have - // not been processed by the application. - // TODO(vasilvv): currently, we always send MAX_STREAMS as long as the overall - // maximum number of streams for the connection has not been exceeded. We - // should also limit the maximum number of streams that the consuming code - // has not accepted to a smaller number, by checking the size of - // |incoming_bidirectional_streams_| and |incoming_unidirectional_streams_| - // before sending MAX_STREAMS. - quiche::QuicheCircularDeque<QuicTransportStream*> - incoming_bidirectional_streams_; - quiche::QuicheCircularDeque<QuicTransportStream*> - incoming_unidirectional_streams_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_CLIENT_SESSION_H_
diff --git a/quiche/quic/quic_transport/quic_transport_client_session_test.cc b/quiche/quic/quic_transport/quic_transport_client_session_test.cc deleted file mode 100644 index ac3977f..0000000 --- a/quiche/quic/quic_transport/quic_transport_client_session_test.cc +++ /dev/null
@@ -1,180 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_client_session.h" - -#include <memory> -#include <utility> - -#include "absl/base/macros.h" -#include "url/gurl.h" -#include "quiche/quic/core/quic_data_writer.h" -#include "quiche/quic/core/quic_server_id.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_utils.h" -#include "quiche/quic/platform/api/quic_expect_bug.h" -#include "quiche/quic/platform/api/quic_test.h" -#include "quiche/quic/test_tools/crypto_test_utils.h" -#include "quiche/quic/test_tools/quic_session_peer.h" -#include "quiche/quic/test_tools/quic_stream_peer.h" -#include "quiche/quic/test_tools/quic_test_utils.h" -#include "quiche/quic/test_tools/quic_transport_test_tools.h" - -namespace quic { -namespace test { -namespace { - -using testing::_; -using testing::ElementsAre; -using testing::Eq; - -const char* kTestOrigin = "https://test-origin.test"; -url::Origin GetTestOrigin() { - GURL origin_url(kTestOrigin); - return url::Origin::Create(origin_url); -} - -ParsedQuicVersionVector GetVersions() { - return {DefaultVersionForQuicTransport()}; -} - -std::string DataInStream(QuicStream* stream) { - QuicStreamSendBuffer& send_buffer = QuicStreamPeer::SendBuffer(stream); - std::string result; - result.resize(send_buffer.stream_offset()); - QuicDataWriter writer(result.size(), &result[0]); - EXPECT_TRUE( - send_buffer.WriteStreamData(0, send_buffer.stream_offset(), &writer)); - return result; -} - -class QuicTransportClientSessionTest : public QuicTest { - protected: - QuicTransportClientSessionTest() - : connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT, - GetVersions()), - crypto_config_(crypto_test_utils::ProofVerifierForTesting()) { - QuicEnableVersion(DefaultVersionForQuicTransport()); - CreateSession(GetTestOrigin(), ""); - } - - void CreateSession(url::Origin origin, std::string url_suffix) { - session_ = std::make_unique<QuicTransportClientSession>( - &connection_, nullptr, DefaultQuicConfig(), GetVersions(), - GURL("quic-transport://test.example.com:50000" + url_suffix), - &crypto_config_, origin, &visitor_, /*datagram_observer=*/nullptr); - session_->Initialize(); - crypto_stream_ = static_cast<QuicCryptoClientStream*>( - session_->GetMutableCryptoStream()); - } - - void Connect() { - session_->CryptoConnect(); - QuicConfig server_config = DefaultQuicConfig(); - std::unique_ptr<QuicCryptoServerConfig> crypto_config( - crypto_test_utils::CryptoServerConfigForTesting()); - crypto_test_utils::HandshakeWithFakeServer( - &server_config, crypto_config.get(), &helper_, &alarm_factory_, - &connection_, crypto_stream_, QuicTransportAlpn()); - } - - MockAlarmFactory alarm_factory_; - MockQuicConnectionHelper helper_; - - PacketSavingConnection connection_; - QuicCryptoClientConfig crypto_config_; - MockClientVisitor visitor_; - std::unique_ptr<QuicTransportClientSession> session_; - QuicCryptoClientStream* crypto_stream_; -}; - -TEST_F(QuicTransportClientSessionTest, HasValidAlpn) { - EXPECT_THAT(session_->GetAlpnsToOffer(), ElementsAre(QuicTransportAlpn())); -} - -TEST_F(QuicTransportClientSessionTest, SuccessfulConnection) { - constexpr char kTestOriginClientIndication[] = - "\0\0" // key (0x0000, origin) - "\0\x18" // length - "https://test-origin.test" // value - "\0\x01" // key (0x0001, path) - "\0\x01" // length - "/"; // value - - EXPECT_CALL(visitor_, OnSessionReady(_)); - Connect(); - EXPECT_TRUE(session_->IsSessionReady()); - - QuicStream* client_indication_stream; - client_indication_stream = - QuicSessionPeer::stream_map(session_.get())[ClientIndicationStream()] - .get(); - ASSERT_TRUE(client_indication_stream != nullptr); - const std::string client_indication = DataInStream(client_indication_stream); - const std::string expected_client_indication{ - kTestOriginClientIndication, - ABSL_ARRAYSIZE(kTestOriginClientIndication) - 1}; - EXPECT_EQ(client_indication, expected_client_indication); -} - -TEST_F(QuicTransportClientSessionTest, SuccessfulConnectionWithPath) { - constexpr char kSuffix[] = "/foo/bar?hello=world#not-sent"; - constexpr char kTestOriginClientIndication[] = - "\0\0" // key (0x0000, origin) - "\0\x18" // length - "https://test-origin.test" // value - "\0\x01" // key (0x0001, path) - "\0\x14" // length - "/foo/bar?hello=world"; // value - - CreateSession(GetTestOrigin(), kSuffix); - Connect(); - EXPECT_TRUE(session_->IsSessionReady()); - - QuicStream* client_indication_stream; - client_indication_stream = - QuicSessionPeer::stream_map(session_.get())[ClientIndicationStream()] - .get(); - ASSERT_TRUE(client_indication_stream != nullptr); - const std::string client_indication = DataInStream(client_indication_stream); - const std::string expected_client_indication{ - kTestOriginClientIndication, - ABSL_ARRAYSIZE(kTestOriginClientIndication) - 1}; - EXPECT_EQ(client_indication, expected_client_indication); -} - -TEST_F(QuicTransportClientSessionTest, OriginTooLong) { - std::string long_string(68000, 'a'); - GURL bad_origin_url{"https://" + long_string + ".example/"}; - EXPECT_TRUE(bad_origin_url.is_valid()); - CreateSession(url::Origin::Create(bad_origin_url), ""); - - EXPECT_QUIC_BUG(Connect(), "Client origin too long"); -} - -TEST_F(QuicTransportClientSessionTest, ReceiveNewStreams) { - Connect(); - ASSERT_TRUE(session_->IsSessionReady()); - ASSERT_TRUE(session_->AcceptIncomingUnidirectionalStream() == nullptr); - - const QuicStreamId id = GetNthServerInitiatedUnidirectionalStreamId( - session_->transport_version(), 0); - QuicStreamFrame frame(id, /*fin=*/false, /*offset=*/0, "test"); - EXPECT_CALL(visitor_, OnIncomingUnidirectionalStreamAvailable()).Times(1); - session_->OnStreamFrame(frame); - - QuicTransportStream* stream = session_->AcceptIncomingUnidirectionalStream(); - ASSERT_TRUE(stream != nullptr); - EXPECT_EQ(stream->ReadableBytes(), 4u); - EXPECT_EQ(stream->id(), id); -} - -TEST_F(QuicTransportClientSessionTest, ReceiveDatagram) { - EXPECT_CALL(visitor_, OnDatagramReceived(Eq("test"))); - session_->OnMessageReceived("test"); -} - -} // namespace -} // namespace test -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_integration_test.cc b/quiche/quic/quic_transport/quic_transport_integration_test.cc deleted file mode 100644 index 1826426..0000000 --- a/quiche/quic/quic_transport/quic_transport_integration_test.cc +++ /dev/null
@@ -1,399 +0,0 @@ -// Copyright (c) 2019 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. - -// An integration test that covers interactions between QuicTransport client and -// server sessions. - -#include <memory> -#include <vector> - -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "url/origin.h" -#include "quiche/quic/core/crypto/quic_crypto_client_config.h" -#include "quiche/quic/core/crypto/quic_crypto_server_config.h" -#include "quiche/quic/core/quic_connection.h" -#include "quiche/quic/core/quic_error_codes.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_flags.h" -#include "quiche/quic/platform/api/quic_test.h" -#include "quiche/quic/quic_transport/quic_transport_client_session.h" -#include "quiche/quic/quic_transport/quic_transport_server_session.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" -#include "quiche/quic/test_tools/crypto_test_utils.h" -#include "quiche/quic/test_tools/quic_session_peer.h" -#include "quiche/quic/test_tools/quic_test_utils.h" -#include "quiche/quic/test_tools/quic_transport_test_tools.h" -#include "quiche/quic/test_tools/simulator/link.h" -#include "quiche/quic/test_tools/simulator/quic_endpoint_base.h" -#include "quiche/quic/test_tools/simulator/simulator.h" -#include "quiche/quic/test_tools/simulator/switch.h" -#include "quiche/quic/tools/quic_transport_simple_server_session.h" - -namespace quic { -namespace test { -namespace { - -using simulator::QuicEndpointBase; -using simulator::Simulator; -using testing::_; -using testing::Assign; -using testing::Eq; - -url::Origin GetTestOrigin() { - constexpr char kTestOrigin[] = "https://test-origin.test"; - GURL origin_url(kTestOrigin); - return url::Origin::Create(origin_url); -} - -ParsedQuicVersionVector GetVersions() { - return {DefaultVersionForQuicTransport()}; -} - -class QuicTransportEndpointBase : public QuicEndpointBase { - public: - QuicTransportEndpointBase(Simulator* simulator, const std::string& name, - const std::string& peer_name, - Perspective perspective) - : QuicEndpointBase(simulator, name, peer_name) { - QuicEnableVersion(DefaultVersionForQuicTransport()); - connection_ = std::make_unique<QuicConnection>( - TestConnectionId(0x10), simulator::GetAddressFromName(name), - simulator::GetAddressFromName(peer_name), simulator, - simulator->GetAlarmFactory(), &writer_, - /*owns_writer=*/false, perspective, GetVersions()); - connection_->SetSelfAddress(simulator::GetAddressFromName(name)); - } -}; - -class QuicTransportClientEndpoint : public QuicTransportEndpointBase { - public: - QuicTransportClientEndpoint(Simulator* simulator, const std::string& name, - const std::string& peer_name, - const QuicConfig& config, url::Origin origin, - const std::string& path) - : QuicTransportEndpointBase(simulator, name, peer_name, - Perspective::IS_CLIENT), - crypto_config_(crypto_test_utils::ProofVerifierForTesting()), - session_(connection_.get(), nullptr, config, GetVersions(), - GURL("quic-transport://test.example.com:50000" + path), - &crypto_config_, origin, &visitor_, - /*datagram_observer=*/nullptr) { - session_.Initialize(); - } - - QuicTransportClientSession* session() { return &session_; } - MockClientVisitor* visitor() { return &visitor_; } - - private: - QuicCryptoClientConfig crypto_config_; - MockClientVisitor visitor_; - QuicTransportClientSession session_; -}; - -class QuicTransportServerEndpoint : public QuicTransportEndpointBase { - public: - QuicTransportServerEndpoint(Simulator* simulator, const std::string& name, - const std::string& peer_name, - const QuicConfig& config, - std::vector<url::Origin> accepted_origins) - : QuicTransportEndpointBase(simulator, name, peer_name, - Perspective::IS_SERVER), - crypto_config_(QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default()), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), - session_(connection_.get(), - /*owns_connection=*/false, nullptr, config, GetVersions(), - &crypto_config_, &compressed_certs_cache_, accepted_origins) { - session_.Initialize(); - } - - QuicTransportServerSession* session() { return &session_; } - - private: - QuicCryptoServerConfig crypto_config_; - QuicCompressedCertsCache compressed_certs_cache_; - QuicTransportSimpleServerSession session_; -}; - -constexpr QuicBandwidth kClientBandwidth = - QuicBandwidth::FromKBitsPerSecond(10000); -constexpr QuicTime::Delta kClientPropagationDelay = - QuicTime::Delta::FromMilliseconds(2); -constexpr QuicBandwidth kServerBandwidth = - QuicBandwidth::FromKBitsPerSecond(4000); -constexpr QuicTime::Delta kServerPropagationDelay = - QuicTime::Delta::FromMilliseconds(50); -const QuicTime::Delta kTransferTime = - kClientBandwidth.TransferTime(kMaxOutgoingPacketSize) + - kServerBandwidth.TransferTime(kMaxOutgoingPacketSize); -const QuicTime::Delta kRtt = - (kClientPropagationDelay + kServerPropagationDelay + kTransferTime) * 2; -const QuicByteCount kBdp = kRtt * kServerBandwidth; - -constexpr QuicTime::Delta kDefaultTimeout = QuicTime::Delta::FromSeconds(3); - -class QuicTransportIntegrationTest : public QuicTest { - public: - QuicTransportIntegrationTest() - : switch_(&simulator_, "Switch", 8, 2 * kBdp) {} - - void CreateDefaultEndpoints(const std::string& path) { - client_ = std::make_unique<QuicTransportClientEndpoint>( - &simulator_, "Client", "Server", client_config_, GetTestOrigin(), path); - server_ = std::make_unique<QuicTransportServerEndpoint>( - &simulator_, "Server", "Client", server_config_, accepted_origins_); - } - - void WireUpEndpoints() { - client_link_ = std::make_unique<simulator::SymmetricLink>( - client_.get(), switch_.port(1), kClientBandwidth, - kClientPropagationDelay); - server_link_ = std::make_unique<simulator::SymmetricLink>( - server_.get(), switch_.port(2), kServerBandwidth, - kServerPropagationDelay); - } - - void RunHandshake() { - client_->session()->CryptoConnect(); - bool result = simulator_.RunUntilOrTimeout( - [this]() { - return IsHandshakeDone(client_->session()) && - IsHandshakeDone(server_->session()); - }, - kDefaultTimeout); - EXPECT_TRUE(result); - } - - protected: - template <class Session> - static bool IsHandshakeDone(const Session* session) { - return session->IsSessionReady() || session->error() != QUIC_NO_ERROR; - } - - QuicConfig client_config_ = DefaultQuicConfig(); - QuicConfig server_config_ = DefaultQuicConfig(); - - Simulator simulator_; - simulator::Switch switch_; - std::unique_ptr<simulator::SymmetricLink> client_link_; - std::unique_ptr<simulator::SymmetricLink> server_link_; - - std::unique_ptr<QuicTransportClientEndpoint> client_; - std::unique_ptr<QuicTransportServerEndpoint> server_; - - std::vector<url::Origin> accepted_origins_ = {GetTestOrigin()}; -}; - -TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) { - CreateDefaultEndpoints("/discard"); - WireUpEndpoints(); - EXPECT_CALL(*client_->visitor(), OnSessionReady(_)); - RunHandshake(); - EXPECT_TRUE(client_->session()->IsSessionReady()); - EXPECT_TRUE(server_->session()->IsSessionReady()); -} - -TEST_F(QuicTransportIntegrationTest, OriginMismatch) { - accepted_origins_ = {url::Origin::Create(GURL{"https://wrong-origin.test"})}; - CreateDefaultEndpoints("/discard"); - WireUpEndpoints(); - RunHandshake(); - // Wait until the client receives CONNECTION_CLOSE. - simulator_.RunUntilOrTimeout( - [this]() { return !client_->session()->connection()->connected(); }, - kDefaultTimeout); - EXPECT_TRUE(client_->session()->IsSessionReady()); - EXPECT_FALSE(server_->session()->IsSessionReady()); - EXPECT_FALSE(client_->session()->connection()->connected()); - EXPECT_FALSE(server_->session()->connection()->connected()); - EXPECT_THAT(client_->session()->error(), - IsError(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION)); - EXPECT_THAT(server_->session()->error(), - IsError(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION)); -} - -TEST_F(QuicTransportIntegrationTest, SendOutgoingStreams) { - CreateDefaultEndpoints("/discard"); - WireUpEndpoints(); - RunHandshake(); - - std::vector<QuicTransportStream*> streams; - for (int i = 0; i < 10; i++) { - QuicTransportStream* stream = - client_->session()->OpenOutgoingUnidirectionalStream(); - ASSERT_TRUE(stream->Write("test")); - streams.push_back(stream); - } - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { - return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == - 10; - }, - kDefaultTimeout)); - - for (QuicTransportStream* stream : streams) { - ASSERT_TRUE(stream->SendFin()); - } - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { - return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == - 0; - }, - kDefaultTimeout)); -} - -TEST_F(QuicTransportIntegrationTest, EchoBidirectionalStreams) { - CreateDefaultEndpoints("/echo"); - WireUpEndpoints(); - RunHandshake(); - - QuicTransportStream* stream = - client_->session()->OpenOutgoingBidirectionalStream(); - EXPECT_TRUE(stream->Write("Hello!")); - - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [stream]() { return stream->ReadableBytes() == strlen("Hello!"); }, - kDefaultTimeout)); - std::string received; - WebTransportStream::ReadResult result = stream->Read(&received); - EXPECT_EQ(result.bytes_read, strlen("Hello!")); - EXPECT_FALSE(result.fin); - EXPECT_EQ(received, "Hello!"); - - EXPECT_TRUE(stream->SendFin()); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { - return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == - 0; - }, - kDefaultTimeout)); -} - -TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) { - CreateDefaultEndpoints("/echo"); - WireUpEndpoints(); - RunHandshake(); - - // Send two streams, but only send FIN on the second one. - QuicTransportStream* stream1 = - client_->session()->OpenOutgoingUnidirectionalStream(); - EXPECT_TRUE(stream1->Write("Stream One")); - QuicTransportStream* stream2 = - client_->session()->OpenOutgoingUnidirectionalStream(); - EXPECT_TRUE(stream2->Write("Stream Two")); - EXPECT_TRUE(stream2->SendFin()); - - // Wait until a stream is received. - bool stream_received = false; - EXPECT_CALL(*client_->visitor(), OnIncomingUnidirectionalStreamAvailable()) - .Times(2) - .WillRepeatedly(Assign(&stream_received, true)); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [&stream_received]() { return stream_received; }, kDefaultTimeout)); - - // Receive a reply stream and expect it to be the second one. - QuicTransportStream* reply = - client_->session()->AcceptIncomingUnidirectionalStream(); - ASSERT_TRUE(reply != nullptr); - std::string buffer; - WebTransportStream::ReadResult result = reply->Read(&buffer); - EXPECT_GT(result.bytes_read, 0u); - EXPECT_TRUE(result.fin); - EXPECT_EQ(buffer, "Stream Two"); - - // Reset reply-related variables. - stream_received = false; - buffer = ""; - - // Send FIN on the first stream, and expect to receive it back. - EXPECT_TRUE(stream1->SendFin()); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [&stream_received]() { return stream_received; }, kDefaultTimeout)); - reply = client_->session()->AcceptIncomingUnidirectionalStream(); - ASSERT_TRUE(reply != nullptr); - result = reply->Read(&buffer); - EXPECT_GT(result.bytes_read, 0u); - EXPECT_TRUE(result.fin); - EXPECT_EQ(buffer, "Stream One"); -} - -TEST_F(QuicTransportIntegrationTest, EchoDatagram) { - CreateDefaultEndpoints("/echo"); - WireUpEndpoints(); - RunHandshake(); - - client_->session()->SendOrQueueDatagram(MemSliceFromString("test")); - - bool datagram_received = false; - EXPECT_CALL(*client_->visitor(), OnDatagramReceived(Eq("test"))) - .WillOnce(Assign(&datagram_received, true)); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [&datagram_received]() { return datagram_received; }, kDefaultTimeout)); -} - -// This test sets the datagram queue to an nearly-infinte queueing time, and -// then sends 1000 datagrams. We expect to receive most of them back, since the -// datagrams would be paced out by the congestion controller. -TEST_F(QuicTransportIntegrationTest, EchoALotOfDatagrams) { - CreateDefaultEndpoints("/echo"); - WireUpEndpoints(); - RunHandshake(); - - // Set the datagrams to effectively never expire. - client_->session()->SetDatagramMaxTimeInQueue(10000 * kRtt); - for (int i = 0; i < 1000; i++) { - client_->session()->SendOrQueueDatagram(MemSliceFromString(std::string( - client_->session()->GetGuaranteedLargestMessagePayload(), 'a'))); - } - - size_t received = 0; - EXPECT_CALL(*client_->visitor(), OnDatagramReceived(_)) - .WillRepeatedly( - [&received](absl::string_view /*datagram*/) { received++; }); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { return client_->session()->datagram_queue()->empty(); }, - 3 * kServerBandwidth.TransferTime(1000 * kMaxOutgoingPacketSize))); - // Allow extra round-trips for the final flight of datagrams to arrive back. - simulator_.RunFor(2 * kRtt); - - EXPECT_GT(received, 500u); - EXPECT_LT(received, 1000u); -} - -TEST_F(QuicTransportIntegrationTest, OutgoingStreamFlowControlBlocked) { - server_config_.SetMaxUnidirectionalStreamsToSend(4); - CreateDefaultEndpoints("/discard"); - WireUpEndpoints(); - RunHandshake(); - - QuicTransportStream* stream; - // Note that since we've already used one stream for client indication, we can - // only send three streams at once. - for (int i = 0; i < 3; i++) { - ASSERT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); - stream = client_->session()->OpenOutgoingUnidirectionalStream(); - ASSERT_TRUE(stream != nullptr); - ASSERT_TRUE(stream->SendFin()); - } - EXPECT_FALSE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); - - // Receiving FINs for the streams we've just opened will cause the server to - // let us open more streams. - bool can_create_new_stream = false; - EXPECT_CALL(*client_->visitor(), OnCanCreateNewOutgoingUnidirectionalStream()) - .WillOnce(Assign(&can_create_new_stream, true)); - ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [&can_create_new_stream]() { return can_create_new_stream; }, - kDefaultTimeout)); - EXPECT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); -} - -} // namespace -} // namespace test -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_protocol.h b/quiche/quic/quic_transport/quic_transport_protocol.h deleted file mode 100644 index e173cce..0000000 --- a/quiche/quic/quic_transport/quic_transport_protocol.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright (c) 2019 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. - -#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_PROTOCOL_H_ -#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_PROTOCOL_H_ - -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_logging.h" - -namespace quic { - -// The ALPN used by QuicTransport. -QUIC_EXPORT_PRIVATE inline const char* QuicTransportAlpn() { - return "wq-vvv-01"; -} - -// The stream ID on which the client indication is sent. -QUIC_EXPORT_PRIVATE constexpr QuicStreamId ClientIndicationStream() { - return 2; -} - -// The maximum allowed size of the client indication. -QUIC_EXPORT_PRIVATE constexpr QuicByteCount ClientIndicationMaxSize() { - return 65536; -} - -// The keys of the fields in the client indication. -enum class QuicTransportClientIndicationKeys : uint16_t { - kOrigin = 0x0000, - kPath = 0x0001, -}; - -// Returns if the specified QUIC version can be used by QuicTransport. -QUIC_EXPORT_PRIVATE constexpr bool IsVersionValidForQuicTransport( - const ParsedQuicVersion& version) { - return VersionSupportsMessageFrames(version.transport_version) && - VersionHasIetfQuicFrames(version.transport_version) && - version.handshake_protocol == PROTOCOL_TLS1_3; -} - -// Returns default QUIC version used for QuicTransport. -QUIC_EXPORT_PRIVATE inline ParsedQuicVersion DefaultVersionForQuicTransport() { - constexpr ParsedQuicVersion version = ParsedQuicVersion::Draft29(); - static_assert(IsVersionValidForQuicTransport(version), - "Default QUIC version used by QuicTransport is invalid"); - return version; -} - -} // namespace quic - -#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_PROTOCOL_H_
diff --git a/quiche/quic/quic_transport/quic_transport_server_session.cc b/quiche/quic/quic_transport/quic_transport_server_session.cc deleted file mode 100644 index cc0b4c2..0000000 --- a/quiche/quic/quic_transport/quic_transport_server_session.cc +++ /dev/null
@@ -1,207 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_server_session.h" - -#include <algorithm> -#include <memory> -#include <string> - -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "url/url_constants.h" -#include "quiche/quic/core/quic_error_codes.h" -#include "quiche/quic/core/quic_stream.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -namespace quic { - -namespace { -class QuicTransportServerCryptoHelper - : public QuicCryptoServerStreamBase::Helper { - public: - bool CanAcceptClientHello(const CryptoHandshakeMessage& /*message*/, - const QuicSocketAddress& /*client_address*/, - const QuicSocketAddress& /*peer_address*/, - const QuicSocketAddress& /*self_address*/, - std::string* /*error_details*/) const override { - return true; - } -}; - -} // namespace - -QuicTransportServerSession::QuicTransportServerSession( - QuicConnection* connection, Visitor* owner, const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, ServerVisitor* visitor) - : QuicSession(connection, owner, config, supported_versions, - /*num_expected_unidirectional_static_streams*/ 0), - visitor_(visitor) { - for (const ParsedQuicVersion& version : supported_versions) { - QUIC_BUG_IF(quic_bug_12025_1, version.handshake_protocol != PROTOCOL_TLS1_3) - << "QuicTransport requires TLS 1.3 handshake"; - } - - static QuicTransportServerCryptoHelper* helper = - new QuicTransportServerCryptoHelper(); - crypto_stream_ = CreateCryptoServerStream( - crypto_config, compressed_certs_cache, this, helper); -} - -QuicStream* QuicTransportServerSession::CreateIncomingStream(QuicStreamId id) { - if (id == ClientIndicationStream()) { - auto indication = std::make_unique<ClientIndication>(this); - ClientIndication* indication_ptr = indication.get(); - ActivateStream(std::move(indication)); - return indication_ptr; - } - - auto stream = std::make_unique<QuicTransportStream>(id, this, this); - QuicTransportStream* stream_ptr = stream.get(); - ActivateStream(std::move(stream)); - OnIncomingDataStream(stream_ptr); - return stream_ptr; -} - -QuicTransportServerSession::ClientIndication::ClientIndication( - QuicTransportServerSession* session) - : QuicStream(ClientIndicationStream(), session, - /* is_static= */ false, StreamType::READ_UNIDIRECTIONAL), - session_(session) {} - -void QuicTransportServerSession::ClientIndication::OnDataAvailable() { - sequencer()->Read(&buffer_); - if (buffer_.size() > ClientIndicationMaxSize()) { - session_->connection()->CloseConnection( - QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, - absl::StrCat("Client indication size exceeds ", - ClientIndicationMaxSize(), " bytes"), - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - if (sequencer()->IsClosed()) { - session_->ProcessClientIndication(buffer_); - OnFinRead(); - } -} - -bool QuicTransportServerSession::ClientIndicationParser::Parse() { - bool origin_received = false; - bool path_received = false; - while (!reader_.IsDoneReading()) { - uint16_t key; - if (!reader_.ReadUInt16(&key)) { - ParseError("Expected 16-bit key"); - return false; - } - - absl::string_view value; - if (!reader_.ReadStringPiece16(&value)) { - ParseError(absl::StrCat("Failed to read value for key ", key)); - return false; - } - - switch (static_cast<QuicTransportClientIndicationKeys>(key)) { - case QuicTransportClientIndicationKeys::kOrigin: { - GURL origin_url{std::string(value)}; - if (!origin_url.is_valid()) { - Error("Unable to parse the specified origin"); - return false; - } - - url::Origin origin = url::Origin::Create(origin_url); - QUIC_DLOG(INFO) << "QuicTransport server received origin " << origin; - if (!session_->visitor_->CheckOrigin(origin)) { - Error("Origin check failed"); - return false; - } - origin_received = true; - break; - } - - case QuicTransportClientIndicationKeys::kPath: { - if (!ProcessPath(value)) { - return false; - } - path_received = true; - break; - } - - default: - QUIC_DLOG(INFO) << "Unknown client indication key: " << key; - break; - } - } - - if (!origin_received) { - Error("No origin received"); - return false; - } - if (!path_received) { - Error("No path received"); - return false; - } - - return true; -} - -bool QuicTransportServerSession::ClientIndicationParser::ProcessPath( - absl::string_view path) { - if (path.empty() || path[0] != '/') { - // https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.2.2 - Error("Path must begin with a '/'"); - return false; - } - - // TODO(b/145674008): use the SNI value from the handshake instead of the IP - // address. - std::string url_text = - absl::StrCat(url::kQuicTransportScheme, url::kStandardSchemeSeparator, - session_->self_address().ToString(), path); - GURL url{url_text}; - if (!url.is_valid()) { - Error("Invalid path specified"); - return false; - } - - if (!session_->visitor_->ProcessPath(url)) { - Error("Specified path rejected"); - return false; - } - return true; -} - -void QuicTransportServerSession::ClientIndicationParser::Error( - const std::string& error_message) { - session_->connection()->CloseConnection( - QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, error_message, - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); -} - -void QuicTransportServerSession::ClientIndicationParser::ParseError( - absl::string_view error_message) { - Error(absl::StrCat("Failed to parse the client indication stream: ", - error_message, reader_.DebugString())); -} - -void QuicTransportServerSession::ProcessClientIndication( - absl::string_view indication) { - ClientIndicationParser parser(this, indication); - if (!parser.Parse()) { - return; - } - // Don't set the ready bit if we closed the connection due to any error - // beforehand. - if (!connection()->connected()) { - return; - } - ready_ = true; -} - -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_server_session.h b/quiche/quic/quic_transport/quic_transport_server_session.h deleted file mode 100644 index 1b74e72..0000000 --- a/quiche/quic/quic_transport/quic_transport_server_session.h +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright (c) 2019 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. - -#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SERVER_SESSION_H_ -#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SERVER_SESSION_H_ - -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "url/origin.h" -#include "quiche/quic/core/quic_connection.h" -#include "quiche/quic/core/quic_crypto_server_stream_base.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/quic_transport/quic_transport_session_interface.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -namespace quic { - -// A server session for the QuicTransport protocol. -class QUIC_EXPORT_PRIVATE QuicTransportServerSession - : public QuicSession, - public QuicTransportSessionInterface { - public: - class QUIC_EXPORT_PRIVATE ServerVisitor { - public: - virtual ~ServerVisitor() {} - - // Allows the server to decide whether the specified origin is allowed to - // connect to it. - virtual bool CheckOrigin(url::Origin origin) = 0; - - // Indicates that the server received a path parameter from the client. The - // path parameter is parsed, and can be retrived from url.path() and - // url.query(). If this method returns false, the connection is closed. - virtual bool ProcessPath(const GURL& url) = 0; - }; - - QuicTransportServerSession(QuicConnection* connection, Visitor* owner, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - ServerVisitor* visitor); - - std::vector<absl::string_view>::const_iterator SelectAlpn( - const std::vector<absl::string_view>& alpns) const override { - return std::find(alpns.cbegin(), alpns.cend(), QuicTransportAlpn()); - } - - bool ShouldKeepConnectionAlive() const override { return true; } - - QuicCryptoServerStreamBase* GetMutableCryptoStream() override { - return crypto_stream_.get(); - } - const QuicCryptoServerStreamBase* GetCryptoStream() const override { - return crypto_stream_.get(); - } - - // Returns true once the encryption has been established, the client - // indication has been received and the origin has been verified. No - // application data will be read or written before the connection is ready. - // Once the connection becomes ready, this method will never return false. - bool IsSessionReady() const override { return ready_; } - - QuicStream* CreateIncomingStream(QuicStreamId id) override; - QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override { - QUIC_BUG(quic_bug_10884_1) - << "QuicTransportServerSession::CreateIncomingStream(" - "PendingStream) not implemented"; - return nullptr; - } - - protected: - class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream { - public: - explicit ClientIndication(QuicTransportServerSession* session); - void OnDataAvailable() override; - - private: - QuicTransportServerSession* session_; - std::string buffer_; - }; - - // Utility class for parsing the client indication. - class QUIC_EXPORT_PRIVATE ClientIndicationParser { - public: - ClientIndicationParser(QuicTransportServerSession* session, - absl::string_view indication) - : session_(session), reader_(indication) {} - - // Parses the specified indication. Automatically closes the connection - // with detailed error if parsing fails. Returns true on success, false on - // failure. - bool Parse(); - - private: - void Error(const std::string& error_message); - void ParseError(absl::string_view error_message); - - // Processes the path portion of the client indication. - bool ProcessPath(absl::string_view path); - - QuicTransportServerSession* session_; - QuicDataReader reader_; - }; - - // Parses and processes the client indication as described in - // https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2 - void ProcessClientIndication(absl::string_view indication); - - virtual void OnIncomingDataStream(QuicTransportStream* /*stream*/) {} - - std::unique_ptr<QuicCryptoServerStreamBase> crypto_stream_; - bool ready_ = false; - ServerVisitor* visitor_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SERVER_SESSION_H_
diff --git a/quiche/quic/quic_transport/quic_transport_server_session_test.cc b/quiche/quic/quic_transport/quic_transport_server_session_test.cc deleted file mode 100644 index 0a9d8e2..0000000 --- a/quiche/quic/quic_transport/quic_transport_server_session_test.cc +++ /dev/null
@@ -1,289 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_server_session.h" - -#include <cstddef> -#include <memory> -#include <string> - -#include "absl/strings/string_view.h" -#include "url/gurl.h" -#include "url/origin.h" -#include "quiche/quic/core/crypto/quic_compressed_certs_cache.h" -#include "quiche/quic/core/crypto/quic_crypto_server_config.h" -#include "quiche/quic/core/frames/quic_stream_frame.h" -#include "quiche/quic/core/quic_data_writer.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_test.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/test_tools/crypto_test_utils.h" -#include "quiche/quic/test_tools/quic_test_utils.h" -#include "quiche/quic/test_tools/quic_transport_test_tools.h" -#include "quiche/common/quiche_text_utils.h" - -namespace quic { -namespace test { -namespace { - -using testing::_; -using testing::AnyNumber; -using testing::DoAll; -using testing::HasSubstr; -using testing::Return; -using testing::SaveArg; - -constexpr char kTestOrigin[] = "https://test-origin.test"; -constexpr char kTestOriginClientIndication[] = - "\0\0" // key (0x0000, origin) - "\0\x18" // length - "https://test-origin.test" // value - "\0\x01" // key (0x0001, path) - "\0\x05" // length - "/test"; // value -const url::Origin GetTestOrigin() { - return url::Origin::Create(GURL(kTestOrigin)); -} -const std::string GetTestOriginClientIndication() { - return std::string(kTestOriginClientIndication, - sizeof(kTestOriginClientIndication) - 1); -} - -ParsedQuicVersionVector GetVersions() { - return {DefaultVersionForQuicTransport()}; -} - -class QuicTransportServerSessionTest : public QuicTest { - public: - QuicTransportServerSessionTest() - : connection_(&helper_, &alarm_factory_, Perspective::IS_SERVER, - GetVersions()), - crypto_config_(QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default()), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { - QuicEnableVersion(DefaultVersionForQuicTransport()); - connection_.AdvanceTime(QuicTime::Delta::FromSeconds(100000)); - crypto_test_utils::SetupCryptoServerConfigForTest( - helper_.GetClock(), helper_.GetRandomGenerator(), &crypto_config_); - session_ = std::make_unique<QuicTransportServerSession>( - &connection_, nullptr, DefaultQuicConfig(), GetVersions(), - &crypto_config_, &compressed_certs_cache_, &visitor_); - session_->Initialize(); - crypto_stream_ = session_->GetMutableCryptoStream(); - ON_CALL(visitor_, ProcessPath(_)) - .WillByDefault(DoAll(SaveArg<0>(&path_), Return(true))); - } - - void Connect() { - crypto_test_utils::FakeClientOptions options; - options.only_tls_versions = true; - crypto_test_utils::HandshakeWithFakeClient( - &helper_, &alarm_factory_, &connection_, crypto_stream_, - QuicServerId("test.example.com", 443), options, QuicTransportAlpn()); - } - - void ReceiveIndication(absl::string_view indication) { - QUIC_LOG(INFO) << "Receiving indication: " - << quiche::QuicheTextUtils::HexDump(indication); - constexpr size_t kChunkSize = 1024; - // Shard the indication, since some of the tests cause it to not fit into a - // single frame. - for (size_t i = 0; i < indication.size(); i += kChunkSize) { - QuicStreamFrame frame(ClientIndicationStream(), /*fin=*/false, i, - indication.substr(i, i + kChunkSize)); - session_->OnStreamFrame(frame); - } - session_->OnStreamFrame(QuicStreamFrame(ClientIndicationStream(), - /*fin=*/true, indication.size(), - absl::string_view())); - } - - void ReceiveIndicationWithPath(absl::string_view path) { - constexpr char kTestOriginClientIndicationPrefix[] = - "\0\0" // key (0x0000, origin) - "\0\x18" // length - "https://test-origin.test" // value - "\0\x01"; // key (0x0001, path) - std::string indication{kTestOriginClientIndicationPrefix, - sizeof(kTestOriginClientIndicationPrefix) - 1}; - indication.push_back(static_cast<char>(path.size() >> 8)); - indication.push_back(static_cast<char>(path.size() & 0xff)); - indication += std::string{path}; - ReceiveIndication(indication); - } - - protected: - MockAlarmFactory alarm_factory_; - MockQuicConnectionHelper helper_; - - PacketSavingConnection connection_; - QuicCryptoServerConfig crypto_config_; - std::unique_ptr<QuicTransportServerSession> session_; - QuicCompressedCertsCache compressed_certs_cache_; - testing::NiceMock<MockServerVisitor> visitor_; - QuicCryptoServerStreamBase* crypto_stream_; - GURL path_; -}; - -TEST_F(QuicTransportServerSessionTest, SuccessfulHandshake) { - Connect(); - - url::Origin origin; - EXPECT_CALL(visitor_, CheckOrigin(_)) - .WillOnce(DoAll(SaveArg<0>(&origin), Return(true))); - ReceiveIndication(GetTestOriginClientIndication()); - EXPECT_TRUE(session_->IsSessionReady()); - EXPECT_EQ(origin, GetTestOrigin()); - EXPECT_EQ(path_.path(), "/test"); -} - -TEST_F(QuicTransportServerSessionTest, PiecewiseClientIndication) { - Connect(); - size_t i = 0; - for (; i < sizeof(kTestOriginClientIndication) - 2; i++) { - QuicStreamFrame frame( - ClientIndicationStream(), false, i, - absl::string_view(&kTestOriginClientIndication[i], 1)); - session_->OnStreamFrame(frame); - } - - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - QuicStreamFrame last_frame( - ClientIndicationStream(), true, i, - absl::string_view(&kTestOriginClientIndication[i], 1)); - session_->OnStreamFrame(last_frame); - EXPECT_TRUE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, OriginRejected) { - Connect(); - EXPECT_CALL(connection_, - CloseConnection(_, HasSubstr("Origin check failed"), _)); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(false)); - ReceiveIndication(GetTestOriginClientIndication()); - EXPECT_FALSE(session_->IsSessionReady()); -} - -std::string MakeUnknownField(absl::string_view payload) { - std::string buffer; - buffer.resize(payload.size() + 4); - QuicDataWriter writer(buffer.size(), &buffer[0]); - EXPECT_TRUE(writer.WriteUInt16(0xffff)); - EXPECT_TRUE(writer.WriteUInt16(payload.size())); - EXPECT_TRUE(writer.WriteStringPiece(payload)); - EXPECT_EQ(writer.remaining(), 0u); - return buffer; -} - -TEST_F(QuicTransportServerSessionTest, SkipUnusedFields) { - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - ReceiveIndication(GetTestOriginClientIndication() + - MakeUnknownField("foobar")); - EXPECT_TRUE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, SkipLongUnusedFields) { - const size_t bytes = - ClientIndicationMaxSize() - GetTestOriginClientIndication().size() - 4; - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - ReceiveIndication(GetTestOriginClientIndication() + - MakeUnknownField(std::string(bytes, 'a'))); - EXPECT_TRUE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, ClientIndicationTooLong) { - Connect(); - EXPECT_CALL( - connection_, - CloseConnection(_, HasSubstr("Client indication size exceeds"), _)) - .Times(AnyNumber()); - ReceiveIndication(GetTestOriginClientIndication() + - MakeUnknownField(std::string(65534, 'a'))); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, NoOrigin) { - Connect(); - EXPECT_CALL(connection_, CloseConnection(_, HasSubstr("No origin"), _)); - ReceiveIndication(MakeUnknownField("foobar")); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, EmptyClientIndication) { - Connect(); - EXPECT_CALL(connection_, CloseConnection(_, HasSubstr("No origin"), _)); - ReceiveIndication(""); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, MalformedIndicationHeader) { - Connect(); - EXPECT_CALL(connection_, - CloseConnection(_, HasSubstr("Expected 16-bit key"), _)); - ReceiveIndication("\xff"); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, FieldTooShort) { - Connect(); - EXPECT_CALL( - connection_, - CloseConnection(_, HasSubstr("Failed to read value for key 257"), _)); - ReceiveIndication("\x01\x01\x01\x01"); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, InvalidOrigin) { - const std::string kEmptyOriginIndication(4, '\0'); - Connect(); - EXPECT_CALL( - connection_, - CloseConnection(_, HasSubstr("Unable to parse the specified origin"), _)); - ReceiveIndication(kEmptyOriginIndication); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, PathWithQuery) { - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - ReceiveIndicationWithPath("/test?foo=bar"); - EXPECT_TRUE(session_->IsSessionReady()); - EXPECT_EQ(path_.path(), "/test"); - EXPECT_EQ(path_.query(), "foo=bar"); -} - -TEST_F(QuicTransportServerSessionTest, PathNormalization) { - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - ReceiveIndicationWithPath("/foo/../bar"); - EXPECT_TRUE(session_->IsSessionReady()); - EXPECT_EQ(path_.path(), "/bar"); -} - -TEST_F(QuicTransportServerSessionTest, EmptyPath) { - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - EXPECT_CALL(connection_, - CloseConnection(_, HasSubstr("Path must begin with a '/'"), _)); - ReceiveIndicationWithPath(""); - EXPECT_FALSE(session_->IsSessionReady()); -} - -TEST_F(QuicTransportServerSessionTest, UnprefixedPath) { - Connect(); - EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true)); - EXPECT_CALL(connection_, - CloseConnection(_, HasSubstr("Path must begin with a '/'"), _)); - ReceiveIndicationWithPath("test"); - EXPECT_FALSE(session_->IsSessionReady()); -} - -} // namespace -} // namespace test -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_session_interface.h b/quiche/quic/quic_transport/quic_transport_session_interface.h deleted file mode 100644 index aad71f0..0000000 --- a/quiche/quic/quic_transport/quic_transport_session_interface.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2019 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. - -#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_INTERFACE_H_ -#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_INTERFACE_H_ - -#include "quiche/quic/platform/api/quic_export.h" - -namespace quic { - -// Shared interface between QuicTransportClientSession and -// QuicTransportServerSession. -class QUIC_EXPORT_PRIVATE QuicTransportSessionInterface { - public: - virtual ~QuicTransportSessionInterface() {} - - // Indicates whether the client indication has been sent/received and the - // connection is thus ready to send/receive application data. Note that the - // expectation for this API is that once it becomes true, it will never - // transition to false. - virtual bool IsSessionReady() const = 0; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_INTERFACE_H_
diff --git a/quiche/quic/quic_transport/quic_transport_stream.cc b/quiche/quic/quic_transport/quic_transport_stream.cc deleted file mode 100644 index efa770e..0000000 --- a/quiche/quic/quic_transport/quic_transport_stream.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -#include <sys/types.h> - -#include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_error_codes.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_utils.h" - -namespace quic { - -QuicTransportStream::QuicTransportStream( - QuicStreamId id, QuicSession* session, - QuicTransportSessionInterface* session_interface) - : QuicStream(id, session, - /*is_static=*/false, - QuicUtils::GetStreamType( - id, session->connection()->perspective(), - session->IsIncomingStream(id), session->version())), - adapter_(session, this, sequencer()), - session_interface_(session_interface) {} - -WebTransportStream::ReadResult QuicTransportStream::Read(char* buffer, - size_t buffer_size) { - if (!session_interface_->IsSessionReady()) { - return ReadResult{0, false}; - } - - return adapter_.Read(buffer, buffer_size); -} - -WebTransportStream::ReadResult QuicTransportStream::Read(std::string* output) { - if (!session_interface_->IsSessionReady()) { - return ReadResult{0, false}; - } - - return adapter_.Read(output); -} - -bool QuicTransportStream::Write(absl::string_view data) { - if (!CanWrite()) { - return false; - } - - return adapter_.Write(data); -} - -bool QuicTransportStream::SendFin() { - if (!CanWrite()) { - return false; - } - - return adapter_.SendFin(); -} - -bool QuicTransportStream::CanWrite() const { - return session_interface_->IsSessionReady() && adapter_.CanWrite(); -} - -size_t QuicTransportStream::ReadableBytes() const { - if (!session_interface_->IsSessionReady()) { - return 0; - } - - return adapter_.ReadableBytes(); -} - -void QuicTransportStream::OnDataAvailable() { adapter_.OnDataAvailable(); } - -void QuicTransportStream::OnCanWriteNewData() { - // Ensure the origin check has been completed, as the stream can be notified - // about being writable before that. - if (!CanWrite()) { - return; - } - adapter_.OnCanWriteNewData(); -} - -} // namespace quic
diff --git a/quiche/quic/quic_transport/quic_transport_stream.h b/quiche/quic/quic_transport/quic_transport_stream.h deleted file mode 100644 index 28c791b..0000000 --- a/quiche/quic/quic_transport/quic_transport_stream.h +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright (c) 2019 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. - -#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_ -#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_ - -#include <cstddef> -#include <memory> - -#include "absl/base/attributes.h" -#include "absl/strings/string_view.h" -#include "quiche/quic/core/http/web_transport_stream_adapter.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/core/quic_stream.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/web_transport_interface.h" -#include "quiche/quic/quic_transport/quic_transport_session_interface.h" - -namespace quic { - -// QuicTransportStream is an extension of QuicStream that provides I/O interface -// that is safe to use in the QuicTransport context. The interface ensures no -// application data is processed before the client indication is processed. -class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream, - public WebTransportStream { - public: - QuicTransportStream(QuicStreamId id, QuicSession* session, - QuicTransportSessionInterface* session_interface); - - // Reads at most |buffer_size| bytes into |buffer| and returns the number of - // bytes actually read. - ReadResult Read(char* buffer, size_t buffer_size) override; - // Reads all available data and appends it to the end of |output|. - ReadResult Read(std::string* output) override; - // Writes |data| into the stream. Returns true on success. - ABSL_MUST_USE_RESULT bool Write(absl::string_view data) override; - // Sends the FIN on the stream. Returns true on success. - ABSL_MUST_USE_RESULT bool SendFin() override; - - // Indicates whether it is possible to write into stream right now. - bool CanWrite() const override; - // Indicates the number of bytes that can be read from the stream. - size_t ReadableBytes() const override; - - // QuicSession method implementations. - void OnDataAvailable() override; - void OnCanWriteNewData() override; - - QuicStreamId GetStreamId() const override { return id(); } - - void ResetWithUserCode(WebTransportStreamError /*error*/) override { - adapter_.ResetWithUserCode(0); - } - void ResetDueToInternalError() override { - adapter_.ResetDueToInternalError(); - } - void SendStopSending(WebTransportStreamError /*error*/) override { - adapter_.SendStopSending(0); - } - void MaybeResetDueToStreamObjectGone() override { - adapter_.MaybeResetDueToStreamObjectGone(); - } - - WebTransportStreamVisitor* visitor() override { return adapter_.visitor(); } - void SetVisitor(std::unique_ptr<WebTransportStreamVisitor> visitor) override { - adapter_.SetVisitor(std::move(visitor)); - } - - protected: - // Hide the methods that allow writing data without checking IsSessionReady(). - using QuicStream::WriteMemSlices; - using QuicStream::WriteOrBufferData; - - void MaybeNotifyFinRead(); - - WebTransportStreamAdapter adapter_; - QuicTransportSessionInterface* session_interface_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_
diff --git a/quiche/quic/quic_transport/quic_transport_stream_test.cc b/quiche/quic/quic_transport/quic_transport_stream_test.cc deleted file mode 100644 index 46fa227..0000000 --- a/quiche/quic/quic_transport/quic_transport_stream_test.cc +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright (c) 2019 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. - -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -#include <memory> - -#include "absl/memory/memory.h" -#include "absl/strings/string_view.h" -#include "quiche/quic/core/crypto/null_encrypter.h" -#include "quiche/quic/core/frames/quic_window_update_frame.h" -#include "quiche/quic/platform/api/quic_expect_bug.h" -#include "quiche/quic/platform/api/quic_test.h" -#include "quiche/quic/quic_transport/quic_transport_session_interface.h" -#include "quiche/quic/test_tools/quic_config_peer.h" -#include "quiche/quic/test_tools/quic_test_utils.h" -#include "quiche/quic/test_tools/quic_transport_test_tools.h" - -namespace quic { -namespace test { -namespace { - -using testing::_; -using testing::Return; - -ParsedQuicVersionVector GetVersions() { - return {DefaultVersionForQuicTransport()}; -} - -class MockQuicTransportSessionInterface : public QuicTransportSessionInterface { - public: - MOCK_METHOD(bool, IsSessionReady, (), (const, override)); -}; - -class QuicTransportStreamTest : public QuicTest { - public: - QuicTransportStreamTest() - : connection_(new MockQuicConnection( - &helper_, &alarm_factory_, Perspective::IS_CLIENT, GetVersions())), - session_(connection_) { - QuicEnableVersion(DefaultVersionForQuicTransport()); - session_.Initialize(); - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(connection_->perspective())); - stream_ = new QuicTransportStream(0, &session_, &interface_); - session_.ActivateStream(absl::WrapUnique(stream_)); - - auto visitor = std::make_unique<MockStreamVisitor>(); - visitor_ = visitor.get(); - stream_->SetVisitor(std::move(visitor)); - } - - void ReceiveStreamData(absl::string_view data, QuicStreamOffset offset) { - QuicStreamFrame frame(0, false, offset, data); - stream_->OnStreamFrame(frame); - } - - protected: - MockAlarmFactory alarm_factory_; - MockQuicConnectionHelper helper_; - - MockQuicConnection* connection_; // Owned by |session_|. - MockQuicSession session_; - MockQuicTransportSessionInterface interface_; - QuicTransportStream* stream_; // Owned by |session_|. - MockStreamVisitor* visitor_; // Owned by |stream_|. -}; - -TEST_F(QuicTransportStreamTest, NotReady) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false)); - ReceiveStreamData("test", 0); - EXPECT_EQ(stream_->ReadableBytes(), 0u); - EXPECT_FALSE(stream_->CanWrite()); -} - -TEST_F(QuicTransportStreamTest, ReadWhenNotReady) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false)); - ReceiveStreamData("test", 0); - char buffer[4]; - WebTransportStream::ReadResult result = stream_->Read(buffer, sizeof(buffer)); - EXPECT_EQ(result.bytes_read, 0u); - EXPECT_FALSE(result.fin); -} - -TEST_F(QuicTransportStreamTest, WriteWhenNotReady) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false)); - EXPECT_FALSE(stream_->Write("test")); -} - -TEST_F(QuicTransportStreamTest, Ready) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - ReceiveStreamData("test", 0); - EXPECT_EQ(stream_->ReadableBytes(), 4u); - EXPECT_TRUE(stream_->CanWrite()); - EXPECT_TRUE(stream_->Write("test")); -} - -TEST_F(QuicTransportStreamTest, ReceiveData) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(*visitor_, OnCanRead()); - ReceiveStreamData("test", 0); - - std::string buffer; - WebTransportStream::ReadResult result = stream_->Read(&buffer); - EXPECT_EQ(result.bytes_read, 4u); - EXPECT_FALSE(result.fin); - EXPECT_EQ(buffer, "test"); -} - -TEST_F(QuicTransportStreamTest, FinReadWithNoDataPending) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(*visitor_, OnCanRead()); - - QuicStreamFrame frame(0, true, 0, ""); - stream_->OnStreamFrame(frame); - - std::string buffer; - WebTransportStream::ReadResult result = stream_->Read(&buffer); - EXPECT_EQ(result.bytes_read, 0u); - EXPECT_TRUE(result.fin); - EXPECT_EQ(buffer, ""); -} - -TEST_F(QuicTransportStreamTest, FinReadWithDataPending) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - - EXPECT_CALL(*visitor_, OnCanRead()); - QuicStreamFrame frame(0, true, 0, "test"); - stream_->OnStreamFrame(frame); - - char buffer[2]; - WebTransportStream::ReadResult result = stream_->Read(buffer, sizeof(buffer)); - EXPECT_EQ(result.bytes_read, 2u); - EXPECT_FALSE(result.fin); - EXPECT_EQ(buffer[0], 't'); - EXPECT_EQ(buffer[1], 'e'); - - result = stream_->Read(buffer, sizeof(buffer)); - EXPECT_EQ(result.bytes_read, 2u); - EXPECT_TRUE(result.fin); - EXPECT_EQ(buffer[0], 's'); - EXPECT_EQ(buffer[1], 't'); -} - -TEST_F(QuicTransportStreamTest, WritingTooMuchData) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - ASSERT_TRUE(stream_->CanWrite()); - - std::string a_little_bit_of_data(128, 'A'); - std::string a_lot_of_data(GetQuicFlag(FLAGS_quic_buffered_data_threshold) * 2, - 'a'); - - EXPECT_TRUE(stream_->Write(a_little_bit_of_data)); - EXPECT_TRUE(stream_->Write(a_little_bit_of_data)); - EXPECT_TRUE(stream_->Write(a_little_bit_of_data)); - - EXPECT_TRUE(stream_->Write(a_lot_of_data)); - EXPECT_FALSE(stream_->Write(a_lot_of_data)); -} - -TEST_F(QuicTransportStreamTest, CannotSendFinTwice) { - EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); - ASSERT_TRUE(stream_->CanWrite()); - - EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) - .WillOnce(Return(QuicConsumedData(0, /*fin_consumed=*/true))); - EXPECT_TRUE(stream_->SendFin()); - EXPECT_FALSE(stream_->CanWrite()); -} - -} // namespace -} // namespace test -} // namespace quic