| // 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 |