Index: net/tools/gdig/gdig.cc |
diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc |
deleted file mode 100644 |
index 0f8c1fe9a32869b13d0715cc3462c111690bd37e..0000000000000000000000000000000000000000 |
--- a/net/tools/gdig/gdig.cc |
+++ /dev/null |
@@ -1,517 +0,0 @@ |
-// 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. |
- |
-#include <stdio.h> |
-#include <string> |
- |
-#include "base/at_exit.h" |
-#include "base/basictypes.h" |
-#include "base/bind.h" |
-#include "base/cancelable_callback.h" |
-#include "base/command_line.h" |
-#include "base/files/file_util.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/string_split.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/time/time.h" |
-#include "net/base/address_list.h" |
-#include "net/base/ip_endpoint.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/net_log.h" |
-#include "net/base/net_util.h" |
-#include "net/dns/dns_client.h" |
-#include "net/dns/dns_config_service.h" |
-#include "net/dns/dns_protocol.h" |
-#include "net/dns/host_cache.h" |
-#include "net/dns/host_resolver_impl.h" |
-#include "net/tools/gdig/file_net_log.h" |
- |
-#if defined(OS_MACOSX) |
-#include "base/mac/scoped_nsautorelease_pool.h" |
-#endif |
- |
-namespace net { |
- |
-namespace { |
- |
-bool StringToIPEndPoint(const std::string& ip_address_and_port, |
- IPEndPoint* ip_end_point) { |
- DCHECK(ip_end_point); |
- |
- std::string ip; |
- int port; |
- if (!ParseHostAndPort(ip_address_and_port, &ip, &port)) |
- return false; |
- if (port == -1) |
- port = dns_protocol::kDefaultPort; |
- |
- net::IPAddressNumber ip_number; |
- if (!net::ParseIPLiteralToNumber(ip, &ip_number)) |
- return false; |
- |
- *ip_end_point = net::IPEndPoint(ip_number, static_cast<uint16>(port)); |
- return true; |
-} |
- |
-// Convert DnsConfig to human readable text omitting the hosts member. |
-std::string DnsConfigToString(const DnsConfig& dns_config) { |
- std::string output; |
- output.append("search "); |
- for (size_t i = 0; i < dns_config.search.size(); ++i) { |
- output.append(dns_config.search[i] + " "); |
- } |
- output.append("\n"); |
- |
- for (size_t i = 0; i < dns_config.nameservers.size(); ++i) { |
- output.append("nameserver "); |
- output.append(dns_config.nameservers[i].ToString()).append("\n"); |
- } |
- |
- base::StringAppendF(&output, "options ndots:%d\n", dns_config.ndots); |
- base::StringAppendF(&output, "options timeout:%d\n", |
- static_cast<int>(dns_config.timeout.InMilliseconds())); |
- base::StringAppendF(&output, "options attempts:%d\n", dns_config.attempts); |
- if (dns_config.rotate) |
- output.append("options rotate\n"); |
- if (dns_config.edns0) |
- output.append("options edns0\n"); |
- return output; |
-} |
- |
-// Convert DnsConfig hosts member to a human readable text. |
-std::string DnsHostsToString(const DnsHosts& dns_hosts) { |
- std::string output; |
- for (DnsHosts::const_iterator i = dns_hosts.begin(); |
- i != dns_hosts.end(); |
- ++i) { |
- const DnsHostsKey& key = i->first; |
- std::string host_name = key.first; |
- output.append(IPEndPoint(i->second, 0).ToStringWithoutPort()); |
- output.append(" ").append(host_name).append("\n"); |
- } |
- return output; |
-} |
- |
-struct ReplayLogEntry { |
- base::TimeDelta start_time; |
- std::string domain_name; |
-}; |
- |
-typedef std::vector<ReplayLogEntry> ReplayLog; |
- |
-// Loads and parses a replay log file and fills |replay_log| with a structured |
-// representation. Returns whether the operation was successful. If not, the |
-// contents of |replay_log| are undefined. |
-// |
-// The replay log is a text file where each line contains |
-// |
-// timestamp_in_milliseconds domain_name |
-// |
-// The timestamp_in_milliseconds needs to be an integral delta from start of |
-// resolution and is in milliseconds. domain_name is the name to be resolved. |
-// |
-// The file should be sorted by timestamp in ascending time. |
-bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) { |
- std::string original_replay_log_contents; |
- if (!base::ReadFileToString(file_path, &original_replay_log_contents)) { |
- fprintf(stderr, "Unable to open replay file %s\n", |
- file_path.MaybeAsASCII().c_str()); |
- return false; |
- } |
- |
- // Strip out \r characters for Windows files. This isn't as efficient as a |
- // smarter line splitter, but this particular use does not need to target |
- // efficiency. |
- std::string replay_log_contents; |
- base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents); |
- |
- std::vector<std::string> lines; |
- base::SplitString(replay_log_contents, '\n', &lines); |
- base::TimeDelta previous_delta; |
- bool bad_parse = false; |
- for (unsigned i = 0; i < lines.size(); ++i) { |
- if (lines[i].empty()) |
- continue; |
- std::vector<std::string> time_and_name; |
- base::SplitString(lines[i], ' ', &time_and_name); |
- if (time_and_name.size() != 2) { |
- fprintf( |
- stderr, |
- "[%s %u] replay log should have format 'timestamp domain_name\\n'\n", |
- file_path.MaybeAsASCII().c_str(), |
- i + 1); |
- bad_parse = true; |
- continue; |
- } |
- |
- int64 delta_in_milliseconds; |
- if (!base::StringToInt64(time_and_name[0], &delta_in_milliseconds)) { |
- fprintf( |
- stderr, |
- "[%s %u] replay log should have format 'timestamp domain_name\\n'\n", |
- file_path.MaybeAsASCII().c_str(), |
- i + 1); |
- bad_parse = true; |
- continue; |
- } |
- |
- base::TimeDelta delta = |
- base::TimeDelta::FromMilliseconds(delta_in_milliseconds); |
- if (delta < previous_delta) { |
- fprintf( |
- stderr, |
- "[%s %u] replay log should be sorted by time\n", |
- file_path.MaybeAsASCII().c_str(), |
- i + 1); |
- bad_parse = true; |
- continue; |
- } |
- |
- previous_delta = delta; |
- ReplayLogEntry entry; |
- entry.start_time = delta; |
- entry.domain_name = time_and_name[1]; |
- replay_log->push_back(entry); |
- } |
- return !bad_parse; |
-} |
- |
-class GDig { |
- public: |
- GDig(); |
- ~GDig(); |
- |
- enum Result { |
- RESULT_NO_RESOLVE = -3, |
- RESULT_NO_CONFIG = -2, |
- RESULT_WRONG_USAGE = -1, |
- RESULT_OK = 0, |
- RESULT_PENDING = 1, |
- }; |
- |
- Result Main(int argc, const char* argv[]); |
- |
- private: |
- bool ParseCommandLine(int argc, const char* argv[]); |
- |
- void Start(); |
- void Finish(Result); |
- |
- void OnDnsConfig(const DnsConfig& dns_config_const); |
- void OnResolveComplete(unsigned index, AddressList* address_list, |
- base::TimeDelta time_since_start, int val); |
- void OnTimeout(); |
- void ReplayNextEntry(); |
- |
- base::TimeDelta config_timeout_; |
- bool print_config_; |
- bool print_hosts_; |
- net::IPEndPoint nameserver_; |
- base::TimeDelta timeout_; |
- int parallellism_; |
- ReplayLog replay_log_; |
- unsigned replay_log_index_; |
- base::Time start_time_; |
- int active_resolves_; |
- Result result_; |
- |
- base::CancelableClosure timeout_closure_; |
- scoped_ptr<DnsConfigService> dns_config_service_; |
- scoped_ptr<FileNetLogObserver> log_observer_; |
- scoped_ptr<NetLog> log_; |
- scoped_ptr<HostResolver> resolver_; |
- |
-#if defined(OS_MACOSX) |
- // Without this there will be a mem leak on osx. |
- base::mac::ScopedNSAutoreleasePool scoped_pool_; |
-#endif |
- |
- // Need AtExitManager to support AsWeakPtr (in NetLog). |
- base::AtExitManager exit_manager_; |
-}; |
- |
-GDig::GDig() |
- : config_timeout_(base::TimeDelta::FromSeconds(5)), |
- print_config_(false), |
- print_hosts_(false), |
- parallellism_(6), |
- replay_log_index_(0u), |
- active_resolves_(0) { |
-} |
- |
-GDig::~GDig() { |
- if (log_) |
- log_->RemoveThreadSafeObserver(log_observer_.get()); |
-} |
- |
-GDig::Result GDig::Main(int argc, const char* argv[]) { |
- if (!ParseCommandLine(argc, argv)) { |
- fprintf(stderr, |
- "usage: %s [--net_log[=<basic|no_bytes|all>]]" |
- " [--print_config] [--print_hosts]" |
- " [--nameserver=<ip_address[:port]>]" |
- " [--timeout=<milliseconds>]" |
- " [--config_timeout=<seconds>]" |
- " [--j=<parallel resolves>]" |
- " [--replay_file=<path>]" |
- " [domain_name]\n", |
- argv[0]); |
- return RESULT_WRONG_USAGE; |
- } |
- |
- base::MessageLoopForIO loop; |
- |
- result_ = RESULT_PENDING; |
- Start(); |
- if (result_ == RESULT_PENDING) |
- base::MessageLoop::current()->Run(); |
- |
- // Destroy it while MessageLoopForIO is alive. |
- dns_config_service_.reset(); |
- return result_; |
-} |
- |
-bool GDig::ParseCommandLine(int argc, const char* argv[]) { |
- base::CommandLine::Init(argc, argv); |
- const base::CommandLine& parsed_command_line = |
- *base::CommandLine::ForCurrentProcess(); |
- |
- if (parsed_command_line.HasSwitch("config_timeout")) { |
- int timeout_seconds = 0; |
- bool parsed = base::StringToInt( |
- parsed_command_line.GetSwitchValueASCII("config_timeout"), |
- &timeout_seconds); |
- if (parsed && timeout_seconds > 0) { |
- config_timeout_ = base::TimeDelta::FromSeconds(timeout_seconds); |
- } else { |
- fprintf(stderr, "Invalid config_timeout parameter\n"); |
- return false; |
- } |
- } |
- |
- if (parsed_command_line.HasSwitch("net_log")) { |
- std::string log_param = parsed_command_line.GetSwitchValueASCII("net_log"); |
- NetLog::LogLevel level = NetLog::LOG_ALL_BUT_BYTES; |
- |
- if (log_param.length() > 0) { |
- std::map<std::string, NetLog::LogLevel> log_levels; |
- log_levels["all"] = NetLog::LOG_ALL; |
- log_levels["no_bytes"] = NetLog::LOG_ALL_BUT_BYTES; |
- |
- if (log_levels.find(log_param) != log_levels.end()) { |
- level = log_levels[log_param]; |
- } else { |
- fprintf(stderr, "Invalid net_log parameter\n"); |
- return false; |
- } |
- } |
- log_.reset(new NetLog); |
- log_observer_.reset(new FileNetLogObserver(stderr)); |
- log_->AddThreadSafeObserver(log_observer_.get(), level); |
- } |
- |
- print_config_ = parsed_command_line.HasSwitch("print_config"); |
- print_hosts_ = parsed_command_line.HasSwitch("print_hosts"); |
- |
- if (parsed_command_line.HasSwitch("nameserver")) { |
- std::string nameserver = |
- parsed_command_line.GetSwitchValueASCII("nameserver"); |
- if (!StringToIPEndPoint(nameserver, &nameserver_)) { |
- fprintf(stderr, |
- "Cannot parse the namerserver string into an IPEndPoint\n"); |
- return false; |
- } |
- } |
- |
- if (parsed_command_line.HasSwitch("timeout")) { |
- int timeout_millis = 0; |
- bool parsed = base::StringToInt( |
- parsed_command_line.GetSwitchValueASCII("timeout"), |
- &timeout_millis); |
- if (parsed && timeout_millis > 0) { |
- timeout_ = base::TimeDelta::FromMilliseconds(timeout_millis); |
- } else { |
- fprintf(stderr, "Invalid timeout parameter\n"); |
- return false; |
- } |
- } |
- |
- if (parsed_command_line.HasSwitch("replay_file")) { |
- base::FilePath replay_path = |
- parsed_command_line.GetSwitchValuePath("replay_file"); |
- if (!LoadReplayLog(replay_path, &replay_log_)) |
- return false; |
- } |
- |
- if (parsed_command_line.HasSwitch("j")) { |
- int parallellism = 0; |
- bool parsed = base::StringToInt( |
- parsed_command_line.GetSwitchValueASCII("j"), |
- ¶llellism); |
- if (parsed && parallellism > 0) { |
- parallellism_ = parallellism; |
- } else { |
- fprintf(stderr, "Invalid parallellism parameter\n"); |
- } |
- } |
- |
- if (parsed_command_line.GetArgs().size() == 1) { |
- ReplayLogEntry entry; |
- entry.start_time = base::TimeDelta(); |
-#if defined(OS_WIN) |
- entry.domain_name = base::UTF16ToASCII(parsed_command_line.GetArgs()[0]); |
-#else |
- entry.domain_name = parsed_command_line.GetArgs()[0]; |
-#endif |
- replay_log_.push_back(entry); |
- } else if (parsed_command_line.GetArgs().size() != 0) { |
- return false; |
- } |
- return print_config_ || print_hosts_ || !replay_log_.empty(); |
-} |
- |
-void GDig::Start() { |
- if (nameserver_.address().size() > 0) { |
- DnsConfig dns_config; |
- dns_config.attempts = 1; |
- dns_config.nameservers.push_back(nameserver_); |
- OnDnsConfig(dns_config); |
- } else { |
- dns_config_service_ = DnsConfigService::CreateSystemService(); |
- dns_config_service_->ReadConfig(base::Bind(&GDig::OnDnsConfig, |
- base::Unretained(this))); |
- timeout_closure_.Reset(base::Bind(&GDig::OnTimeout, |
- base::Unretained(this))); |
- base::MessageLoop::current()->PostDelayedTask( |
- FROM_HERE, timeout_closure_.callback(), config_timeout_); |
- } |
-} |
- |
-void GDig::Finish(Result result) { |
- DCHECK_NE(RESULT_PENDING, result); |
- result_ = result; |
- if (base::MessageLoop::current()) |
- base::MessageLoop::current()->Quit(); |
-} |
- |
-void GDig::OnDnsConfig(const DnsConfig& dns_config_const) { |
- timeout_closure_.Cancel(); |
- DCHECK(dns_config_const.IsValid()); |
- DnsConfig dns_config = dns_config_const; |
- |
- if (timeout_.InMilliseconds() > 0) |
- dns_config.timeout = timeout_; |
- if (print_config_) { |
- printf("# Dns Configuration\n" |
- "%s", DnsConfigToString(dns_config).c_str()); |
- } |
- if (print_hosts_) { |
- printf("# Host Database\n" |
- "%s", DnsHostsToString(dns_config.hosts).c_str()); |
- } |
- |
- if (replay_log_.empty()) { |
- Finish(RESULT_OK); |
- return; |
- } |
- |
- scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL)); |
- dns_client->SetConfig(dns_config); |
- HostResolver::Options options; |
- options.max_concurrent_resolves = parallellism_; |
- options.max_retry_attempts = 1u; |
- scoped_ptr<HostResolverImpl> resolver( |
- new HostResolverImpl(options, log_.get())); |
- resolver->SetDnsClient(dns_client.Pass()); |
- resolver_ = resolver.Pass(); |
- |
- start_time_ = base::Time::Now(); |
- |
- ReplayNextEntry(); |
-} |
- |
-void GDig::ReplayNextEntry() { |
- DCHECK_LT(replay_log_index_, replay_log_.size()); |
- |
- base::TimeDelta time_since_start = base::Time::Now() - start_time_; |
- while (replay_log_index_ < replay_log_.size()) { |
- const ReplayLogEntry& entry = replay_log_[replay_log_index_]; |
- if (time_since_start < entry.start_time) { |
- // Delay call to next time and return. |
- base::MessageLoop::current()->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&GDig::ReplayNextEntry, base::Unretained(this)), |
- entry.start_time - time_since_start); |
- return; |
- } |
- |
- HostResolver::RequestInfo info(HostPortPair(entry.domain_name.c_str(), 80)); |
- AddressList* addrlist = new AddressList(); |
- unsigned current_index = replay_log_index_; |
- CompletionCallback callback = base::Bind(&GDig::OnResolveComplete, |
- base::Unretained(this), |
- current_index, |
- base::Owned(addrlist), |
- time_since_start); |
- ++active_resolves_; |
- ++replay_log_index_; |
- int ret = resolver_->Resolve( |
- info, |
- DEFAULT_PRIORITY, |
- addrlist, |
- callback, |
- NULL, |
- BoundNetLog::Make(log_.get(), net::NetLog::SOURCE_NONE)); |
- if (ret != ERR_IO_PENDING) |
- callback.Run(ret); |
- } |
-} |
- |
-void GDig::OnResolveComplete(unsigned entry_index, |
- AddressList* address_list, |
- base::TimeDelta resolve_start_time, |
- int val) { |
- DCHECK_GT(active_resolves_, 0); |
- DCHECK(address_list); |
- DCHECK_LT(entry_index, replay_log_.size()); |
- --active_resolves_; |
- base::TimeDelta resolve_end_time = base::Time::Now() - start_time_; |
- base::TimeDelta resolve_time = resolve_end_time - resolve_start_time; |
- printf("%u %d %d %s %d ", |
- entry_index, |
- static_cast<int>(resolve_end_time.InMilliseconds()), |
- static_cast<int>(resolve_time.InMilliseconds()), |
- replay_log_[entry_index].domain_name.c_str(), val); |
- if (val != OK) { |
- std::string error_string = ErrorToString(val); |
- printf("%s", error_string.c_str()); |
- } else { |
- for (size_t i = 0; i < address_list->size(); ++i) { |
- if (i != 0) |
- printf(" "); |
- printf("%s", (*address_list)[i].ToStringWithoutPort().c_str()); |
- } |
- } |
- printf("\n"); |
- if (active_resolves_ == 0 && replay_log_index_ >= replay_log_.size()) |
- Finish(RESULT_OK); |
-} |
- |
-void GDig::OnTimeout() { |
- fprintf(stderr, "Timed out waiting to load the dns config\n"); |
- Finish(RESULT_NO_CONFIG); |
-} |
- |
-} // empty namespace |
- |
-} // namespace net |
- |
-int main(int argc, const char* argv[]) { |
- net::GDig dig; |
- return dig.Main(argc, argv); |
-} |