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..b729ae39997860e63af7e817f1489332ded9365d |
| --- /dev/null |
| +++ b/net/tools/gdig/gdig.cc |
| @@ -0,0 +1,208 @@ |
| +#include <stdio.h> |
| +#include <iostream> |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/at_exit.h" |
| +#include "base/message_loop.h" |
| +#include "base/command_line.h" |
| +#include "base/string_number_conversions.h" |
| + |
| +#include "net/base/host_resolver_impl.h" |
| +#include "net/base/net_util.h" |
| +#include "net/base/sys_addrinfo.h" |
| + |
| +#include "net/base/net_errors.h" |
|
szym
2012/05/14 18:48:32
The lint tool will automatically point most style
|
| + |
| +#if defined(OS_MACOSX) |
| +#include "base/mac/scoped_nsautorelease_pool.h" |
| +#endif |
| + |
| +namespace net { |
| + |
| +namespace { |
| + |
| +void usage(const char* program_name) { |
|
szym
2012/05/14 18:48:32
Suggested function name: PrintUsage, probably shou
Daniele
2012/05/17 23:04:34
Ok, even if I don't really see the necessity to ma
|
| + std::cout << "usage: " << program_name << |
| + " [--max_retry=<retry>] [--concurrent_resolves=<n>] domain_name" << |
| + std::endl; |
| +} |
| + |
| +// This class is used to mock the DnsConfigService when an HostResolverImpl |
| +// is created and to set to it a custom dns_config. |
| +class DnsConfigServiceMock : public DnsConfigService { |
| + public: |
| + DnsConfigServiceMock(const DnsConfig& dns_config) : |
| + dns_config_(dns_config) {}; |
| + |
| + virtual ~DnsConfigServiceMock() {}; |
| + |
| + virtual void Watch(const CallbackType& callback) OVERRIDE{ |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(!callback.is_null()); |
| + set_callback(callback); |
| + callback.Run(dns_config_); |
|
szym
2012/05/14 18:48:32
This is strongly discouraged. Rule-of-thumb: avoid
Daniele
2012/05/17 23:04:34
Quite clear,
it solved other problems I had to wor
|
| + } |
| + private: |
| + const DnsConfig& dns_config_; |
| +}; |
| + |
| +class GDig { |
| + |
| + public: |
| + GDig() : |
| + resolve_name_ret_(ERR_TIMED_OUT), |
| + max_retry_(1), |
| + concurrent_resolves_(1){ } |
| + |
| + int Main(int argc, const char* argv[]) { |
| + |
| + if( !ParseCommandLine(argc, argv) ){ |
| + usage(argv[0]); |
| + return -1; |
|
szym
2012/05/14 18:48:32
I suggest defining in GDig:
enum {
RESULT_NO_RES
Daniele
2012/05/17 23:04:34
Done,
but the name you used seems ok to me, so I k
|
| + } |
| + |
| +#if defined(OS_MACOSX) |
| + //without this there will be a mem leak on osx |
| + base::mac::ScopedNSAutoreleasePool scoped_pool; |
| +#endif |
| + |
| + base::AtExitManager exit_manager; |
| + MessageLoop loop(MessageLoop::TYPE_IO); |
| + |
| + LoadDnsConfig(); |
|
szym
2012/05/14 18:48:32
I suggest:
void Start() {
resolver_ = new HostR
Daniele
2012/05/17 23:04:34
That's definitely nicer than what I did.
On 2012/
|
| + |
| + MessageLoop::current()->Run(); |
| + |
| + if (!dns_config_.IsValid()){ |
| + std::cout << "Dns configuration is not valid." << std::endl; |
| + return -2; |
| + } |
| + if (resolve_name_ret_ < 0){ |
| + std::cout << "Error trying to resolve hostname " << domain_name_ << |
| + ":" << ErrorToString(resolve_name_ret_) << std::endl; |
| + return -3; |
| + } |
| + |
| + return 0; |
| + } |
| + |
| +private: |
| + void ResolverCallback(int val){ |
|
szym
2012/05/14 18:48:32
better name: OnResolveComplete(int rv)
Daniele
2012/05/17 23:04:34
Done.
|
| + timeout_.Cancel(); |
| + resolve_name_ret_ = val; |
| + |
| + if (resolve_name_ret_ < 0 ){ |
| + MessageLoop::current()->Quit(); |
| + } |
| + |
| + const struct addrinfo* addrinf = addrlist_.head(); |
| + while (addrinf){ |
| + std::string ip = NetAddressToStringWithPort(addrinf); |
| + std::cout << ip << std::endl; |
| + addrinf = addrinf->ai_next; |
| + } |
| + |
| + MessageLoop::current()->Quit(); |
| + } |
| + |
| + void ReleaseDnsConfigService(){ |
| + config_service_.reset(); |
| + } |
| + |
| + void ResolveName(const std::string& domain_name){ |
| + |
| + scoped_ptr<DnsConfigService> |
| + dns_config_service(new DnsConfigServiceMock(dns_config_)); |
| + |
| + resolver_.reset(CreateHostResolver(concurrent_resolves_, |
| + max_retry_, |
| + HostCache::CreateDefaultCache(), |
| + dns_config_service.Pass(), |
| + NULL)); |
| + |
| + HostResolver::RequestInfo info(HostPortPair(domain_name.c_str(), 80)); |
| + |
| + CompletionCallback callback = base::Bind(&GDig::ResolverCallback, |
| + base::Unretained(this)); |
| + int ret = resolver_->Resolve(info, &addrlist_, callback, NULL, |
| + BoundNetLog()); |
| + DCHECK(ret == ERR_IO_PENDING); |
| + |
| + timeout_.Reset(MessageLoop::QuitClosure()); |
| + MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| + timeout_.callback(), |
| + base::TimeDelta::FromSeconds(5)); |
|
szym
2012/05/14 18:48:32
Ideally, make timeout value a command-line argumen
Daniele
2012/05/17 23:04:34
Done.
|
| + } |
| + |
| + void OnDnsConfigChanged(const DnsConfig& dns_config) { |
| + timeout_.Cancel(); |
| + dns_config_ = dns_config; |
| + MessageLoop::current()->PostTask(FROM_HERE, |
|
szym
2012/05/14 18:48:32
No need to post it on MessageLoop. Just let go of
Daniele
2012/05/17 23:04:34
Releasing the pointer here, caused a DCHECK to com
|
| + base::Bind(&GDig::ReleaseDnsConfigService, |
| + base::Unretained(this))); |
| + |
| + ResolveName(domain_name_); |
| + } |
| + |
| + bool ParseCommandLine(int argc, const char* argv[]){ |
| + CommandLine::Init(argc, 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); |
| + |
| + if (parsed_command_line.HasSwitch("max_retry")) { |
|
szym
2012/05/14 18:48:32
These values are not going to be used with DnsConf
Daniele
2012/05/17 23:04:34
Done.
|
| + base::StringToInt(parsed_command_line.GetSwitchValueASCII("max_retry"), |
| + &max_retry_); |
| + } |
| + |
| + if (parsed_command_line.HasSwitch("concurrent_resolves")) { |
| + base::StringToInt(parsed_command_line. |
| + GetSwitchValueASCII("concurrent_resolves"), |
| + &concurrent_resolves_); |
| + } |
| + |
| + return true; |
| + } |
| + |
| + void LoadDnsConfig(){ |
| + |
| + timeout_.Reset(MessageLoop::QuitClosure()); |
| + |
| + // Is there a better way of doing this? |
| + config_service_.reset(DnsConfigService::CreateSystemService().release()); |
|
szym
2012/05/14 18:48:32
scoped_ptr::operator= has the semantics you want:
|
| + config_service_->Watch(base::Bind(&GDig::OnDnsConfigChanged, |
| + base::Unretained(this))); |
| + |
| + MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| + timeout_.callback(), |
| + base::TimeDelta::FromSeconds(5)); |
| + |
| + } |
| + |
| + int resolve_name_ret_; |
| + AddressList addrlist_; |
| + |
| + base::CancelableClosure timeout_; |
| + DnsConfig dns_config_; |
| + |
| + int max_retry_; |
| + int concurrent_resolves_; |
| + |
| + std::string domain_name_; |
| + |
| + scoped_ptr<DnsConfigService> config_service_; |
| + scoped_ptr<HostResolver> resolver_; |
| + |
| +}; |
| + |
| +} // empty namespace |
| + |
| +} // namespace net |
| + |
| +int main(int argc, const char* argv[]) { |
| + net::GDig dig; |
| + return dig.Main(argc, argv); |
| +} |