| // 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 "net/third_party/quiche/src/quic/masque/masque_epoll_client.h" | 
 | #include "net/third_party/quiche/src/quic/masque/masque_client_session.h" | 
 | #include "net/third_party/quiche/src/quic/masque/masque_utils.h" | 
 | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | MasqueEpollClient::MasqueEpollClient( | 
 |     QuicSocketAddress server_address, | 
 |     const QuicServerId& server_id, | 
 |     QuicEpollServer* epoll_server, | 
 |     std::unique_ptr<ProofVerifier> proof_verifier, | 
 |     const std::string& authority) | 
 |     : QuicClient(server_address, | 
 |                  server_id, | 
 |                  MasqueSupportedVersions(), | 
 |                  epoll_server, | 
 |                  std::move(proof_verifier)), | 
 |       authority_(authority) {} | 
 |  | 
 | std::unique_ptr<QuicSession> MasqueEpollClient::CreateQuicClientSession( | 
 |     const ParsedQuicVersionVector& supported_versions, | 
 |     QuicConnection* connection) { | 
 |   QUIC_DLOG(INFO) << "Creating MASQUE session for " | 
 |                   << connection->connection_id(); | 
 |   return std::make_unique<MasqueClientSession>( | 
 |       *config(), supported_versions, connection, server_id(), crypto_config(), | 
 |       push_promise_index(), this); | 
 | } | 
 |  | 
 | MasqueClientSession* MasqueEpollClient::masque_client_session() { | 
 |   return static_cast<MasqueClientSession*>(QuicClient::session()); | 
 | } | 
 |  | 
 | QuicConnectionId MasqueEpollClient::connection_id() { | 
 |   return masque_client_session()->connection_id(); | 
 | } | 
 |  | 
 | // static | 
 | std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create( | 
 |     const std::string& host, | 
 |     int port, | 
 |     QuicEpollServer* epoll_server, | 
 |     std::unique_ptr<ProofVerifier> proof_verifier) { | 
 |   // Build the masque_client, and try to connect. | 
 |   QuicSocketAddress addr = | 
 |       tools::LookupAddress(host, quiche::QuicheStrCat(port)); | 
 |   if (!addr.IsInitialized()) { | 
 |     QUIC_LOG(ERROR) << "Unable to resolve address: " << host; | 
 |     return nullptr; | 
 |   } | 
 |   QuicServerId server_id(host, port); | 
 |   // Use QuicWrapUnique(new MasqueEpollClient(...)) instead of | 
 |   // std::make_unique<MasqueEpollClient>(...) because the constructor for | 
 |   // MasqueEpollClient is private and therefore not accessible from make_unique. | 
 |   auto masque_client = QuicWrapUnique(new MasqueEpollClient( | 
 |       addr, server_id, epoll_server, std::move(proof_verifier), | 
 |       quiche::QuicheStrCat(host, ":", port))); | 
 |  | 
 |   if (masque_client == nullptr) { | 
 |     QUIC_LOG(ERROR) << "Failed to create masque_client"; | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   masque_client->set_initial_max_packet_length(kDefaultMaxPacketSize); | 
 |   masque_client->set_drop_response_body(false); | 
 |   if (!masque_client->Initialize()) { | 
 |     QUIC_LOG(ERROR) << "Failed to initialize masque_client"; | 
 |     return nullptr; | 
 |   } | 
 |   if (!masque_client->Connect()) { | 
 |     QuicErrorCode error = masque_client->session()->error(); | 
 |     QUIC_LOG(ERROR) << "Failed to connect to " << host << ":" << port | 
 |                     << ". Error: " << QuicErrorCodeToString(error); | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   std::string body = "foo"; | 
 |  | 
 |   // Construct a GET or POST request for supplied URL. | 
 |   spdy::SpdyHeaderBlock header_block; | 
 |   header_block[":method"] = "POST"; | 
 |   header_block[":scheme"] = "https"; | 
 |   header_block[":authority"] = masque_client->authority_; | 
 |   header_block[":path"] = "/.well-known/masque/init"; | 
 |  | 
 |   // Make sure to store the response, for later output. | 
 |   masque_client->set_store_response(true); | 
 |  | 
 |   // Send the MASQUE init command. | 
 |   masque_client->SendRequestAndWaitForResponse(header_block, body, | 
 |                                                /*fin=*/true); | 
 |  | 
 |   if (!masque_client->connected()) { | 
 |     QUIC_LOG(ERROR) << "MASQUE init request caused connection failure. Error: " | 
 |                     << QuicErrorCodeToString(masque_client->session()->error()); | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   const int response_code = masque_client->latest_response_code(); | 
 |   if (response_code != 200) { | 
 |     QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code " | 
 |                     << response_code; | 
 |     return nullptr; | 
 |   } | 
 |   return masque_client; | 
 | } | 
 |  | 
 | void MasqueEpollClient::UnregisterClientConnectionId( | 
 |     QuicConnectionId client_connection_id) { | 
 |   std::string body(client_connection_id.data(), client_connection_id.length()); | 
 |  | 
 |   // Construct a GET or POST request for supplied URL. | 
 |   spdy::SpdyHeaderBlock header_block; | 
 |   header_block[":method"] = "POST"; | 
 |   header_block[":scheme"] = "https"; | 
 |   header_block[":authority"] = authority_; | 
 |   header_block[":path"] = "/.well-known/masque/unregister"; | 
 |  | 
 |   // Make sure to store the response, for later output. | 
 |   set_store_response(true); | 
 |  | 
 |   // Send the MASQUE unregister command. | 
 |   SendRequest(header_block, body, /*fin=*/true); | 
 | } | 
 |  | 
 | }  // namespace quic |