summaryrefslogtreecommitdiffstats
path: root/net/tools/quic/quic_client_bin.cc
blob: 6fcde96fa6be57c79221bf914dc413853fab46b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A binary wrapper for QuicClient.
// Connects to a host using QUIC, and sends requests to the provided URLS.
//
// Example usage:
//  quic_client --address=127.0.0.1 --port=6122 --hostname=www.google.com
//      http://www.google.com/index.html http://www.google.com/favicon.ico

#include <iostream>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/ip_endpoint.h"
#include "net/base/privacy_mode.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_server_id.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client.h"

std::string FLAGS_address = "127.0.0.1";
// The IP or hostname the quic client will connect to.
std::string FLAGS_hostname = "localhost";
// The port the quic client will connect to.
int32 FLAGS_port = 6121;
// Check the certificates using proof verifier.
bool FLAGS_secure = false;
// QUIC version to speak, e.g. 21. Default value of 0 means 'use the latest
// version'.
int32 FLAGS_quic_version = 0;
// Size of flow control receive window to advertize to the peer.
int32 FLAGS_flow_control_window_bytes = 10 * 1024 * 1024;  // 10 Mb

int main(int argc, char *argv[]) {
  base::CommandLine::Init(argc, argv);
  base::CommandLine* line = base::CommandLine::ForCurrentProcess();
  const base::CommandLine::StringVector& urls = line->GetArgs();

  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  CHECK(logging::InitLogging(settings));

  if (line->HasSwitch("h") || line->HasSwitch("help") || urls.empty()) {
    const char* help_str =
        "Usage: quic_client [options] <url> ...\n"
        "\n"
        "At least one <url> with scheme must be provided "
        "(e.g. http://www.google.com/)\n\n"
        "Options:\n"
        "-h, --help                  show this help message and exit\n"
        "--port=<port>               specify the port to connect to\n"
        "--address=<address>         specify the IP address to connect to\n"
        "--host=<host>               specify the SNI hostname to use\n"
        "--secure                    check certificates\n"
        "--quic-version=<quic version> specify QUIC version to speak\n"
        "--flow-control-window-bytes=<bytes> specify size of flow control "
        "receive window to advertize to the peer\n";
    std::cout << help_str;
    exit(0);
  }
  if (line->HasSwitch("port")) {
    int port;
    if (base::StringToInt(line->GetSwitchValueASCII("port"), &port)) {
      FLAGS_port = port;
    }
  }
  if (line->HasSwitch("address")) {
    FLAGS_address = line->GetSwitchValueASCII("address");
  }
  if (line->HasSwitch("hostname")) {
    FLAGS_hostname = line->GetSwitchValueASCII("hostname");
  }
  if (line->HasSwitch("secure")) {
    FLAGS_secure = true;
  }
  if (line->HasSwitch("quic-version")) {
    int quic_version;
    if (base::StringToInt(line->GetSwitchValueASCII("quic-version"),
                          &quic_version)) {
      FLAGS_quic_version = quic_version;
    }
  }
  if (line->HasSwitch("flow-control-window-bytes")) {
    int flow_control_window_bytes;
    if (base::StringToInt(
            line->GetSwitchValueASCII("flow-control-window-bytes"),
            &flow_control_window_bytes)) {
      FLAGS_flow_control_window_bytes = flow_control_window_bytes;
    }
  }
  VLOG(1) << "server port: " << FLAGS_port
          << " address: " << FLAGS_address
          << " hostname: " << FLAGS_hostname
          << " secure: " << FLAGS_secure
          << " quic-version: " << FLAGS_quic_version;

  base::AtExitManager exit_manager;

  // Determine IP address to connect to from supplied hostname.
  net::IPAddressNumber addr;
  CHECK(net::ParseIPLiteralToNumber(FLAGS_address, &addr));

  // Populate version vector with all versions if none specified.
  net::QuicVersionVector versions;
  if (FLAGS_quic_version == 0) {
    versions = net::QuicSupportedVersions();
  } else {
    versions.push_back(static_cast<net::QuicVersion>(FLAGS_quic_version));
  }

  // Build the client, and try to connect.
  VLOG(1) << "Conecting to " << FLAGS_hostname << ":" << FLAGS_port
          << " with supported versions "
          << QuicVersionVectorToString(versions);
  net::EpollServer epoll_server;

  net::tools::QuicClient client(
      net::IPEndPoint(addr, FLAGS_port),
      net::QuicServerId(FLAGS_hostname, FLAGS_port, FLAGS_secure,
                        net::PRIVACY_MODE_DISABLED),
      versions, true, &epoll_server);

  client.Initialize();

  if (!client.Connect()) {
    LOG(ERROR) << "Client failed to connect to host: "
               << FLAGS_hostname << ":" << FLAGS_port;
    return 1;
  }

  // Send a GET request for each supplied url.
  client.SendRequestsAndWaitForResponse(urls);
  return 0;
}