|  | // Copyright 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/masque/masque_encapsulated_client.h" | 
|  |  | 
|  | #include "quiche/quic/core/quic_utils.h" | 
|  | #include "quiche/quic/masque/masque_client.h" | 
|  | #include "quiche/quic/masque/masque_client_session.h" | 
|  | #include "quiche/quic/masque/masque_encapsulated_client_session.h" | 
|  | #include "quiche/quic/masque/masque_utils.h" | 
|  | #include "quiche/quic/tools/quic_client_default_network_helper.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Custom packet writer that allows getting all of a connection's outgoing | 
|  | // packets. | 
|  | class MasquePacketWriter : public QuicPacketWriter { | 
|  | public: | 
|  | explicit MasquePacketWriter(MasqueEncapsulatedClient* client) | 
|  | : client_(client) {} | 
|  | WriteResult WritePacket(const char* buffer, size_t buf_len, | 
|  | const QuicIpAddress& /*self_address*/, | 
|  | const QuicSocketAddress& peer_address, | 
|  | PerPacketOptions* /*options*/) override { | 
|  | QUICHE_DCHECK(peer_address.IsInitialized()); | 
|  | QUIC_DVLOG(1) << "MasquePacketWriter trying to write " << buf_len | 
|  | << " bytes to " << peer_address; | 
|  | absl::string_view packet(buffer, buf_len); | 
|  | client_->masque_client()->masque_client_session()->SendPacket( | 
|  | packet, peer_address, client_->masque_encapsulated_client_session()); | 
|  | return WriteResult(WRITE_STATUS_OK, buf_len); | 
|  | } | 
|  |  | 
|  | bool IsWriteBlocked() const override { return false; } | 
|  |  | 
|  | void SetWritable() override {} | 
|  |  | 
|  | absl::optional<int> MessageTooBigErrorCode() const override { | 
|  | return absl::nullopt; | 
|  | } | 
|  |  | 
|  | QuicByteCount GetMaxPacketSize( | 
|  | const QuicSocketAddress& /*peer_address*/) const override { | 
|  | return kMasqueMaxEncapsulatedPacketSize; | 
|  | } | 
|  |  | 
|  | bool SupportsReleaseTime() const override { return false; } | 
|  |  | 
|  | bool IsBatchMode() const override { return false; } | 
|  | QuicPacketBuffer GetNextWriteLocation( | 
|  | const QuicIpAddress& /*self_address*/, | 
|  | const QuicSocketAddress& /*peer_address*/) override { | 
|  | return {nullptr, nullptr}; | 
|  | } | 
|  |  | 
|  | WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); } | 
|  |  | 
|  | private: | 
|  | MasqueEncapsulatedClient* client_;  // Unowned. | 
|  | }; | 
|  |  | 
|  | // Custom network helper that allows injecting a custom packet writer in order | 
|  | // to get all of a connection's outgoing packets. | 
|  | class MasqueClientDefaultNetworkHelper : public QuicClientDefaultNetworkHelper { | 
|  | public: | 
|  | MasqueClientDefaultNetworkHelper(QuicEventLoop* event_loop, | 
|  | MasqueEncapsulatedClient* client) | 
|  | : QuicClientDefaultNetworkHelper(event_loop, client), client_(client) {} | 
|  | QuicPacketWriter* CreateQuicPacketWriter() override { | 
|  | return new MasquePacketWriter(client_); | 
|  | } | 
|  |  | 
|  | private: | 
|  | MasqueEncapsulatedClient* client_;  // Unowned. | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | MasqueEncapsulatedClient::MasqueEncapsulatedClient( | 
|  | QuicSocketAddress server_address, const QuicServerId& server_id, | 
|  | QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier, | 
|  | MasqueClient* masque_client) | 
|  | : QuicDefaultClient( | 
|  | server_address, server_id, MasqueSupportedVersions(), | 
|  | MasqueEncapsulatedConfig(), event_loop, | 
|  | std::make_unique<MasqueClientDefaultNetworkHelper>(event_loop, this), | 
|  | std::move(proof_verifier)), | 
|  | masque_client_(masque_client) {} | 
|  |  | 
|  | MasqueEncapsulatedClient::~MasqueEncapsulatedClient() { | 
|  | masque_client_->masque_client_session()->CloseConnectUdpStream( | 
|  | masque_encapsulated_client_session()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicSession> MasqueEncapsulatedClient::CreateQuicClientSession( | 
|  | const ParsedQuicVersionVector& supported_versions, | 
|  | QuicConnection* connection) { | 
|  | QUIC_DLOG(INFO) << "Creating MASQUE encapsulated session for " | 
|  | << connection->connection_id(); | 
|  | return std::make_unique<MasqueEncapsulatedClientSession>( | 
|  | *config(), supported_versions, connection, server_id(), crypto_config(), | 
|  | push_promise_index(), masque_client_->masque_client_session()); | 
|  | } | 
|  |  | 
|  | MasqueEncapsulatedClientSession* | 
|  | MasqueEncapsulatedClient::masque_encapsulated_client_session() { | 
|  | return static_cast<MasqueEncapsulatedClientSession*>( | 
|  | QuicDefaultClient::session()); | 
|  | } | 
|  |  | 
|  | }  // namespace quic |