diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc')
-rw-r--r-- | chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc new file mode 100644 index 00000000000..6d6470bc099 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc @@ -0,0 +1,154 @@ +// 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_epoll_client.h" + +#include <string> + +#include "absl/memory/memory.h" +#include "quiche/quic/masque/masque_client_session.h" +#include "quiche/quic/masque/masque_utils.h" +#include "quiche/quic/tools/quic_url.h" + +namespace quic { + +MasqueEpollClient::MasqueEpollClient( + QuicSocketAddress server_address, const QuicServerId& server_id, + MasqueMode masque_mode, QuicEpollServer* epoll_server, + std::unique_ptr<ProofVerifier> proof_verifier, + const std::string& uri_template) + : QuicClient(server_address, server_id, MasqueSupportedVersions(), + epoll_server, std::move(proof_verifier)), + masque_mode_(masque_mode), + uri_template_(uri_template) {} + +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>( + masque_mode_, uri_template_, *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(); +} + +std::string MasqueEpollClient::authority() const { + QuicUrl url(uri_template_); + return absl::StrCat(url.host(), ":", url.port()); +} + +// static +std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create( + const std::string& uri_template, MasqueMode masque_mode, + QuicEpollServer* epoll_server, + std::unique_ptr<ProofVerifier> proof_verifier) { + QuicUrl url(uri_template); + std::string host = url.host(); + uint16_t port = url.port(); + // Build the masque_client, and try to connect. + QuicSocketAddress addr = tools::LookupAddress(host, absl::StrCat(port)); + if (!addr.IsInitialized()) { + QUIC_LOG(ERROR) << "Unable to resolve address: " << host; + return nullptr; + } + QuicServerId server_id(host, port); + // Use absl::WrapUnique(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 = absl::WrapUnique( + new MasqueEpollClient(addr, server_id, masque_mode, epoll_server, + std::move(proof_verifier), uri_template)); + + if (masque_client == nullptr) { + QUIC_LOG(ERROR) << "Failed to create masque_client"; + return nullptr; + } + + masque_client->set_initial_max_packet_length(kMasqueMaxOuterPacketSize); + 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; + } + + if (!masque_client->WaitUntilSettingsReceived()) { + QUIC_LOG(ERROR) << "Failed to receive settings"; + return nullptr; + } + + if (masque_client->masque_mode() == MasqueMode::kLegacy) { + // Construct the legacy mode init request. + spdy::Http2HeaderBlock header_block; + header_block[":method"] = "POST"; + header_block[":scheme"] = "https"; + header_block[":authority"] = masque_client->authority(); + header_block[":path"] = "/.well-known/masque/init"; + std::string body = "foo"; + + // 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::OnSettingsReceived() { settings_received_ = true; } + +bool MasqueEpollClient::WaitUntilSettingsReceived() { + while (connected() && !settings_received_) { + network_helper()->RunEventLoop(); + } + return connected() && settings_received_; +} + +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::Http2HeaderBlock 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 |