Skip to content

Commit

Permalink
Abstract QuicTransportClient API into WebTransportClient
Browse files Browse the repository at this point in the history
Bug: 1193408, 1193409
Change-Id: I6399de2a6fbf63baf0a917b7e1384907a8395d39
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2804811
Commit-Queue: Victor Vasiliev <vasilvv@chromium.org>
Reviewed-by: David Schinazi <dschinazi@chromium.org>
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#869310}
  • Loading branch information
Victor Vasiliev authored and Chromium LUCI CQ committed Apr 5, 2021
1 parent df5950d commit ac81b02
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 121 deletions.
2 changes: 2 additions & 0 deletions net/BUILD.gn
Expand Up @@ -939,6 +939,8 @@ component("net") {
"quic/quic_transport_client.h",
"quic/quic_transport_error.cc",
"quic/quic_transport_error.h",
"quic/web_transport_client.cc",
"quic/web_transport_client.h",
"quiche/common/platform/impl/quiche_bug_tracker_impl.h",
"quiche/common/platform/impl/quiche_flag_utils_impl.h",
"quiche/common/platform/impl/quiche_flags_impl.cc",
Expand Down
27 changes: 14 additions & 13 deletions net/quic/quic_transport_client.cc
Expand Up @@ -35,7 +35,7 @@ std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
std::unique_ptr<quic::ProofVerifier> CreateProofVerifier(
const NetworkIsolationKey& isolation_key,
URLRequestContext* context,
const QuicTransportClient::Parameters& parameters) {
const WebTransportParameters& parameters) {
if (parameters.server_certificate_fingerprints.empty()) {
return std::make_unique<ProofVerifierChromium>(
context->cert_verifier(), context->ct_policy_enforcer(),
Expand All @@ -59,18 +59,13 @@ std::unique_ptr<quic::ProofVerifier> CreateProofVerifier(
}
} // namespace

QuicTransportClient::Parameters::Parameters() = default;
QuicTransportClient::Parameters::~Parameters() = default;
QuicTransportClient::Parameters::Parameters(const Parameters&) = default;
QuicTransportClient::Parameters::Parameters(Parameters&&) = default;

QuicTransportClient::QuicTransportClient(
const GURL& url,
const url::Origin& origin,
Visitor* visitor,
WebTransportClientVisitor* visitor,
const NetworkIsolationKey& isolation_key,
URLRequestContext* context,
const Parameters& parameters)
const WebTransportParameters& parameters)
: url_(url),
origin_(origin),
isolation_key_(isolation_key),
Expand All @@ -94,8 +89,6 @@ QuicTransportClient::QuicTransportClient(

QuicTransportClient::~QuicTransportClient() = default;

QuicTransportClient::Visitor::~Visitor() = default;

void QuicTransportClient::Connect() {
if (state_ != NEW || next_connect_state_ != CONNECT_STATE_NONE) {
NOTREACHED();
Expand All @@ -107,7 +100,15 @@ void QuicTransportClient::Connect() {
DoLoop(OK);
}

quic::QuicTransportClientSession* QuicTransportClient::session() {
const QuicTransportError& QuicTransportClient::error() const {
return error_;
}

quic::WebTransportSession* QuicTransportClient::session() {
return quic_session();
}

quic::QuicTransportClientSession* QuicTransportClient::quic_session() {
if (session_ == nullptr || !session_->IsSessionReady())
return nullptr;
return session_.get();
Expand Down Expand Up @@ -311,8 +312,8 @@ int QuicTransportClient::DoConfirmConnection() {
return OK;
}

void QuicTransportClient::TransitionToState(State next_state) {
const State last_state = state_;
void QuicTransportClient::TransitionToState(WebTransportState next_state) {
const WebTransportState last_state = state_;
state_ = next_state;
switch (next_state) {
case CONNECTING:
Expand Down
85 changes: 14 additions & 71 deletions net/quic/quic_transport_client.h
Expand Up @@ -15,10 +15,12 @@
#include "net/quic/quic_context.h"
#include "net/quic/quic_event_logger.h"
#include "net/quic/quic_transport_error.h"
#include "net/quic/web_transport_client.h"
#include "net/socket/client_socket_factory.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/web_transport_interface.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
#include "net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h"
#include "url/gurl.h"
Expand All @@ -32,72 +34,12 @@ class URLRequestContext;

// QuicTransportClient is the top-level API for QuicTransport in //net.
class NET_EXPORT QuicTransportClient
: public quic::WebTransportVisitor,
: public WebTransportClient,
public quic::WebTransportVisitor,
public QuicChromiumPacketReader::Visitor,
public QuicChromiumPacketWriter::Delegate,
public quic::QuicSession::Visitor {
public:
//
// Diagram of allowed state transitions:
//
// NEW -> CONNECTING -> CONNECTED -> CLOSED
// | |
// | |
// +---> FAILED <---+
//
// These values are logged to UMA. Entries should not be renumbered and
// numeric values should never be reused. Please keep in sync with
// "QuicTransportClientState" in src/tools/metrics/histograms/enums.xml.
enum State {
// The client object has been created but Connect() has not been called.
NEW,
// Connection establishment is in progress. No application data can be sent
// or received at this point.
CONNECTING,
// The connection has been established and application data can be sent and
// received.
CONNECTED,
// The connection has been closed gracefully by either endpoint.
CLOSED,
// The connection has been closed abruptly.
FAILED,

// Total number of possible states.
NUM_STATES,
};

class NET_EXPORT Visitor {
public:
virtual ~Visitor();

// State change notifiers.
virtual void OnConnected() = 0; // CONNECTING -> CONNECTED
virtual void OnConnectionFailed() = 0; // CONNECTING -> FAILED
virtual void OnClosed() = 0; // CONNECTED -> CLOSED
virtual void OnError() = 0; // CONNECTED -> FAILED

virtual void OnIncomingBidirectionalStreamAvailable() = 0;
virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
virtual void OnDatagramReceived(base::StringPiece datagram) = 0;
virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
virtual void OnDatagramProcessed(
base::Optional<quic::MessageStatus> status) = 0;
};

struct NET_EXPORT Parameters {
Parameters();
~Parameters();
Parameters(const Parameters&);
Parameters(Parameters&&);

// A vector of fingerprints for expected server certificates, as described
// in
// https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints
// When empty, Web PKI is used.
std::vector<quic::CertificateFingerprint> server_certificate_fingerprints;
};

// QUIC protocol versions that are used in the origin trial.
static quic::ParsedQuicVersionVector
QuicVersionsForWebTransportOriginTrial() {
Expand All @@ -109,20 +51,21 @@ class NET_EXPORT QuicTransportClient
// |visitor| and |context| must outlive this object.
QuicTransportClient(const GURL& url,
const url::Origin& origin,
Visitor* visitor,
WebTransportClientVisitor* visitor,
const NetworkIsolationKey& isolation_key,
URLRequestContext* context,
const Parameters& parameters);
const WebTransportParameters& parameters);
~QuicTransportClient() override;

State state() const { return state_; }
const QuicTransportError& error() const { return error_; }
WebTransportState state() const { return state_; }
const QuicTransportError& error() const override;

// Connect() is an asynchronous operation. Once the operation is finished,
// OnConnected() or OnConnectionFailed() is called on the Visitor.
void Connect();
void Connect() override;

quic::QuicTransportClientSession* session();
quic::WebTransportSession* session() override;
quic::QuicTransportClientSession* quic_session();

// QuicTransportClientSession::ClientVisitor methods.
void OnSessionReady() override;
Expand Down Expand Up @@ -209,13 +152,13 @@ class NET_EXPORT QuicTransportClient
// Verifies that the connection has succeeded.
int DoConfirmConnection();

void TransitionToState(State next_state);
void TransitionToState(WebTransportState next_state);

const GURL url_;
const url::Origin origin_;
const NetworkIsolationKey isolation_key_;
URLRequestContext* const context_; // Unowned.
Visitor* const visitor_; // Unowned.
WebTransportClientVisitor* const visitor_; // Unowned.

ClientSocketFactory* const client_socket_factory_;
QuicContext* const quic_context_;
Expand All @@ -227,7 +170,7 @@ class NET_EXPORT QuicTransportClient
std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
quic::QuicCryptoClientConfig crypto_config_;

State state_ = NEW;
WebTransportState state_ = NEW;
ConnectState next_connect_state_ = CONNECT_STATE_NONE;
QuicTransportError error_;
bool retried_with_new_version_ = false;
Expand Down
40 changes: 19 additions & 21 deletions net/quic/quic_transport_end_to_end_test.cc
Expand Up @@ -33,7 +33,7 @@ namespace {
using ::quic::test::MemSliceFromString;
using ::testing::_;

class MockVisitor : public QuicTransportClient::Visitor {
class MockVisitor : public WebTransportClientVisitor {
public:
MOCK_METHOD0(OnConnected, void());
MOCK_METHOD0(OnConnectionFailed, void());
Expand Down Expand Up @@ -174,40 +174,39 @@ TEST_F(QuicTransportEndToEndTest, Connect) {
StartServer();
client_ = std::make_unique<QuicTransportClient>(
GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
QuicTransportClient::Parameters());
WebTransportParameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
ASSERT_TRUE(client_->session() != nullptr);
EXPECT_TRUE(client_->session()->IsSessionReady());
ASSERT_TRUE(client_->quic_session() != nullptr);
EXPECT_TRUE(client_->quic_session()->IsSessionReady());
}

TEST_F(QuicTransportEndToEndTest, SendDatagram) {
StartServer();
client_ = std::make_unique<QuicTransportClient>(
GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
QuicTransportClient::Parameters());
WebTransportParameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
ASSERT_TRUE(client_->session() != nullptr);
EXPECT_TRUE(client_->session()->IsSessionReady());
ASSERT_TRUE(client_->quic_session() != nullptr);
EXPECT_TRUE(client_->quic_session()->IsSessionReady());

EXPECT_CALL(visitor_, OnDatagramProcessed(_)).Times(1);
client_->session()->datagram_queue()->SendOrQueueDatagram(
MemSliceFromString("test"));
client_->session()->SendOrQueueDatagram(MemSliceFromString("test"));
}

TEST_F(QuicTransportEndToEndTest, EchoUnidirectionalStream) {
StartServer();
client_ = std::make_unique<QuicTransportClient>(
GetURL("/echo"), origin_, &visitor_, isolation_key_, context_.get(),
QuicTransportClient::Parameters());
WebTransportParameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();

quic::QuicTransportClientSession* session = client_->session();
quic::QuicTransportClientSession* session = client_->quic_session();
ASSERT_TRUE(session != nullptr);
ASSERT_TRUE(session->CanOpenNextOutgoingUnidirectionalStream());
quic::QuicTransportStream* stream_out =
Expand Down Expand Up @@ -240,7 +239,7 @@ TEST_F(QuicTransportEndToEndTest, CertificateFingerprint) {
helper_->clock().set_wall_now(
quic::QuicWallTime::FromUNIXSeconds(1591389300));

QuicTransportClient::Parameters parameters;
WebTransportParameters parameters;
parameters.server_certificate_fingerprints.push_back(
quic::CertificateFingerprint{
.algorithm = quic::CertificateFingerprint::kSha256,
Expand All @@ -252,13 +251,13 @@ TEST_F(QuicTransportEndToEndTest, CertificateFingerprint) {
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
ASSERT_NE(client_->session(), nullptr);
EXPECT_TRUE(client_->session()->IsSessionReady());
ASSERT_NE(client_->quic_session(), nullptr);
EXPECT_TRUE(client_->quic_session()->IsSessionReady());
}

TEST_F(QuicTransportEndToEndTest, CertificateFingerprintValidityTooLong) {
StartServer();
QuicTransportClient::Parameters parameters;
WebTransportParameters parameters;
// The default QUIC test certificate is valid for ten years, which exceeds
// the two-week limit.
parameters.server_certificate_fingerprints.push_back(
Expand All @@ -280,7 +279,7 @@ TEST_F(QuicTransportEndToEndTest, CertificateFingerprintValidityTooLong) {
TEST_F(QuicTransportEndToEndTest, CertificateFingerprintMismatch) {
StartServer();

QuicTransportClient::Parameters parameters;
WebTransportParameters parameters;
parameters.server_certificate_fingerprints.push_back(
quic::CertificateFingerprint{
.algorithm = quic::CertificateFingerprint::kSha256,
Expand Down Expand Up @@ -310,12 +309,12 @@ TEST_F(QuicTransportEndToEndTest, OldVersion) {
StartServer();
client_ = std::make_unique<QuicTransportClient>(
GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
QuicTransportClient::Parameters());
WebTransportParameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
ASSERT_TRUE(client_->session() != nullptr);
EXPECT_TRUE(client_->session()->IsSessionReady());
ASSERT_TRUE(client_->quic_session() != nullptr);
EXPECT_TRUE(client_->quic_session()->IsSessionReady());

std::vector<NetLogEntry> events = net_log_.GetEntriesWithType(
NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATED);
Expand All @@ -327,8 +326,7 @@ TEST_F(QuicTransportEndToEndTest, OldVersion) {

// Ensure the observer is set correctly after the version negotiation process.
EXPECT_CALL(visitor_, OnDatagramProcessed(_)).Times(1);
client_->session()->datagram_queue()->SendOrQueueDatagram(
MemSliceFromString("test"));
client_->session()->SendOrQueueDatagram(MemSliceFromString("test"));
}

} // namespace
Expand Down
1 change: 1 addition & 0 deletions net/quic/quic_transport_error.h
Expand Up @@ -15,6 +15,7 @@

namespace net {

// TODO(crbug.com/1193409): rename this class to WebTransportError.
struct NET_EXPORT QuicTransportError {
QuicTransportError() = default;
QuicTransportError(int net_error,
Expand Down

0 comments on commit ac81b02

Please sign in to comment.