mirror of https://github.com/aria2/aria2
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
parent
cf546810e4
commit
f0682a98c0
|
@ -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()));
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
std::string error_;
|
||||
std::string hostname_;
|
||||
public:
|
||||
AsyncNameResolver(int family);
|
||||
AsyncNameResolver(int family, ares_addr_node* servers);
|
||||
|
||||
~AsyncNameResolver();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.")
|
||||
|
|
Loading…
Reference in New Issue