summaryrefslogtreecommitdiffstats
path: root/net/tools/hresolv/hresolv.cc
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-31 20:30:28 +0100
committerKristian Monsen <kristianm@google.com>2011-06-14 20:31:41 -0700
commit72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch)
tree382278a54ce7a744d62fa510a9a80688cc12434b /net/tools/hresolv/hresolv.cc
parentc4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff)
downloadexternal_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.zip
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.gz
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.bz2
Merge Chromium.org at r11.0.672.0: Initial merge by git.
Change-Id: I8b4aaf611a2a405fe3fe10e8a94ea7658645c192
Diffstat (limited to 'net/tools/hresolv/hresolv.cc')
-rw-r--r--net/tools/hresolv/hresolv.cc460
1 files changed, 0 insertions, 460 deletions
diff --git a/net/tools/hresolv/hresolv.cc b/net/tools/hresolv/hresolv.cc
deleted file mode 100644
index 24d73a8..0000000
--- a/net/tools/hresolv/hresolv.cc
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright (c) 2010 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.
-
-// hrseolv is a command line utility which runs the HostResolver in the
-// Chromium network stack.
-//
-// The user specifies the hosts to lookup and when to look them up.
-// The hosts must be specified in order.
-// The hosts can be contained in a file or on the command line. If no
-// time is specified, the resolv is assumed to be the same time as the
-// previous host - which is an offset of 0 for the very first host.
-//
-// The user can also control whether the lookups happen asynchronously
-// or synchronously by specifying --async on the command line.
-//
-// Future ideas:
-// Specify whether the lookup is speculative.
-// Interleave synchronous and asynchronous lookups.
-// Specify the address family.
-
-#include <stdio.h>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/string_number_conversions.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/threading/thread.h"
-#include "base/time.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/base/host_resolver_impl.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/sys_addrinfo.h"
-
-struct FlagName {
- int flag;
- const char* name;
-};
-
-static const FlagName kAddrinfoFlagNames[] = {
- {AI_PASSIVE, "AI_PASSIVE"},
- {AI_CANONNAME, "AI_CANONNAME"},
- {AI_NUMERICHOST, "AI_NUMERICHOST"},
- {AI_V4MAPPED, "AI_V4MAPPED"},
- {AI_ALL, "AI_ALL"},
- {AI_ADDRCONFIG, "AI_ADDRCONFIG"},
-#if !defined(OS_MACOSX)
- {AI_NUMERICSERV, "AI_NUMERICSERV"},
-#endif
-};
-
-std::string FormatAddrinfoFlags(int ai_flags) {
- std::string flag_names;
- for (unsigned int i = 0; i < arraysize(kAddrinfoFlagNames); ++i) {
- const FlagName& flag_name = kAddrinfoFlagNames[i];
- if (ai_flags & flag_name.flag) {
- ai_flags &= ~flag_name.flag;
- if (!flag_names.empty()) {
- flag_names += "|";
- }
- flag_names += flag_name.name;
- }
- }
- if (ai_flags) {
- if (!flag_names.empty()) {
- flag_names += "|";
- }
- base::StringAppendF(&flag_names, "0x%x", ai_flags);
- }
- return flag_names;
-}
-
-const char* GetNameOfFlag(const FlagName* flag_names,
- unsigned int num_flag_names,
- int flag) {
- for (unsigned int i = 0; i < num_flag_names; ++i) {
- const FlagName& flag_name = flag_names[i];
- if (flag_name.flag == flag) {
- return flag_name.name;
- }
- }
- return "UNKNOWN";
-}
-
-static const FlagName kFamilyFlagNames[] = {
- {AF_UNSPEC, "AF_UNSPEC"},
- {AF_INET, "AF_INET"},
- {AF_INET6, "AF_INET6"},
-};
-
-const char* FormatAddrinfoFamily(int ai_family) {
- return GetNameOfFlag(kFamilyFlagNames,
- arraysize(kFamilyFlagNames),
- ai_family);
-}
-
-static const FlagName kSocktypeFlagNames[] = {
- {SOCK_STREAM, "SOCK_STREAM"},
- {SOCK_DGRAM, "SOCK_DGRAM"},
- {SOCK_RAW, "SOCK_RAW"},
-};
-
-const char* FormatAddrinfoSocktype(int ai_socktype) {
- return GetNameOfFlag(kSocktypeFlagNames,
- arraysize(kSocktypeFlagNames),
- ai_socktype);
-}
-
-static const FlagName kProtocolFlagNames[] = {
- {IPPROTO_TCP, "IPPROTO_TCP"},
- {IPPROTO_UDP, "IPPROTO_UDP"},
-};
-
-const char* FormatAddrinfoProtocol(int ai_protocol) {
- return GetNameOfFlag(kProtocolFlagNames,
- arraysize(kProtocolFlagNames),
- ai_protocol);
-}
-
-std::string FormatAddrinfoDetails(const struct addrinfo& ai,
- const char* indent) {
- std::string ai_flags = FormatAddrinfoFlags(ai.ai_flags);
- const char* ai_family = FormatAddrinfoFamily(ai.ai_family);
- const char* ai_socktype = FormatAddrinfoSocktype(ai.ai_socktype);
- const char* ai_protocol = FormatAddrinfoProtocol(ai.ai_protocol);
- std::string ai_addr = net::NetAddressToString(&ai);
- std::string ai_canonname;
- if (ai.ai_canonname) {
- ai_canonname = base::StringPrintf("%s ai_canonname: %s\n",
- indent,
- ai.ai_canonname);
- }
- return base::StringPrintf("%saddrinfo {\n"
- "%s ai_flags: %s\n"
- "%s ai_family: %s\n"
- "%s ai_socktype: %s\n"
- "%s ai_protocol: %s\n"
- "%s ai_addrlen: %d\n"
- "%s ai_addr: %s\n"
- "%s"
- "%s}\n",
- indent,
- indent, ai_flags.c_str(),
- indent, ai_family,
- indent, ai_socktype,
- indent, ai_protocol,
- indent, ai.ai_addrlen,
- indent, ai_addr.c_str(),
- ai_canonname.c_str(),
- indent);
-}
-
-std::string FormatAddressList(const net::AddressList& address_list,
- const std::string& host) {
- std::string ret_string;
- base::StringAppendF(&ret_string, "AddressList {\n");
- base::StringAppendF(&ret_string, " Host: %s\n", host.c_str());
- for (const struct addrinfo* it = address_list.head();
- it != NULL;
- it = it->ai_next) {
- base::StringAppendF(&ret_string, "%s",
- FormatAddrinfoDetails(*it, " ").c_str());
- }
- base::StringAppendF(&ret_string, "}\n");
- return ret_string;
-}
-
-class ResolverInvoker;
-
-// DelayedResolve contains state for a DNS resolution to be performed later.
-class DelayedResolve : public base::RefCounted<DelayedResolve> {
- public:
- DelayedResolve(const std::string& host, bool is_async,
- net::HostResolver* resolver,
- ResolverInvoker* invoker)
- : host_(host),
- address_list_(),
- is_async_(is_async),
- resolver_(resolver),
- invoker_(invoker),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- io_callback_(this, &DelayedResolve::OnResolveComplete)) {
- }
-
- void Start() {
- net::CompletionCallback* callback = (is_async_) ? &io_callback_ : NULL;
- net::HostResolver::RequestInfo request_info(net::HostPortPair(host_, 80));
- int rv = resolver_->Resolve(request_info,
- &address_list_,
- callback,
- NULL,
- net::BoundNetLog());
- if (rv != net::ERR_IO_PENDING) {
- OnResolveComplete(rv);
- }
- }
-
- private:
-
- // Without this, VC++ complains about the private destructor below.
- friend class base::RefCounted<DelayedResolve>;
-
- // The destructor is called by Release.
- ~DelayedResolve() {}
-
- void OnResolveComplete(int result);
-
- std::string host_;
- net::AddressList address_list_;
- bool is_async_;
- net::HostResolver* const resolver_;
- ResolverInvoker* invoker_;
- net::CompletionCallbackImpl<DelayedResolve> io_callback_;
-};
-
-
-struct HostAndTime {
- // The host to resolve, i.e. www.google.com
- std::string host;
- // Time since the start of this program to actually kick off the resolution.
- int delta_in_milliseconds;
-};
-
-// Invokes a sequence of host resolutions at specified times.
-class ResolverInvoker {
- public:
- explicit ResolverInvoker(net::HostResolver* resolver)
- : message_loop_(MessageLoop::TYPE_DEFAULT),
- resolver_(resolver),
- remaining_requests_(0) {
- }
-
- ~ResolverInvoker() {
- }
-
- // Resolves all specified hosts in the order provided. hosts_and_times is
- // assumed to be ordered by the delta_in_milliseconds field. There is no
- // guarantee that the resolutions will complete in the order specified when
- // async is true. There is no guarantee that the DNS queries will be issued
- // at exactly the time specified by delta_in_milliseconds, but they are
- // guaranteed to be issued at a time >= delta_in_milliseconds.
- //
- // When async is true, HostResolver::Resolve will issue the DNS lookups
- // asynchronously - this can be used to have multiple requests in flight at
- // the same time.
- //
- // ResolveAll will block until all resolutions are complete.
- void ResolveAll(const std::vector<HostAndTime>& hosts_and_times,
- bool async) {
- // Schedule all tasks on our message loop, and then run.
- int num_requests = hosts_and_times.size();
- remaining_requests_ = num_requests;
- for (int i = 0; i < num_requests; ++i) {
- const HostAndTime& host_and_time = hosts_and_times[i];
- const std::string& host = host_and_time.host;
- DelayedResolve* resolve_request = new DelayedResolve(host,
- async, resolver_, this);
- resolve_request->AddRef();
- message_loop_.PostDelayedTask(
- FROM_HERE,
- NewRunnableMethod(resolve_request, &DelayedResolve::Start),
- host_and_time.delta_in_milliseconds);
- }
- message_loop_.Run();
- }
-
- private:
- friend class DelayedResolve;
-
- void OnResolved(int err, net::AddressList* address_list,
- const std::string& host) {
- if (err == net::OK) {
- printf("%s", FormatAddressList(*address_list, host).c_str());
- } else {
- printf("Error resolving %s\n", host.c_str());
- }
- DCHECK(remaining_requests_ > 0);
- --remaining_requests_;
- if (remaining_requests_ == 0) {
- message_loop_.Quit();
- }
- }
-
- MessageLoop message_loop_;
- net::HostResolver* const resolver_;
- int remaining_requests_;
-};
-
-void DelayedResolve::OnResolveComplete(int result) {
- invoker_->OnResolved(result, &address_list_, host_);
- this->Release();
-}
-
-struct CommandLineOptions {
- CommandLineOptions()
- : verbose(false),
- async(false),
- cache_size(100),
- cache_ttl(50),
- input_path() {
- }
-
- bool verbose;
- bool async;
- int cache_size;
- int cache_ttl;
- FilePath input_path;
-};
-
-const char* kAsync = "async";
-const char* kCacheSize = "cache-size";
-const char* kCacheTtl = "cache-ttl";
-const char* kInputPath = "input-path";
-
-// Parses the command line values. Returns false if there is a problem,
-// options otherwise.
-bool ParseCommandLine(CommandLine* command_line, CommandLineOptions* options) {
- options->async = command_line->HasSwitch(kAsync);
- if (command_line->HasSwitch(kCacheSize)) {
- std::string cache_size = command_line->GetSwitchValueASCII(kCacheSize);
- bool valid_size = base::StringToInt(cache_size, &options->cache_size);
- if (valid_size) {
- valid_size = options->cache_size >= 0;
- }
- if (!valid_size) {
- printf("Invalid --cachesize value: %s\n", cache_size.c_str());
- return false;
- }
- }
-
- if (command_line->HasSwitch(kCacheTtl)) {
- std::string cache_ttl = command_line->GetSwitchValueASCII(kCacheTtl);
- bool valid_ttl = base::StringToInt(cache_ttl, &options->cache_ttl);
- if (valid_ttl) {
- valid_ttl = options->cache_ttl >= 0;
- }
- if (!valid_ttl) {
- printf("Invalid --cachettl value: %s\n", cache_ttl.c_str());
- return false;
- }
- }
-
- if (command_line->HasSwitch(kInputPath)) {
- options->input_path = command_line->GetSwitchValuePath(kInputPath);
- }
-
- return true;
-}
-
-bool ReadHostsAndTimesFromLooseValues(
- const std::vector<CommandLine::StringType>& args,
- std::vector<HostAndTime>* hosts_and_times) {
- for (std::vector<CommandLine::StringType>::const_iterator it =
- args.begin();
- it != args.end();
- ++it) {
- // TODO(cbentzel): Read time offset.
-#if defined(OS_WIN)
- HostAndTime host_and_time = {WideToASCII(*it), 0};
-#else
- HostAndTime host_and_time = {*it, 0};
-#endif
- hosts_and_times->push_back(host_and_time);
- }
- return true;
-}
-
-bool ReadHostsAndTimesFromFile(const FilePath& path,
- std::vector<HostAndTime>* hosts_and_times) {
- // TODO(cbentzel): There are smarter and safer ways to do this.
- std::string file_contents;
- if (!file_util::ReadFileToString(path, &file_contents)) {
- return false;
- }
- std::vector<std::string> lines;
- // TODO(cbentzel): This should probably handle CRLF-style separators as well.
- // Maybe it's worth adding functionality like this to base tools.
- base::SplitString(file_contents, '\n', &lines);
- std::vector<std::string>::const_iterator line_end = lines.end();
- int previous_timestamp = 0;
- for (std::vector<std::string>::const_iterator it = lines.begin();
- it != line_end;
- ++it) {
- std::vector<std::string> tokens;
- base::SplitStringAlongWhitespace(*it, &tokens);
- switch (tokens.size()) {
- case 0:
- // Unexpected, but keep going.
- break;
- case 1: {
- HostAndTime host_and_time = {tokens[0], previous_timestamp};
- hosts_and_times->push_back(host_and_time);
- break;
- }
- case 2: {
- int timestamp;
- if (!base::StringToInt(tokens[1], &timestamp)) {
- // Unexpected value - keep going.
- }
- if (timestamp < previous_timestamp) {
- // Unexpected value - ignore.
- }
- previous_timestamp = timestamp;
- HostAndTime host_and_time = {tokens[0], timestamp};
- hosts_and_times->push_back(host_and_time);
- break;
- }
- default:
- DCHECK(false);
- break;
- }
- }
- return true;
-}
-
-int main(int argc, char** argv) {
- base::AtExitManager at_exit_manager;
- CommandLine::Init(argc, argv);
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- CommandLineOptions options;
- if (!ParseCommandLine(command_line, &options)) {
- exit(1);
- }
-
- // Get the hosts and times - either from a file or command line options.
- // TODO(cbentzel): Add stdin support to POSIX versions - not sure if
- // there's an equivalent in Windows.
- // TODO(cbentzel): If really large, may not want to spool the whole
- // file into memory.
- std::vector<HostAndTime> hosts_and_times;
- if (options.input_path.empty()) {
- if (!ReadHostsAndTimesFromLooseValues(command_line->args(),
- &hosts_and_times)) {
- exit(1);
- }
- } else {
- if (!ReadHostsAndTimesFromFile(options.input_path, &hosts_and_times)) {
- exit(1);
- }
- }
-
- net::HostCache* cache = new net::HostCache(
- options.cache_size,
- base::TimeDelta::FromMilliseconds(options.cache_ttl),
- base::TimeDelta::FromSeconds(0));
-
- net::HostResolverImpl host_resolver(NULL, cache, 100u, NULL);
- ResolverInvoker invoker(&host_resolver);
- invoker.ResolveAll(hosts_and_times, options.async);
-
- CommandLine::Reset();
- return 0;
-}