From f0682a98c0c22a9ef1a47e54d19244c9b4b9d208 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 8 Feb 2011 23:05:40 +0900 Subject: [PATCH] Added --async-dns-server option. This option accepts comma separated list of DNS server address used in asynchronous DNS resolver. Usually asynchronous DNS resolver reads DNS server addresses from /etc/resolv.conf. When this option is used, it uses DNS servers specified in this option instead of ones in /etc/resolv.conf. You can specify both IPv4 and IPv6 address. This option is useful when the system does not have /etc/resolv.conf and user does not have the permission to create it. --- src/AbstractCommand.cc | 3 +- src/AsyncNameResolver.cc | 9 ++++- src/AsyncNameResolver.h | 2 +- src/DHTEntryPointNameResolveCommand.cc | 2 +- src/DownloadEngine.cc | 15 ++++++++ src/DownloadEngine.h | 11 ++++++ src/MultiUrlRequestInfo.cc | 49 ++++++++++++++++++++++++++ src/OptionHandlerFactory.cc | 8 +++++ src/prefs.cc | 2 ++ src/prefs.h | 2 ++ src/usage_text.h | 11 ++++++ 11 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index de89fec9..04c36077 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -650,7 +650,8 @@ void AbstractCommand::initAsyncNameResolver(const std::string& hostname) } else { family = AF_INET; } - asyncNameResolver_.reset(new AsyncNameResolver(family)); + asyncNameResolver_.reset + (new AsyncNameResolver(family, e_->getAsyncDNSServers())); A2_LOG_INFO(fmt(MSG_RESOLVING_HOSTNAME, getCuid(), hostname.c_str())); diff --git a/src/AsyncNameResolver.cc b/src/AsyncNameResolver.cc index 7c7d6320..832d8a45 100644 --- a/src/AsyncNameResolver.cc +++ b/src/AsyncNameResolver.cc @@ -37,6 +37,7 @@ #include #include "A2STR.h" +#include "LogFactory.h" namespace aria2 { @@ -77,12 +78,18 @@ void callback(void* arg, int status, int timeouts, struct hostent* host) } } -AsyncNameResolver::AsyncNameResolver(int family): +AsyncNameResolver::AsyncNameResolver(int family, ares_addr_node* servers): status_(STATUS_READY), family_(family) { // TODO evaluate return value ares_init(&channel_); + if(servers) { + // ares_set_servers has been added since c-ares 1.7.1 + if(ares_set_servers(channel_, servers) != ARES_SUCCESS) { + A2_LOG_DEBUG("ares_set_servers failed"); + } + } } AsyncNameResolver::~AsyncNameResolver() diff --git a/src/AsyncNameResolver.h b/src/AsyncNameResolver.h index b1974a03..76610813 100644 --- a/src/AsyncNameResolver.h +++ b/src/AsyncNameResolver.h @@ -70,7 +70,7 @@ private: std::string error_; std::string hostname_; public: - AsyncNameResolver(int family); + AsyncNameResolver(int family, ares_addr_node* servers); ~AsyncNameResolver(); diff --git a/src/DHTEntryPointNameResolveCommand.cc b/src/DHTEntryPointNameResolveCommand.cc index 0fad4a83..2332673f 100644 --- a/src/DHTEntryPointNameResolveCommand.cc +++ b/src/DHTEntryPointNameResolveCommand.cc @@ -84,7 +84,7 @@ bool DHTEntryPointNameResolveCommand::execute() } else { family = AF_INET; } - resolver_.reset(new AsyncNameResolver(family)); + resolver_.reset(new AsyncNameResolver(family, e_->getAsyncDNSServers())); } #endif // ENABLE_ASYNC_DNS try { diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 00801bf6..ad024f82 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -95,6 +95,9 @@ DownloadEngine::DownloadEngine(const SharedHandle& eventPoll) #ifdef ENABLE_BITTORRENT btRegistry_(new BtRegistry()), #endif // ENABLE_BITTORRENT +#ifdef ENABLE_ASYNC_DNS + asyncDNSServers_(0), +#endif // ENABLE_ASYNC_DNS dnsCache_(new DNSCache()) { unsigned char sessionId[20]; @@ -104,6 +107,7 @@ DownloadEngine::DownloadEngine(const SharedHandle& eventPoll) DownloadEngine::~DownloadEngine() { cleanQueue(); + setAsyncDNSServers(0); } void DownloadEngine::cleanQueue() { @@ -560,4 +564,15 @@ void DownloadEngine::setCheckIntegrityMan checkIntegrityMan_ = ciman; } +void DownloadEngine::setAsyncDNSServers(ares_addr_node* asyncDNSServers) +{ + ares_addr_node* node = asyncDNSServers_; + while(node) { + ares_addr_node* next = node->next; + delete node; + node = next; + } + asyncDNSServers_ = asyncDNSServers; +} + } // namespace aria2 diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h index 675920cb..e86b7c69 100644 --- a/src/DownloadEngine.h +++ b/src/DownloadEngine.h @@ -135,6 +135,10 @@ private: CUIDCounter cuidCounter_; +#ifdef ENABLE_ASYNC_DNS + ares_addr_node* asyncDNSServers_; +#endif // ENABLE_ASYNC_DNS + SharedHandle dnsCache_; SharedHandle authConfigFactory_; @@ -326,6 +330,13 @@ public: { return sessionId_; } + + void setAsyncDNSServers(ares_addr_node* asyncDNSServers); + + ares_addr_node* getAsyncDNSServers() const + { + return asyncDNSServers_; + } }; typedef SharedHandle DownloadEngineHandle; diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index 2a6c1292..60e0c3fa 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -36,6 +36,7 @@ #include +#include #include #include "RequestGroupMan.h" @@ -90,6 +91,50 @@ void handler(int signal) { } } // namespace +namespace { + +ares_addr_node* parseAsyncDNSServers(const std::string& serversOpt) +{ + std::vector servers; + util::split(serversOpt, + std::back_inserter(servers), + A2STR::COMMA_C, + true /* doStrip */); + ares_addr_node root; + root.next = 0; + ares_addr_node* tail = &root; + for(std::vector::const_iterator i = servers.begin(), + eoi = servers.end(); i != eoi; ++i) { + struct addrinfo* res; + int s = callGetaddrinfo(&res, (*i).c_str(), 0, AF_UNSPEC, + 0, AI_NUMERICHOST, 0); + if(s != 0) { + continue; + } + WSAAPI_AUTO_DELETE resDeleter(res, freeaddrinfo); + if(res) { + ares_addr_node* node = new ares_addr_node(); + node->next = 0; + node->family = res->ai_family; + if(node->family == AF_INET) { + struct sockaddr_in* in = + reinterpret_cast(res->ai_addr); + memcpy(&node->addr.addr4, &(in->sin_addr), 4); + } else { + struct sockaddr_in6* in = + reinterpret_cast(res->ai_addr); + memcpy(&node->addr.addr6, &(in->sin6_addr), 16); + } + tail->next = node; + tail = node; + } + } + return root.next; +} + +} // namespace + + MultiUrlRequestInfo::MultiUrlRequestInfo (const std::vector >& requestGroups, const SharedHandle