diff options
author | Kristian Monsen <kristianm@google.com> | 2011-05-31 20:30:28 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-06-14 20:31:41 -0700 |
commit | 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch) | |
tree | 382278a54ce7a744d62fa510a9a80688cc12434b /net/tools/hresolv/hresolv.cc | |
parent | c4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff) | |
download | external_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.cc | 460 |
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], ×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; -} |