blob: 7b96abe97584c687da560269661f527f04d7ca1b [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_client_tools.h"
6#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h"
7#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
9#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
10#include "net/third_party/quiche/src/quic/tools/quic_url.h"
11
12namespace quic {
13namespace tools {
14
15bool SendEncapsulatedMasqueRequest(MasqueEpollClient* masque_client,
16 QuicEpollServer* epoll_server,
17 std::string url_string,
18 bool disable_certificate_verification) {
19 const QuicUrl url(url_string, "https");
20 std::unique_ptr<ProofVerifier> proof_verifier;
21 if (disable_certificate_verification) {
22 proof_verifier = std::make_unique<FakeProofVerifier>();
23 } else {
24 proof_verifier = CreateDefaultProofVerifier(url.host());
25 }
26
27 // Build the client, and try to connect.
28 const QuicSocketAddress addr =
29 LookupAddress(url.host(), quiche::QuicheStrCat(url.port()));
30 if (!addr.IsInitialized()) {
31 QUIC_LOG(ERROR) << "Unable to resolve address: " << url.host();
32 return false;
33 }
34 const QuicServerId server_id(url.host(), url.port());
35 auto client = std::make_unique<MasqueEncapsulatedEpollClient>(
36 addr, server_id, epoll_server, std::move(proof_verifier), masque_client);
37
38 if (client == nullptr) {
39 QUIC_LOG(ERROR) << "Failed to create MasqueEncapsulatedEpollClient for "
40 << url_string;
41 return false;
42 }
43
44 client->set_initial_max_packet_length(kMasqueMaxEncapsulatedPacketSize);
45 client->set_drop_response_body(false);
46 if (!client->Initialize()) {
47 QUIC_LOG(ERROR) << "Failed to initialize MasqueEncapsulatedEpollClient for "
48 << url_string;
49 return false;
50 }
51
52 if (!client->Connect()) {
53 QuicErrorCode error = client->session()->error();
54 QUIC_LOG(ERROR) << "Failed to connect with client "
55 << client->session()->connection()->client_connection_id()
56 << " server " << client->session()->connection_id()
57 << " to " << url.HostPort()
58 << ". Error: " << QuicErrorCodeToString(error);
59 return false;
60 }
61
62 QUIC_LOG(INFO) << "Connected client "
63 << client->session()->connection()->client_connection_id()
64 << " server " << client->session()->connection_id() << " for "
65 << url_string;
66
67 // Construct the string body from flags, if provided.
68 // TODO(dschinazi) Add support for HTTP POST and non-empty bodies.
69 const std::string body = "";
70
71 // Construct a GET or POST request for supplied URL.
72 spdy::SpdyHeaderBlock header_block;
73 header_block[":method"] = "GET";
74 header_block[":scheme"] = url.scheme();
75 header_block[":authority"] = url.HostPort();
76 header_block[":path"] = url.PathParamsQuery();
77
78 // Make sure to store the response, for later output.
79 client->set_store_response(true);
80
81 // Send the MASQUE init request.
82 client->SendRequestAndWaitForResponse(header_block, body,
83 /*fin=*/true);
84
85 if (!client->connected()) {
86 QUIC_LOG(ERROR) << "Request for " << url_string
87 << " caused connection failure. Error: "
88 << QuicErrorCodeToString(client->session()->error());
89 return false;
90 }
91
92 const int response_code = client->latest_response_code();
93 if (response_code < 200 || response_code >= 300) {
94 QUIC_LOG(ERROR) << "Request for " << url_string
95 << " failed with HTTP response code " << response_code;
96 return false;
97 }
98
99 const std::string response_body = client->latest_response_body();
100 QUIC_LOG(INFO) << "Request succeeded for " << url_string << std::endl
101 << response_body;
102
103 return true;
104}
105
106} // namespace tools
107} // namespace quic