rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 1 | // Copyright (c) 2012 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 | // A binary wrapper for QuicClient. |
| 6 | // Connects to a host using QUIC, sends a request to the provided URL, and |
| 7 | // displays the response. |
| 8 | // |
| 9 | // Some usage examples: |
| 10 | // |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 11 | // Standard request/response: |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 12 | // quic_client http://www.google.com |
| 13 | // quic_client http://www.google.com --quiet |
| 14 | // quic_client https://www.google.com --port=443 |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 15 | // |
| 16 | // Use a specific version: |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 17 | // quic_client http://www.google.com --quic_version=23 |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 18 | // |
| 19 | // Send a POST instead of a GET: |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 20 | // quic_client http://www.google.com --body="this is a POST body" |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 21 | // |
| 22 | // Append additional headers to the request: |
| 23 | // quic_client http://www.google.com --host=${IP} |
| 24 | // --headers="Header-A: 1234; Header-B: 5678" |
| 25 | // |
| 26 | // Connect to a host different to the URL being requested: |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 27 | // quic_client mail.google.com --host=www.google.com |
| 28 | // |
| 29 | // Connect to a specific IP: |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 30 | // IP=`dig www.google.com +short | head -1` |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 31 | // quic_client www.google.com --host=${IP} |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 32 | // |
| 33 | // Try to connect to a host which does not speak QUIC: |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 34 | // quic_client http://www.example.com |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 35 | |
| 36 | #include <iostream> |
| 37 | |
| 38 | #include "base/at_exit.h" |
| 39 | #include "base/command_line.h" |
| 40 | #include "base/logging.h" |
Alexander Timin | 4f9c35c | 2018-11-01 20:15:20 | [diff] [blame] | 41 | #include "base/message_loop/message_loop.h" |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 42 | #include "base/task/thread_pool/thread_pool.h" |
rch | da78df5a | 2015-03-22 05:16:37 | [diff] [blame] | 43 | #include "net/base/net_errors.h" |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 44 | #include "net/base/privacy_mode.h" |
| 45 | #include "net/cert/cert_verifier.h" |
rch | 71bd233 | 2017-02-04 00:06:47 | [diff] [blame] | 46 | #include "net/cert/ct_log_verifier.h" |
Ryan Sleevi | 8a9c9c1 | 2018-05-09 02:36:23 | [diff] [blame] | 47 | #include "net/cert/ct_policy_enforcer.h" |
rtenneti | 052774e | 2015-11-24 21:00:12 | [diff] [blame] | 48 | #include "net/cert/multi_log_ct_verifier.h" |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 49 | #include "net/http/transport_security_state.h" |
Victor Vasiliev | 4f6fb89 | 2019-05-31 16:58:31 | [diff] [blame^] | 50 | #include "net/quic/address_utils.h" |
Ryan Hamilton | a3ee93a7 | 2018-08-01 22:03:08 | [diff] [blame] | 51 | #include "net/quic/crypto/proof_verifier_chromium.h" |
Bence Béky | 94658bf | 2018-05-11 19:22:58 | [diff] [blame] | 52 | #include "net/spdy/spdy_http_utils.h" |
Victor Vasiliev | 6bb59d2 | 2019-03-08 21:34:51 | [diff] [blame] | 53 | #include "net/third_party/quiche/src/quic/core/quic_error_codes.h" |
| 54 | #include "net/third_party/quiche/src/quic/core/quic_packets.h" |
| 55 | #include "net/third_party/quiche/src/quic/core/quic_server_id.h" |
David Schinazi | c00136a | 2019-04-16 02:54:52 | [diff] [blame] | 56 | #include "net/third_party/quiche/src/quic/core/quic_versions.h" |
Victor Vasiliev | 6bb59d2 | 2019-03-08 21:34:51 | [diff] [blame] | 57 | #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" |
| 58 | #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" |
| 59 | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 60 | #include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h" |
Victor Vasiliev | 6bb59d2 | 2019-03-08 21:34:51 | [diff] [blame] | 61 | #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 62 | #include "net/third_party/quiche/src/quic/tools/quic_toy_client.h" |
Victor Vasiliev | 27cc771 | 2019-01-24 11:50:14 | [diff] [blame] | 63 | #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" |
rch | a9d12ce1 | 2015-03-19 23:06:49 | [diff] [blame] | 64 | #include "net/tools/quic/quic_simple_client.h" |
rch | da78df5a | 2015-03-22 05:16:37 | [diff] [blame] | 65 | #include "net/tools/quic/synchronous_host_resolver.h" |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 66 | #include "url/gurl.h" |
| 67 | |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 68 | using net::CertVerifier; |
rtenneti | 052774e | 2015-11-24 21:00:12 | [diff] [blame] | 69 | using net::CTVerifier; |
| 70 | using net::MultiLogCTVerifier; |
Ryan Hamilton | 8d9ee76e | 2018-05-29 23:52:52 | [diff] [blame] | 71 | using quic::ProofVerifier; |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 72 | using net::ProofVerifierChromium; |
Ryan Hamilton | 8d9ee76e | 2018-05-29 23:52:52 | [diff] [blame] | 73 | using quic::QuicStringPiece; |
| 74 | using quic::QuicTextUtils; |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 75 | using net::TransportSecurityState; |
Ryan Hamilton | 0239aac | 2018-05-19 00:03:13 | [diff] [blame] | 76 | using spdy::SpdyHeaderBlock; |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 77 | using std::cout; |
| 78 | using std::cerr; |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 79 | using std::endl; |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 80 | |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 81 | namespace { |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 82 | |
Ryan Hamilton | 8d54e39 | 2019-05-19 17:24:40 | [diff] [blame] | 83 | class QuicSimpleClientFactory : public quic::QuicToyClient::ClientFactory { |
rch | e22c2fb | 2015-11-17 00:22:32 | [diff] [blame] | 84 | public: |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 85 | std::unique_ptr<quic::QuicSpdyClientBase> CreateClient( |
| 86 | std::string host, |
| 87 | uint16_t port, |
| 88 | quic::ParsedQuicVersionVector versions, |
| 89 | std::unique_ptr<quic::ProofVerifier> verifier) override { |
rch | da78df5a | 2015-03-22 05:16:37 | [diff] [blame] | 90 | net::AddressList addresses; |
rch | 750447f9 | 2016-01-31 02:54:53 | [diff] [blame] | 91 | int rv = net::SynchronousHostResolver::Resolve(host, &addresses); |
rch | da78df5a | 2015-03-22 05:16:37 | [diff] [blame] | 92 | if (rv != net::OK) { |
rjshade | d5ced07 | 2015-12-18 19:26:02 | [diff] [blame] | 93 | LOG(ERROR) << "Unable to resolve '" << host |
| 94 | << "' : " << net::ErrorToShortString(rv); |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 95 | return nullptr; |
rch | da78df5a | 2015-03-22 05:16:37 | [diff] [blame] | 96 | } |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 97 | // Determine IP address to connect to from supplied hostname. |
| 98 | quic::QuicIpAddress ip_addr; |
| 99 | if (!ip_addr.FromString(host)) { |
| 100 | net::AddressList addresses; |
| 101 | int rv = net::SynchronousHostResolver::Resolve(host, &addresses); |
| 102 | if (rv != net::OK) { |
| 103 | LOG(ERROR) << "Unable to resolve '" << host |
| 104 | << "' : " << net::ErrorToShortString(rv); |
| 105 | return nullptr; |
| 106 | } |
Victor Vasiliev | 4f6fb89 | 2019-05-31 16:58:31 | [diff] [blame^] | 107 | ip_addr = net::ToQuicIpAddress(addresses[0].address()); |
Takashi Sakamoto | 9014ca56d | 2019-05-17 09:02:52 | [diff] [blame] | 108 | } |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 109 | |
| 110 | quic::QuicServerId server_id(host, port, false); |
| 111 | return quic::QuicMakeUnique<net::QuicSimpleClient>( |
| 112 | quic::QuicSocketAddress(ip_addr, port), server_id, versions, |
| 113 | std::move(verifier)); |
Takashi Sakamoto | 9014ca56d | 2019-05-17 09:02:52 | [diff] [blame] | 114 | } |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 115 | }; |
| 116 | |
| 117 | } // namespace |
| 118 | |
| 119 | int main(int argc, char* argv[]) { |
| 120 | QuicSystemEventLoop event_loop("quic_client"); |
| 121 | const char* usage = "Usage: quic_client [options] <url>"; |
| 122 | |
| 123 | // All non-flag arguments should be interpreted as URLs to fetch. |
| 124 | std::vector<std::string> urls = |
| 125 | quic::QuicParseCommandLineFlags(usage, argc, argv); |
| 126 | if (urls.size() != 1) { |
| 127 | quic::QuicPrintCommandLineFlagHelp(usage); |
| 128 | exit(0); |
Takashi Sakamoto | 9014ca56d | 2019-05-17 09:02:52 | [diff] [blame] | 129 | } |
| 130 | |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 131 | QuicSimpleClientFactory factory; |
Ryan Hamilton | 8d54e39 | 2019-05-19 17:24:40 | [diff] [blame] | 132 | quic::QuicToyClient client(&factory); |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 133 | return client.SendRequestsAndPrintResponses(urls); |
rch | fdfdc8ed | 2015-03-18 00:35:20 | [diff] [blame] | 134 | } |