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