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.
pull/1/head
Tatsuhiro Tsujikawa 2011-02-08 23:05:40 +09:00
parent cf546810e4
commit f0682a98c0
11 changed files with 110 additions and 4 deletions

View File

@ -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()));

View File

@ -37,6 +37,7 @@
#include <cstring>
#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()

View File

@ -70,7 +70,7 @@ private:
std::string error_;
std::string hostname_;
public:
AsyncNameResolver(int family);
AsyncNameResolver(int family, ares_addr_node* servers);
~AsyncNameResolver();

View File

@ -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 {

View File

@ -95,6 +95,9 @@ DownloadEngine::DownloadEngine(const SharedHandle<EventPoll>& 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>& 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

View File

@ -135,6 +135,10 @@ private:
CUIDCounter cuidCounter_;
#ifdef ENABLE_ASYNC_DNS
ares_addr_node* asyncDNSServers_;
#endif // ENABLE_ASYNC_DNS
SharedHandle<DNSCache> dnsCache_;
SharedHandle<AuthConfigFactory> authConfigFactory_;
@ -326,6 +330,13 @@ public:
{
return sessionId_;
}
void setAsyncDNSServers(ares_addr_node* asyncDNSServers);
ares_addr_node* getAsyncDNSServers() const
{
return asyncDNSServers_;
}
};
typedef SharedHandle<DownloadEngine> DownloadEngineHandle;

View File

@ -36,6 +36,7 @@
#include <signal.h>
#include <cstring>
#include <ostream>
#include "RequestGroupMan.h"
@ -90,6 +91,50 @@ void handler(int signal) {
}
} // namespace
namespace {
ares_addr_node* parseAsyncDNSServers(const std::string& serversOpt)
{
std::vector<std::string> 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<std::string>::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<struct addrinfo*> 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<struct sockaddr_in*>(res->ai_addr);
memcpy(&node->addr.addr4, &(in->sin_addr), 4);
} else {
struct sockaddr_in6* in =
reinterpret_cast<struct sockaddr_in6*>(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<SharedHandle<RequestGroup> >& requestGroups,
const SharedHandle<Option>& op,
@ -170,6 +215,10 @@ error_code::Value MultiUrlRequestInfo::execute()
}
SocketCore::setTLSContext(tlsContext);
#endif
ares_addr_node* asyncDNSServers =
parseAsyncDNSServers(option_->get(PREF_ASYNC_DNS_SERVER));
e->setAsyncDNSServers(asyncDNSServers);
if(!Timer::monotonicClock()) {
A2_LOG_WARN("Don't change system time while aria2c is running."
" Doing this may make aria2c hang for long time.");

View File

@ -205,6 +205,14 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
op->addTag(TAG_ADVANCED);
handlers.push_back(op);
}
{
SharedHandle<OptionHandler> op(new DefaultOptionHandler
(PREF_ASYNC_DNS_SERVER,
TEXT_ASYNC_DNS_SERVER,
NO_DEFAULT_VALUE));
op->addTag(TAG_ADVANCED);
handlers.push_back(op);
}
#endif // ENABLE_ASYNC_DNS
#ifdef ENABLE_DIRECT_IO
{

View File

@ -204,6 +204,8 @@ const std::string PREF_ENABLE_ASYNC_DNS6("enable-async-dns6");
const std::string PREF_MAX_DOWNLOAD_RESULT("max-download-result");
// value: 1*digit
const std::string PREF_RETRY_WAIT("retry-wait");
// value: string
const std::string PREF_ASYNC_DNS_SERVER("async-dns-server");
/**
* FTP related preferences

View File

@ -208,6 +208,8 @@ extern const std::string PREF_ENABLE_ASYNC_DNS6;
extern const std::string PREF_MAX_DOWNLOAD_RESULT;
// value: 1*digit
extern const std::string PREF_RETRY_WAIT;
// value: string
extern const std::string PREF_ASYNC_DNS_SERVER;
/**
* FTP related preferences

View File

@ -753,3 +753,14 @@
" option may result high memory consumption after\n" \
" thousands of downloads. Specifying 0 means no\n" \
" download result is kept.")
#define TEXT_ASYNC_DNS_SERVER \
_(" --async-dns-server=IPADDRESS[,...] Comma separated list of DNS server address\n" \
" used in asynchronous DNS resolver. Usually\n" \
" asynchronous DNS resolver reads DNS server\n" \
" addresses from /etc/resolv.conf. When this option\n" \
" is used, it uses DNS servers specified in this\n" \
" option instead of ones in /etc/resolv.conf. You\n" \
" can specify both IPv4 and IPv6 address. This\n" \
" option is useful when the system does not have\n" \
" /etc/resolv.conf and user does not have the\n" \
" permission to create it.")