blob: 9ddc291ceb0b13bd7b8b5b8a8d9b5a1181f105d0 [file] [log] [blame] [edit]
// Copyright (c) 2012 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/tools/quic_default_client.h"
#include <memory>
#include <utility>
#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
#include "quiche/quic/core/crypto/proof_verifier.h"
#include "quiche/quic/core/crypto/quic_crypto_client_config.h"
#include "quiche/quic/core/http/quic_connection_migration_manager.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_connection.h"
#include "quiche/quic/core/quic_default_connection_helper.h"
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/core/quic_path_context_factory.h"
#include "quiche/quic/core/quic_path_validator.h"
#include "quiche/quic/core/quic_server_id.h"
#include "quiche/quic/core/quic_session.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/quic_client_base.h"
#include "quiche/quic/tools/quic_client_default_network_helper.h"
#include "quiche/quic/tools/quic_simple_client_session.h"
#include "quiche/quic/tools/quic_spdy_client_base.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
namespace quic {
// A path context which owns the writer.
class QUIC_EXPORT_PRIVATE PathValidationContextForMigrationManager
: public QuicClientPathValidationContext {
public:
PathValidationContextForMigrationManager(
std::unique_ptr<QuicForceBlockablePacketWriter> writer,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address, QuicNetworkHandle network)
: QuicClientPathValidationContext(self_address, peer_address, network),
alternative_writer_(std::move(writer)) {}
QuicForceBlockablePacketWriter* ForceBlockableWriterToUse() override {
return alternative_writer_.get();
}
bool ShouldConnectionOwnWriter() const override { return false; }
QuicPacketWriter* ReleaseWriter() { return alternative_writer_.release(); }
private:
std::unique_ptr<QuicForceBlockablePacketWriter> alternative_writer_;
};
class QuicDefaultPathContextFactory : public QuicPathContextFactory {
public:
QuicDefaultPathContextFactory(
QuicDefaultClient::QuicDefaultMigrationHelper& migration_helper,
QuicClientBase::NetworkHelper* network_helper)
: migration_helper_(migration_helper), network_helper_(network_helper) {}
void CreatePathValidationContext(
QuicNetworkHandle network, QuicSocketAddress peer_address,
std::unique_ptr<CreationResultDelegate> result_delegate) override {
QuicIpAddress self_address =
migration_helper_.GetAddressForNetwork(network);
if (network_helper_ == nullptr || !network_helper_->CreateUDPSocketAndBind(
peer_address, self_address, 0)) {
result_delegate->OnCreationFailed(network,
"Failed to create UDP socket.");
QUICHE_LOG(ERROR) << "Failed to create UDP socket.";
return;
}
QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter();
if (writer == nullptr) {
result_delegate->OnCreationFailed(network,
"Failed to create QuicPacketWriter.");
QUICHE_LOG(ERROR) << "Failed to create QuicPacketWriter.";
return;
}
auto force_blockable_writer =
std::make_unique<QuicForceBlockablePacketWriter>();
force_blockable_writer->set_writer(writer);
return result_delegate->OnCreationSucceeded(
std::make_unique<PathValidationContextForMigrationManager>(
std::move(force_blockable_writer),
network_helper_->GetLatestClientAddress(), peer_address, network));
}
private:
QuicDefaultClient::QuicDefaultMigrationHelper& migration_helper_;
QuicClientBase::NetworkHelper* network_helper_;
};
std::unique_ptr<QuicPathContextFactory>
QuicDefaultClient::QuicDefaultMigrationHelper::CreateQuicPathContextFactory() {
return std::make_unique<QuicDefaultPathContextFactory>(
*this, client_.network_helper());
}
void QuicDefaultClient::QuicDefaultMigrationHelper::OnMigrationToPathDone(
std::unique_ptr<QuicClientPathValidationContext> context, bool success) {
if (success) {
auto migration_context =
absl::WrapUnique(static_cast<PathValidationContextForMigrationManager*>(
context.release()));
client_.set_writer(migration_context->ReleaseWriter());
} else {
QUICHE_LOG(ERROR) << "Failed to migrate to path.";
}
}
QuicIpAddress
QuicDefaultClient::QuicDefaultMigrationHelper::GetAddressForNetwork(
QuicNetworkHandle network) const {
QUICHE_BUG_IF(network_handle_not_supported, network != kInvalidNetworkHandle)
<< "network handle is not supported on this";
return client_.session()->connection()->self_address().host();
}
QuicNetworkHandle
QuicDefaultClient::QuicDefaultMigrationHelper::FindAlternateNetwork(
QuicNetworkHandle /*network*/) {
QUICHE_BUG(alternative_network_not_supported)
<< "Alternative network interface is not supported on this client.";
return kInvalidNetworkHandle;
}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier)
: QuicDefaultClient(
server_address, server_id, supported_versions, QuicConfig(),
event_loop,
std::make_unique<QuicClientDefaultNetworkHelper>(event_loop, this),
std::move(proof_verifier), nullptr) {}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier,
std::unique_ptr<SessionCache> session_cache)
: QuicDefaultClient(
server_address, server_id, supported_versions, QuicConfig(),
event_loop,
std::make_unique<QuicClientDefaultNetworkHelper>(event_loop, this),
std::move(proof_verifier), std::move(session_cache)) {}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions, const QuicConfig& config,
QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier,
std::unique_ptr<SessionCache> session_cache)
: QuicDefaultClient(
server_address, server_id, supported_versions, config, event_loop,
std::make_unique<QuicClientDefaultNetworkHelper>(event_loop, this),
std::move(proof_verifier), std::move(session_cache)) {}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
QuicEventLoop* event_loop,
std::unique_ptr<QuicClientDefaultNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicDefaultClient(server_address, server_id, supported_versions,
QuicConfig(), event_loop, std::move(network_helper),
std::move(proof_verifier), nullptr) {}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions, const QuicConfig& config,
QuicEventLoop* event_loop,
std::unique_ptr<QuicClientDefaultNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicDefaultClient(server_address, server_id, supported_versions, config,
event_loop, std::move(network_helper),
std::move(proof_verifier), nullptr) {}
QuicDefaultClient::QuicDefaultClient(
QuicSocketAddress server_address, const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions, const QuicConfig& config,
QuicEventLoop* event_loop,
std::unique_ptr<QuicClientDefaultNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier,
std::unique_ptr<SessionCache> session_cache)
: QuicSpdyClientBase(server_id, supported_versions, config,
new QuicDefaultConnectionHelper(),
event_loop->CreateAlarmFactory().release(),
std::move(network_helper), std::move(proof_verifier),
std::move(session_cache)) {
set_server_address(server_address);
}
void QuicDefaultClient::OnServerPreferredAddressAvailable(
const QuicSocketAddress& server_preferred_address) {
if (!handle_migration_in_session()) {
QuicSpdyClientBase::OnServerPreferredAddressAvailable(
server_preferred_address);
}
}
void QuicDefaultClient::OnPathDegrading() {
if (!handle_migration_in_session()) {
QuicSpdyClientBase::OnPathDegrading();
}
}
QuicDefaultClient::~QuicDefaultClient() = default;
bool QuicDefaultClient::Initialize() {
migration_helper_ = CreateQuicMigrationHelper();
return QuicSpdyClientBase::Initialize();
}
std::unique_ptr<QuicMigrationHelper>
QuicDefaultClient::CreateQuicMigrationHelper() {
return std::make_unique<QuicDefaultMigrationHelper>(*this);
}
std::unique_ptr<QuicSession> QuicDefaultClient::CreateQuicClientSession(
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection) {
if (handle_migration_in_session()) {
return std::make_unique<QuicSimpleClientSession>(
*config(), supported_versions, connection, this,
static_cast<QuicForceBlockablePacketWriter*>(connection->writer()),
migration_helper_.get(), migration_config_, network_helper(),
server_id(), crypto_config(), drop_response_body(),
enable_web_transport());
}
return std::make_unique<QuicSimpleClientSession>(
*config(), supported_versions, connection, this, network_helper(),
server_id(), crypto_config(), drop_response_body(),
enable_web_transport());
}
QuicClientDefaultNetworkHelper* QuicDefaultClient::default_network_helper() {
return static_cast<QuicClientDefaultNetworkHelper*>(network_helper());
}
const QuicClientDefaultNetworkHelper*
QuicDefaultClient::default_network_helper() const {
return static_cast<const QuicClientDefaultNetworkHelper*>(network_helper());
}
} // namespace quic