|  | // 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 "quic/masque/masque_encapsulated_epoll_client.h" | 
|  | #include "quic/core/quic_utils.h" | 
|  | #include "quic/masque/masque_client_session.h" | 
|  | #include "quic/masque/masque_encapsulated_client_session.h" | 
|  | #include "quic/masque/masque_epoll_client.h" | 
|  | #include "quic/masque/masque_utils.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Custom packet writer that allows getting all of a connection's outgoing | 
|  | // packets. | 
|  | class MasquePacketWriter : public QuicPacketWriter { | 
|  | public: | 
|  | explicit MasquePacketWriter(MasqueEncapsulatedEpollClient* 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( | 
|  | client_->session()->connection()->client_connection_id(), | 
|  | client_->session()->connection()->connection_id(), packet, peer_address, | 
|  | client_->masque_encapsulated_client_session()); | 
|  | return WriteResult(WRITE_STATUS_OK, buf_len); | 
|  | } | 
|  |  | 
|  | bool IsWriteBlocked() const override { return false; } | 
|  |  | 
|  | void SetWritable() override {} | 
|  |  | 
|  | 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: | 
|  | MasqueEncapsulatedEpollClient* client_;  // Unowned. | 
|  | }; | 
|  |  | 
|  | // Custom network helper that allows injecting a custom packet writer in order | 
|  | // to get all of a connection's outgoing packets. | 
|  | class MasqueClientEpollNetworkHelper : public QuicClientEpollNetworkHelper { | 
|  | public: | 
|  | MasqueClientEpollNetworkHelper(QuicEpollServer* epoll_server, | 
|  | MasqueEncapsulatedEpollClient* client) | 
|  | : QuicClientEpollNetworkHelper(epoll_server, client), client_(client) {} | 
|  | QuicPacketWriter* CreateQuicPacketWriter() override { | 
|  | return new MasquePacketWriter(client_); | 
|  | } | 
|  |  | 
|  | private: | 
|  | MasqueEncapsulatedEpollClient* client_;  // Unowned. | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | MasqueEncapsulatedEpollClient::MasqueEncapsulatedEpollClient( | 
|  | QuicSocketAddress server_address, | 
|  | const QuicServerId& server_id, | 
|  | QuicEpollServer* epoll_server, | 
|  | std::unique_ptr<ProofVerifier> proof_verifier, | 
|  | MasqueEpollClient* masque_client) | 
|  | : QuicClient( | 
|  | server_address, | 
|  | server_id, | 
|  | MasqueSupportedVersions(), | 
|  | MasqueEncapsulatedConfig(), | 
|  | epoll_server, | 
|  | std::make_unique<MasqueClientEpollNetworkHelper>(epoll_server, this), | 
|  | std::move(proof_verifier)), | 
|  | masque_client_(masque_client) {} | 
|  |  | 
|  | MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() { | 
|  | masque_client_->masque_client_session()->UnregisterConnectionId( | 
|  | client_connection_id_, masque_encapsulated_client_session()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicSession> | 
|  | MasqueEncapsulatedEpollClient::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* | 
|  | MasqueEncapsulatedEpollClient::masque_encapsulated_client_session() { | 
|  | return static_cast<MasqueEncapsulatedClientSession*>(QuicClient::session()); | 
|  | } | 
|  |  | 
|  | QuicConnectionId MasqueEncapsulatedEpollClient::GetClientConnectionId() { | 
|  | if (client_connection_id_.IsEmpty()) { | 
|  | client_connection_id_ = QuicUtils::CreateRandomConnectionId(); | 
|  | masque_client_->masque_client_session()->RegisterConnectionId( | 
|  | client_connection_id_, masque_encapsulated_client_session()); | 
|  | } | 
|  | return client_connection_id_; | 
|  | } | 
|  |  | 
|  | }  // namespace quic |