quic_simple_client_bin.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. // A binary wrapper for QuicClient.
  5. // Connects to a host using QUIC, sends a request to the provided URL, and
  6. // displays the response.
  7. //
  8. // Some usage examples:
  9. //
  10. // Standard request/response:
  11. // quic_client http://www.google.com
  12. // quic_client http://www.google.com --quiet
  13. // quic_client https://www.google.com --port=443
  14. //
  15. // Use a specific version:
  16. // quic_client http://www.google.com --quic_version=23
  17. //
  18. // Send a POST instead of a GET:
  19. // quic_client http://www.google.com --body="this is a POST body"
  20. //
  21. // Append additional headers to the request:
  22. // quic_client http://www.google.com --host=${IP}
  23. // --headers="Header-A: 1234; Header-B: 5678"
  24. //
  25. // Connect to a host different to the URL being requested:
  26. // quic_client mail.google.com --host=www.google.com
  27. //
  28. // Connect to a specific IP:
  29. // IP=`dig www.google.com +short | head -1`
  30. // quic_client www.google.com --host=${IP}
  31. //
  32. // Try to connect to a host which does not speak QUIC:
  33. // quic_client http://www.example.com
  34. #include "base/logging.h"
  35. #include "base/ranges/algorithm.h"
  36. #include "net/base/address_family.h"
  37. #include "net/base/net_errors.h"
  38. #include "net/quic/address_utils.h"
  39. #include "net/third_party/quiche/src/quiche/common/platform/api/quiche_command_line_flags.h"
  40. #include "net/third_party/quiche/src/quiche/common/platform/api/quiche_system_event_loop.h"
  41. #include "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.h"
  42. #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
  43. #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
  44. #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
  45. #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.h"
  46. #include "net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.h"
  47. #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h"
  48. #include "net/tools/quic/quic_simple_client.h"
  49. #include "net/tools/quic/synchronous_host_resolver.h"
  50. #include "url/scheme_host_port.h"
  51. #include "url/url_constants.h"
  52. using quic::ProofVerifier;
  53. namespace {
  54. class QuicSimpleClientFactory : public quic::QuicToyClient::ClientFactory {
  55. public:
  56. std::unique_ptr<quic::QuicSpdyClientBase> CreateClient(
  57. std::string host_for_handshake,
  58. std::string host_for_lookup,
  59. int address_family_for_lookup,
  60. uint16_t port,
  61. quic::ParsedQuicVersionVector versions,
  62. const quic::QuicConfig& config,
  63. std::unique_ptr<quic::ProofVerifier> verifier,
  64. std::unique_ptr<quic::SessionCache> /*session_cache*/) override {
  65. // Determine IP address to connect to from supplied hostname.
  66. quic::QuicIpAddress ip_addr;
  67. if (!ip_addr.FromString(host_for_lookup)) {
  68. net::AddressList addresses;
  69. // TODO(https://crbug.com/1300660) Let the caller pass in the scheme
  70. // rather than guessing "https"
  71. int rv = net::SynchronousHostResolver::Resolve(
  72. url::SchemeHostPort(url::kHttpsScheme, host_for_lookup, port),
  73. &addresses);
  74. if (rv != net::OK) {
  75. LOG(ERROR) << "Unable to resolve '" << host_for_lookup
  76. << "' : " << net::ErrorToShortString(rv);
  77. return nullptr;
  78. }
  79. const auto endpoint = base::ranges::find_if(
  80. addresses,
  81. [address_family_for_lookup](net::AddressFamily family) {
  82. if (address_family_for_lookup == AF_INET)
  83. return family == net::AddressFamily::ADDRESS_FAMILY_IPV4;
  84. if (address_family_for_lookup == AF_INET6)
  85. return family == net::AddressFamily::ADDRESS_FAMILY_IPV6;
  86. return address_family_for_lookup == AF_UNSPEC;
  87. },
  88. &net::IPEndPoint::GetFamily);
  89. if (endpoint == addresses.end()) {
  90. LOG(ERROR) << "No results for '" << host_for_lookup
  91. << "' with appropriate address family";
  92. return nullptr;
  93. }
  94. // Arbitrarily select the first result with a matching address family,
  95. // ignoring any subsequent matches.
  96. ip_addr = net::ToQuicIpAddress(endpoint->address());
  97. port = endpoint->port();
  98. }
  99. quic::QuicServerId server_id(host_for_handshake, port, false);
  100. return std::make_unique<net::QuicSimpleClient>(
  101. quic::QuicSocketAddress(ip_addr, port), server_id, versions, config,
  102. std::move(verifier));
  103. }
  104. };
  105. } // namespace
  106. int main(int argc, char* argv[]) {
  107. quiche::QuicheSystemEventLoop event_loop("quic_client");
  108. const char* usage = "Usage: quic_client [options] <url>";
  109. // All non-flag arguments should be interpreted as URLs to fetch.
  110. std::vector<std::string> urls =
  111. quiche::QuicheParseCommandLineFlags(usage, argc, argv);
  112. if (urls.size() != 1) {
  113. quiche::QuichePrintCommandLineFlagHelp(usage);
  114. exit(0);
  115. }
  116. QuicSimpleClientFactory factory;
  117. quic::QuicToyClient client(&factory);
  118. return client.SendRequestsAndPrintResponses(urls);
  119. }