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, and sends requests to the provided URLS. 7 // 8 // Example usage: 9 // quic_client --address=127.0.0.1 --port=6122 --hostname=www.google.com 10 // http://www.google.com/index.html http://www.google.com/favicon.ico 11 12 #include <iostream> 13 14 #include "base/at_exit.h" 15 #include "base/command_line.h" 16 #include "base/logging.h" 17 #include "base/strings/string_number_conversions.h" 18 #include "net/base/ip_endpoint.h" 19 #include "net/base/privacy_mode.h" 20 #include "net/quic/quic_protocol.h" 21 #include "net/quic/quic_server_id.h" 22 #include "net/tools/epoll_server/epoll_server.h" 23 #include "net/tools/quic/quic_client.h" 24 25 std::string FLAGS_address = "127.0.0.1"; 26 // The IP or hostname the quic client will connect to. 27 std::string FLAGS_hostname = "localhost"; 28 // The port the quic client will connect to. 29 int32 FLAGS_port = 6121; 30 // Check the certificates using proof verifier. 31 bool FLAGS_secure = false; 32 // QUIC version to speak, e.g. 21. Default value of 0 means 'use the latest 33 // version'. 34 int32 FLAGS_quic_version = 0; 35 // Size of flow control receive window to advertize to the peer. 36 int32 FLAGS_flow_control_window_bytes = 10 * 1024 * 1024; // 10 Mb 37 38 int main(int argc, char *argv[]) { 39 base::CommandLine::Init(argc, argv); 40 base::CommandLine* line = base::CommandLine::ForCurrentProcess(); 41 const base::CommandLine::StringVector& urls = line->GetArgs(); 42 43 logging::LoggingSettings settings; 44 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 45 CHECK(logging::InitLogging(settings)); 46 47 if (line->HasSwitch("h") || line->HasSwitch("help") || urls.empty()) { 48 const char* help_str = 49 "Usage: quic_client [options] <url> ...\n" 50 "\n" 51 "At least one <url> with scheme must be provided " 52 "(e.g. http://www.google.com/)\n\n" 53 "Options:\n" 54 "-h, --help show this help message and exit\n" 55 "--port=<port> specify the port to connect to\n" 56 "--address=<address> specify the IP address to connect to\n" 57 "--host=<host> specify the SNI hostname to use\n" 58 "--secure check certificates\n" 59 "--quic-version=<quic version> specify QUIC version to speak\n" 60 "--flow-control-window-bytes=<bytes> specify size of flow control " 61 "receive window to advertize to the peer\n"; 62 std::cout << help_str; 63 exit(0); 64 } 65 if (line->HasSwitch("port")) { 66 int port; 67 if (base::StringToInt(line->GetSwitchValueASCII("port"), &port)) { 68 FLAGS_port = port; 69 } 70 } 71 if (line->HasSwitch("address")) { 72 FLAGS_address = line->GetSwitchValueASCII("address"); 73 } 74 if (line->HasSwitch("hostname")) { 75 FLAGS_hostname = line->GetSwitchValueASCII("hostname"); 76 } 77 if (line->HasSwitch("secure")) { 78 FLAGS_secure = true; 79 } 80 if (line->HasSwitch("quic-version")) { 81 int quic_version; 82 if (base::StringToInt(line->GetSwitchValueASCII("quic-version"), 83 &quic_version)) { 84 FLAGS_quic_version = quic_version; 85 } 86 } 87 if (line->HasSwitch("flow-control-window-bytes")) { 88 int flow_control_window_bytes; 89 if (base::StringToInt( 90 line->GetSwitchValueASCII("flow-control-window-bytes"), 91 &flow_control_window_bytes)) { 92 FLAGS_flow_control_window_bytes = flow_control_window_bytes; 93 } 94 } 95 VLOG(1) << "server port: " << FLAGS_port 96 << " address: " << FLAGS_address 97 << " hostname: " << FLAGS_hostname 98 << " secure: " << FLAGS_secure 99 << " quic-version: " << FLAGS_quic_version; 100 101 base::AtExitManager exit_manager; 102 103 // Determine IP address to connect to from supplied hostname. 104 net::IPAddressNumber addr; 105 CHECK(net::ParseIPLiteralToNumber(FLAGS_address, &addr)); 106 107 // Populate version vector with all versions if none specified. 108 net::QuicVersionVector versions; 109 if (FLAGS_quic_version == 0) { 110 versions = net::QuicSupportedVersions(); 111 } else { 112 versions.push_back(static_cast<net::QuicVersion>(FLAGS_quic_version)); 113 } 114 115 // Build the client, and try to connect. 116 VLOG(1) << "Conecting to " << FLAGS_hostname << ":" << FLAGS_port 117 << " with supported versions " 118 << QuicVersionVectorToString(versions); 119 net::EpollServer epoll_server; 120 net::QuicConfig config; 121 config.SetDefaults(); 122 123 // The default flow control window of 16 Kb is too small for practical 124 // purposes. Set it to the specified value, which has a large default. 125 config.SetInitialFlowControlWindowToSend( 126 FLAGS_flow_control_window_bytes); 127 config.SetInitialStreamFlowControlWindowToSend( 128 FLAGS_flow_control_window_bytes); 129 config.SetInitialSessionFlowControlWindowToSend( 130 FLAGS_flow_control_window_bytes); 131 132 net::tools::QuicClient client( 133 net::IPEndPoint(addr, FLAGS_port), 134 net::QuicServerId(FLAGS_hostname, FLAGS_port, FLAGS_secure, 135 net::PRIVACY_MODE_DISABLED), 136 versions, true, config, &epoll_server); 137 138 client.Initialize(); 139 140 if (!client.Connect()) { 141 LOG(ERROR) << "Client failed to connect to host: " 142 << FLAGS_hostname << ":" << FLAGS_port; 143 return 1; 144 } 145 146 // Send a GET request for each supplied url. 147 client.SendRequestsAndWaitForResponse(urls); 148 return 0; 149 } 150