blob: 24cbaa6a75d818c196f8541f25a7c0f841ca5bef [file] [log] [blame]
dschinazi1c99fcf2019-12-13 11:54:22 -08001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
6#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
7#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
9
10namespace quic {
11
12MasqueEpollClient::MasqueEpollClient(
13 QuicSocketAddress server_address,
14 const QuicServerId& server_id,
15 QuicEpollServer* epoll_server,
16 std::unique_ptr<ProofVerifier> proof_verifier,
17 const std::string& authority)
18 : QuicClient(server_address,
19 server_id,
20 MasqueSupportedVersions(),
21 epoll_server,
22 std::move(proof_verifier)),
dschinazi1c99fcf2019-12-13 11:54:22 -080023 authority_(authority) {}
24
25std::unique_ptr<QuicSession> MasqueEpollClient::CreateQuicClientSession(
26 const ParsedQuicVersionVector& supported_versions,
27 QuicConnection* connection) {
28 QUIC_DLOG(INFO) << "Creating MASQUE session for "
29 << connection->connection_id();
30 return std::make_unique<MasqueClientSession>(
31 *config(), supported_versions, connection, server_id(), crypto_config(),
32 push_promise_index(), this);
33}
34
35MasqueClientSession* MasqueEpollClient::masque_client_session() {
36 return static_cast<MasqueClientSession*>(QuicClient::session());
37}
38
39QuicConnectionId MasqueEpollClient::connection_id() {
40 return masque_client_session()->connection_id();
41}
42
43// static
44std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
45 const std::string& host,
46 int port,
47 QuicEpollServer* epoll_server,
48 std::unique_ptr<ProofVerifier> proof_verifier) {
49 // Build the masque_client, and try to connect.
50 QuicSocketAddress addr =
51 tools::LookupAddress(host, quiche::QuicheStrCat(port));
52 if (!addr.IsInitialized()) {
53 QUIC_LOG(ERROR) << "Unable to resolve address: " << host;
54 return nullptr;
55 }
56 QuicServerId server_id(host, port);
57 // Use QuicWrapUnique(new MasqueEpollClient(...)) instead of
58 // std::make_unique<MasqueEpollClient>(...) because the constructor for
59 // MasqueEpollClient is private and therefore not accessible from make_unique.
60 auto masque_client = QuicWrapUnique(new MasqueEpollClient(
61 addr, server_id, epoll_server, std::move(proof_verifier),
62 quiche::QuicheStrCat(host, ":", port)));
63
64 if (masque_client == nullptr) {
65 QUIC_LOG(ERROR) << "Failed to create masque_client";
66 return nullptr;
67 }
68
69 masque_client->set_initial_max_packet_length(kDefaultMaxPacketSize);
70 masque_client->set_drop_response_body(false);
71 if (!masque_client->Initialize()) {
72 QUIC_LOG(ERROR) << "Failed to initialize masque_client";
73 return nullptr;
74 }
75 if (!masque_client->Connect()) {
76 QuicErrorCode error = masque_client->session()->error();
77 QUIC_LOG(ERROR) << "Failed to connect to " << host << ":" << port
78 << ". Error: " << QuicErrorCodeToString(error);
79 return nullptr;
80 }
81
82 std::string body = "foo";
83
84 // Construct a GET or POST request for supplied URL.
85 spdy::SpdyHeaderBlock header_block;
86 header_block[":method"] = "POST";
87 header_block[":scheme"] = "https";
88 header_block[":authority"] = masque_client->authority_;
89 header_block[":path"] = "/.well-known/masque/init";
90
91 // Make sure to store the response, for later output.
92 masque_client->set_store_response(true);
93
94 // Send the MASQUE init command.
95 masque_client->SendRequestAndWaitForResponse(header_block, body,
96 /*fin=*/true);
97
98 if (!masque_client->connected()) {
99 QUIC_LOG(ERROR) << "MASQUE init request caused connection failure. Error: "
100 << QuicErrorCodeToString(masque_client->session()->error());
101 return nullptr;
102 }
103
104 const int response_code = masque_client->latest_response_code();
105 if (response_code != 200) {
106 QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code "
107 << response_code;
108 return nullptr;
109 }
110 return masque_client;
111}
112
113void MasqueEpollClient::UnregisterClientConnectionId(
114 QuicConnectionId client_connection_id) {
115 std::string body(client_connection_id.data(), client_connection_id.length());
116
117 // Construct a GET or POST request for supplied URL.
118 spdy::SpdyHeaderBlock header_block;
119 header_block[":method"] = "POST";
120 header_block[":scheme"] = "https";
121 header_block[":authority"] = authority_;
122 header_block[":path"] = "/.well-known/masque/unregister";
123
124 // Make sure to store the response, for later output.
125 set_store_response(true);
126
127 // Send the MASQUE unregister command.
128 SendRequest(header_block, body, /*fin=*/true);
129}
130
131} // namespace quic