Chromium Code Reviews| Index: net/tools/gdig/gdig.cc |
| diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ded4b008d17b00c8c35d0fc8b60620b12e9f2541 |
| --- /dev/null |
| +++ b/net/tools/gdig/gdig.cc |
| @@ -0,0 +1,183 @@ |
| +// 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/bind.h" |
| +#include "base/cancelable_callback.h" |
| +#include "base/command_line.h" |
| +#include "base/logging.h" |
| +#if defined(OS_MACOSX) |
| +#include "base/mac/scoped_nsautorelease_pool.h" |
| +#endif |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop.h" |
| +#include "base/string_number_conversions.h" |
| +#include "base/time.h" |
| +#include "net/base/host_cache.h" |
| +#include "net/base/host_resolver_impl.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/base/net_util.h" |
| +#include "net/base/address_list.h" |
| +#include "net/dns/dns_client.h" |
| +#include "net/dns/dns_config_service.h" |
| + |
| +namespace net { |
| + |
| +namespace { |
| + |
| +class GDig { |
| + public: |
| + GDig(); |
| + |
| + enum Result { |
| + RESULT_NO_RESOLVE = -4, |
| + RESULT_NO_CONFIG = -3, |
| + RESULT_WRONG_USAGE = -2, |
| + RESULT_CANNOT_INITIALIZE_LOGGING = -1, |
| + RESULT_OK = 0, |
| + }; |
| + |
| + Result Main(int argc, const char* argv[]); |
| + |
| + private: |
| + bool ParseCommandLine(int argc, const char* argv[]); |
| + |
| + void Start(); |
| + |
| + void OnDnsConfig(const DnsConfig& dns_config); |
| + void OnResolveComplete(int val); |
| + void OnTimeout(); |
| + |
| + base::TimeDelta timeout_; |
| + std::string domain_name_; |
| + |
| + Result result_; |
| + AddressList addrlist_; |
| + |
| + base::CancelableClosure timeout_closure_; |
| + scoped_ptr<DnsConfigService> dns_config_service_; |
| + scoped_ptr<HostResolver> resolver_; |
| +}; |
| + |
| +GDig::GDig() |
| + : timeout_(base::TimeDelta::FromSeconds(5)), |
| + result_(GDig::RESULT_OK) { |
| +} |
| + |
| +GDig::Result GDig::Main(int argc, const char* argv[]) { |
| + CommandLine::Init(argc, argv); |
| + if (!logging::InitLogging( |
| + NULL, |
| + logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
| + logging::DONT_LOCK_LOG_FILE, |
| + logging::DELETE_OLD_LOG_FILE, |
| + logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS)) { |
| + printf("Error: could not initialize logging. Exiting.\n"); |
| + return RESULT_CANNOT_INITIALIZE_LOGGING; |
| + } |
| + if (!ParseCommandLine(argc, argv)) { |
| + LOG(INFO) << "usage: " << argv[0] << |
| + " [--config_timeout=<seconds>] domain_name"; |
| + return RESULT_WRONG_USAGE; |
| + } |
| + |
| +#if defined(OS_MACOSX) |
| + // Without this there will be a mem leak on osx. |
| + base::mac::ScopedNSAutoreleasePool scoped_pool; |
| +#endif |
| + |
| + base::AtExitManager exit_manager; |
| + MessageLoopForIO loop; |
| + |
| + Start(); |
| + |
| + MessageLoop::current()->Run(); |
| + |
| + // Destroy it while MessageLoopForIO is alive. |
| + dns_config_service_.reset(); |
| + return result_; |
| +} |
| + |
| +void GDig::OnResolveComplete(int val) { |
| + MessageLoop::current()->Quit(); |
| + if (val != OK) { |
| + LOG(ERROR) << "Error trying to resolve hostname " << domain_name_ << |
| + ":" << ErrorToString(val); |
| + result_ = RESULT_NO_RESOLVE; |
| + } else { |
| + for (AddressList::iterator i = addrlist_.begin(); i != addrlist_.end(); ++i) |
| + printf("%s\n", i->ToStringWithoutPort().c_str()); |
| + } |
| +} |
| + |
| +void GDig::OnTimeout() { |
| + MessageLoop::current()->Quit(); |
| + LOG(ERROR) << "Timed out waiting to load the dns config"; |
| + result_ = RESULT_NO_CONFIG; |
| +} |
| + |
| +void GDig::Start() { |
| + dns_config_service_ = DnsConfigService::CreateSystemService(); |
| + dns_config_service_->Read(base::Bind(&GDig::OnDnsConfig, |
| + base::Unretained(this))); |
| + |
| + timeout_closure_.Reset(base::Bind(&GDig::OnTimeout, base::Unretained(this))); |
| + |
| + MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + timeout_closure_.callback(), |
| + timeout_); |
| +} |
| + |
| +void GDig::OnDnsConfig(const DnsConfig& dns_config) { |
| + timeout_closure_.Cancel(); |
| + DCHECK(dns_config.IsValid()); |
| + |
| + scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL)); |
| + dns_client->SetConfig(dns_config); |
| + resolver_.reset( |
| + new HostResolverImpl( |
| + HostCache::CreateDefaultCache(), |
| + PrioritizedDispatcher::Limits(NUM_PRIORITIES, 1), |
| + HostResolverImpl::ProcTaskParams(NULL, 1), |
| + scoped_ptr<DnsConfigService>(NULL), |
| + dns_client.Pass(), |
| + NULL)); |
| + |
| + HostResolver::RequestInfo info(HostPortPair(domain_name_.c_str(), 80)); |
| + |
| + CompletionCallback callback = base::Bind(&GDig::OnResolveComplete, |
| + base::Unretained(this)); |
| + int ret = resolver_->Resolve(info, &addrlist_, callback, NULL, BoundNetLog()); |
| + DCHECK(ret == ERR_IO_PENDING); |
| +} |
| + |
| +bool GDig::ParseCommandLine(int argc, const char* argv[]) { |
| + const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| + |
| + if (parsed_command_line.GetArgs().size() != 1) |
| + return false; |
| + domain_name_ = parsed_command_line.GetArgs().at(0); |
|
szym
2012/06/04 22:03:56
Use operator[] rather than .at() for consistency w
|
| + |
| + if (parsed_command_line.HasSwitch("config_timeout")) { |
| + int timeout_seconds = 0; |
| + base::StringToInt( |
| + parsed_command_line.GetSwitchValueASCII("config_timeout"), |
| + &timeout_seconds); |
| + timeout_ = base::TimeDelta::FromSeconds(timeout_seconds); |
| + } |
| + |
| + return true; |
| +} |
| + |
| +} // empty namespace |
| + |
| +} // namespace net |
| + |
| +int main(int argc, const char* argv[]) { |
| + net::GDig dig; |
| + return dig.Main(argc, argv); |
| +} |