| Index: net/tools/hresolv/hresolv.cc
|
| diff --git a/net/tools/hresolv/hresolv.cc b/net/tools/hresolv/hresolv.cc
|
| deleted file mode 100644
|
| index 24d73a8f57747f8d2229b43c6def3a98921ae2b3..0000000000000000000000000000000000000000
|
| --- 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], ×tamp)) {
|
| - // 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;
|
| -}
|
|
|