dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 1 | // 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 | // This file is reponsible for the masque_client binary. It allows testing |
| 6 | // our MASQUE client code by connecting to a MASQUE proxy and then sending |
| 7 | // HTTP/3 requests to web servers tunnelled over that MASQUE connection. |
| 8 | // e.g.: masque_client $PROXY_HOST:$PROXY_PORT $URL1 $URL2 |
| 9 | |
| 10 | #include <memory> |
| 11 | |
vasilvv | 13aa6a0 | 2020-12-03 13:02:33 -0800 | [diff] [blame] | 12 | #include "absl/strings/str_cat.h" |
vasilvv | 3049b2b | 2020-10-08 08:18:31 -0700 | [diff] [blame] | 13 | #include "absl/strings/string_view.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 14 | #include "quic/core/quic_server_id.h" |
| 15 | #include "quic/masque/masque_client_tools.h" |
| 16 | #include "quic/masque/masque_encapsulated_epoll_client.h" |
| 17 | #include "quic/masque/masque_epoll_client.h" |
| 18 | #include "quic/masque/masque_utils.h" |
| 19 | #include "quic/platform/api/quic_default_proof_providers.h" |
| 20 | #include "quic/platform/api/quic_flags.h" |
| 21 | #include "quic/platform/api/quic_socket_address.h" |
| 22 | #include "quic/platform/api/quic_system_event_loop.h" |
| 23 | #include "quic/tools/fake_proof_verifier.h" |
| 24 | #include "quic/tools/quic_url.h" |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 25 | |
| 26 | DEFINE_QUIC_COMMAND_LINE_FLAG(bool, |
| 27 | disable_certificate_verification, |
| 28 | false, |
| 29 | "If true, don't verify the server certificate."); |
| 30 | |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 31 | DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, |
| 32 | masque_mode, |
| 33 | "", |
| 34 | "Allows setting MASQUE mode, valid values are " |
| 35 | "open and legacy. Defaults to open."); |
| 36 | |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 37 | namespace quic { |
| 38 | |
| 39 | namespace { |
| 40 | |
| 41 | int RunMasqueClient(int argc, char* argv[]) { |
| 42 | QuicSystemEventLoop event_loop("masque_client"); |
| 43 | const char* usage = "Usage: masque_client [options] <url>"; |
| 44 | |
| 45 | // The first non-flag argument is the MASQUE server. All subsequent ones are |
| 46 | // interpreted as URLs to fetch via the MASQUE server. |
| 47 | std::vector<std::string> urls = QuicParseCommandLineFlags(usage, argc, argv); |
| 48 | if (urls.empty()) { |
| 49 | QuicPrintCommandLineFlagHelp(usage); |
| 50 | return 1; |
| 51 | } |
| 52 | |
dschinazi | 388d7f9 | 2021-02-25 20:58:46 -0800 | [diff] [blame] | 53 | SetQuicReloadableFlag(quic_h3_datagram, true); |
| 54 | |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 55 | const bool disable_certificate_verification = |
| 56 | GetQuicFlag(FLAGS_disable_certificate_verification); |
| 57 | QuicEpollServer epoll_server; |
| 58 | |
| 59 | QuicUrl masque_url(urls[0], "https"); |
| 60 | if (masque_url.host().empty()) { |
vasilvv | 13aa6a0 | 2020-12-03 13:02:33 -0800 | [diff] [blame] | 61 | masque_url = QuicUrl(absl::StrCat("https://", urls[0]), "https"); |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 62 | } |
| 63 | if (masque_url.host().empty()) { |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 64 | std::cerr << "Failed to parse MASQUE server address \"" << urls[0] << "\"" |
| 65 | << std::endl; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 66 | return 1; |
| 67 | } |
| 68 | std::unique_ptr<ProofVerifier> proof_verifier; |
| 69 | if (disable_certificate_verification) { |
| 70 | proof_verifier = std::make_unique<FakeProofVerifier>(); |
| 71 | } else { |
| 72 | proof_verifier = CreateDefaultProofVerifier(masque_url.host()); |
| 73 | } |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 74 | MasqueMode masque_mode = MasqueMode::kOpen; |
| 75 | std::string mode_string = GetQuicFlag(FLAGS_masque_mode); |
| 76 | if (mode_string == "legacy") { |
| 77 | masque_mode = MasqueMode::kLegacy; |
| 78 | } else if (!mode_string.empty() && mode_string != "open") { |
| 79 | std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl; |
| 80 | return 1; |
| 81 | } |
| 82 | std::unique_ptr<MasqueEpollClient> masque_client = MasqueEpollClient::Create( |
| 83 | masque_url.host(), masque_url.port(), masque_mode, &epoll_server, |
| 84 | std::move(proof_verifier)); |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 85 | if (masque_client == nullptr) { |
| 86 | return 1; |
| 87 | } |
| 88 | |
| 89 | std::cerr << "MASQUE is connected " << masque_client->connection_id() |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 90 | << " in " << masque_mode << " mode" << std::endl; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 91 | |
| 92 | for (size_t i = 1; i < urls.size(); ++i) { |
| 93 | if (!tools::SendEncapsulatedMasqueRequest( |
| 94 | masque_client.get(), &epoll_server, urls[i], |
| 95 | disable_certificate_verification)) { |
| 96 | return 1; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | } // namespace |
| 104 | |
| 105 | } // namespace quic |
| 106 | |
| 107 | int main(int argc, char* argv[]) { |
| 108 | return quic::RunMasqueClient(argc, argv); |
| 109 | } |