From d52bce74d3a40d75dcfa3496e67abbed9f1fcba8 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 8 May 2008 11:18:36 +0000 Subject: [PATCH] 2008-05-08 Tatsuhiro Tsujikawa Rewritten name resolver. Now async DNS can be disabled by --async-dns option. The asynchronous DNS is not capable of IPv6 yet. By disabling asynchronous DNS, aria2 is IPv6 enabled application, at least for HTTP download. * src/AbstractCommand.cc * src/AbstractCommand.h * src/AsyncNameResolver.cc * src/AsyncNameResolver.h * src/DHTEntryPointNameResolveCommand.cc * src/DHTEntryPointNameResolveCommand.h * src/DownloadEngine.cc * src/DownloadEngine.h * src/FtpInitiateConnectionCommand.cc * src/FtpInitiateConnectionCommand.h * src/HelpItemFactory.cc * src/HttpInitiateConnectionCommand.cc * src/HttpInitiateConnectionCommand.h * src/InitiateConnectionCommand.cc * src/InitiateConnectionCommand.h * src/Makefile.am * src/Makefile.in * src/NameResolver.cc * src/NameResolver.h * src/OptionHandlerFactory.cc * src/SocketCore.cc * src/SocketCore.h * src/Util.cc * src/Util.h * src/option_processing.cc * src/prefs.h * src/usage_text.h --- ChangeLog | 35 +++++++ src/AbstractCommand.cc | 99 ++++++++++-------- src/AbstractCommand.h | 32 ++++-- src/AsyncNameResolver.cc | 137 +++++++++++++++++++++++++ src/AsyncNameResolver.h | 103 +++++++++++++++++++ src/DHTEntryPointNameResolveCommand.cc | 120 ++++++++++++---------- src/DHTEntryPointNameResolveCommand.h | 16 ++- src/DownloadEngine.cc | 63 ++++++++---- src/DownloadEngine.h | 28 +++-- src/FtpInitiateConnectionCommand.cc | 79 ++++---------- src/FtpInitiateConnectionCommand.h | 16 ++- src/HelpItemFactory.cc | 7 ++ src/HttpInitiateConnectionCommand.cc | 75 ++++---------- src/HttpInitiateConnectionCommand.h | 24 ++--- src/InitiateConnectionCommand.cc | 109 ++++++++++++++++++++ src/InitiateConnectionCommand.h | 66 ++++++++++++ src/Makefile.am | 7 +- src/Makefile.in | 76 ++++++++------ src/NameResolver.cc | 103 +++++-------------- src/NameResolver.h | 104 ++----------------- src/OptionHandlerFactory.cc | 3 + src/SocketCore.cc | 21 +--- src/SocketCore.h | 3 - src/Util.cc | 14 +++ src/Util.h | 4 + src/option_processing.cc | 13 +++ src/prefs.h | 2 + src/usage_text.h | 2 + 28 files changed, 841 insertions(+), 520 deletions(-) create mode 100644 src/AsyncNameResolver.cc create mode 100644 src/AsyncNameResolver.h create mode 100644 src/InitiateConnectionCommand.cc create mode 100644 src/InitiateConnectionCommand.h diff --git a/ChangeLog b/ChangeLog index d82d5b0c..aa1e8c26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2008-05-08 Tatsuhiro Tsujikawa + + Rewritten name resolver. Now async DNS can be disabled by --async-dns + option. + The asynchronous DNS is not capable of IPv6 yet. + By disabling asynchronous DNS, aria2 is IPv6 enabled application, at + least for HTTP download. + * src/AbstractCommand.cc + * src/AbstractCommand.h + * src/AsyncNameResolver.cc + * src/AsyncNameResolver.h + * src/DHTEntryPointNameResolveCommand.cc + * src/DHTEntryPointNameResolveCommand.h + * src/DownloadEngine.cc + * src/DownloadEngine.h + * src/FtpInitiateConnectionCommand.cc + * src/FtpInitiateConnectionCommand.h + * src/HelpItemFactory.cc + * src/HttpInitiateConnectionCommand.cc + * src/HttpInitiateConnectionCommand.h + * src/InitiateConnectionCommand.cc + * src/InitiateConnectionCommand.h + * src/Makefile.am + * src/Makefile.in + * src/NameResolver.cc + * src/NameResolver.h + * src/OptionHandlerFactory.cc + * src/SocketCore.cc + * src/SocketCore.h + * src/Util.cc + * src/Util.h + * src/option_processing.cc + * src/prefs.h + * src/usage_text.h + 2008-05-07 Tatsuhiro Tsujikawa Updated man page: --quiet, --header were added. diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 40febf23..5d49870e 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -46,8 +46,9 @@ #include "DownloadFailureException.h" #include "InitiateConnectionCommandFactory.h" #include "SleepCommand.h" -#include "NameResolver.h" -#include "DNSCache.h" +#ifdef ENABLE_ASYNC_DNS +#include "AsyncNameResolver.h" +#endif // ENABLE_ASYNC_DNS #include "StreamCheckIntegrityEntry.h" #include "PieceStorage.h" #include "Socket.h" @@ -57,6 +58,8 @@ namespace aria2 { +// TODO $$$$$$$$$$$ fix two nearly identical constructor. $$$$$$$$$$$$$$ +// Modify two constructor at the same time! AbstractCommand::AbstractCommand(int32_t cuid, const SharedHandle& req, RequestGroup* requestGroup, @@ -89,6 +92,9 @@ AbstractCommand::AbstractCommand(int32_t cuid, AbstractCommand::~AbstractCommand() { disableReadCheckSocket(); disableWriteCheckSocket(); +#ifdef ENABLE_ASYNC_DNS + disableNameResolverCheck(_asyncNameResolver); +#endif // ENABLE_ASYNC_DNS _requestGroup->decreaseStreamConnection(); } @@ -257,59 +263,64 @@ void AbstractCommand::setWriteCheckSocket(const SocketHandle& socket) { } } -bool AbstractCommand::resolveHostname(const std::string& hostname, - const NameResolverHandle& resolver) { - std::string ipaddr = DNSCacheSingletonHolder::instance()->find(hostname); - if(ipaddr.empty()) { #ifdef ENABLE_ASYNC_DNS - switch(resolver->getStatus()) { - case NameResolver::STATUS_READY: - logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); - resolver->resolve(hostname); - setNameResolverCheck(resolver); - return false; - case NameResolver::STATUS_SUCCESS: - logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, - hostname.c_str(), resolver->getAddrString().c_str()); - DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); - return true; - break; - case NameResolver::STATUS_ERROR: - throw DlAbortEx(StringFormat(MSG_NAME_RESOLUTION_FAILED, cuid, - hostname.c_str(), - resolver->getError().c_str()).str()); - default: - return false; - } -#else - logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); - resolver->resolve(hostname); + +bool AbstractCommand::isAsyncNameResolverInitialized() const +{ + return !_asyncNameResolver.isNull(); +} + +void AbstractCommand::initAsyncNameResolver(const std::string& hostname) +{ + _asyncNameResolver.reset(new AsyncNameResolver()); + logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); + _asyncNameResolver->resolve(hostname); + setNameResolverCheck(_asyncNameResolver); +} + +bool AbstractCommand::asyncResolveHostname() +{ + switch(_asyncNameResolver->getStatus()) { + case AsyncNameResolver::STATUS_SUCCESS: logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, - hostname.c_str(), resolver->getAddrString().c_str()); - DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); - return true; -#endif // ENABLE_ASYNC_DNS - } else { - logger->info(MSG_DNS_CACHE_HIT, cuid, - hostname.c_str(), ipaddr.c_str()); - resolver->setAddr(ipaddr); + _asyncNameResolver->getHostname().c_str(), + _asyncNameResolver->getResolvedAddresses().front().c_str()); return true; + break; + case AsyncNameResolver::STATUS_ERROR: + throw DlAbortEx(StringFormat(MSG_NAME_RESOLUTION_FAILED, cuid, + _asyncNameResolver->getHostname().c_str(), + _asyncNameResolver->getError().c_str()).str()); + default: + return false; } } -#ifdef ENABLE_ASYNC_DNS -void AbstractCommand::setNameResolverCheck(const NameResolverHandle& resolver) { - nameResolverCheck = true; - e->addNameResolverCheck(resolver, this); +const std::deque& AbstractCommand::getResolvedAddresses() +{ + return _asyncNameResolver->getResolvedAddresses(); } -void AbstractCommand::disableNameResolverCheck(const NameResolverHandle& resolver) { - nameResolverCheck = false; - e->deleteNameResolverCheck(resolver, this); +void AbstractCommand::setNameResolverCheck +(const SharedHandle& resolver) { + if(!resolver.isNull()) { + nameResolverCheck = true; + e->addNameResolverCheck(resolver, this); + } +} + +void AbstractCommand::disableNameResolverCheck +(const SharedHandle& resolver) { + if(!resolver.isNull()) { + nameResolverCheck = false; + e->deleteNameResolverCheck(resolver, this); + } } bool AbstractCommand::nameResolveFinished() const { - return false; + return + _asyncNameResolver->getStatus() == AsyncNameResolver::STATUS_SUCCESS || + _asyncNameResolver->getStatus() == AsyncNameResolver::STATUS_ERROR; } #endif // ENABLE_ASYNC_DNS diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h index 831a0ada..45151ef6 100644 --- a/src/AbstractCommand.h +++ b/src/AbstractCommand.h @@ -46,9 +46,11 @@ class Request; class DownloadEngine; class RequestGroup; class Segment; -class NameResolver; class Exception; class SocketCore; +#ifdef ENABLE_ASYNC_DNS +class AsyncNameResolver; +#endif // ENABLE_ASYNC_DNS class AbstractCommand : public Command, public RequestGroupAware { private: @@ -60,6 +62,18 @@ protected: SharedHandle socket; std::deque > _segments; +#ifdef ENABLE_ASYNC_DNS + SharedHandle _asyncNameResolver; + + bool isAsyncNameResolverInitialized() const; + + void initAsyncNameResolver(const std::string& hostname); + + bool asyncResolveHostname(); + + const std::deque& getResolvedAddresses(); +#endif // ENABLE_ASYNC_DNS + void tryReserved(); virtual bool prepareForRetry(time_t wait); virtual void onAbort(); @@ -69,13 +83,7 @@ protected: void setWriteCheckSocket(const SharedHandle& socket); void disableReadCheckSocket(); void disableWriteCheckSocket(); - bool resolveHostname(const std::string& hostname, - const SharedHandle& nameResolver); -#ifdef ENABLE_ASYNC_DNS - void setNameResolverCheck(const SharedHandle& resolver); - void disableNameResolverCheck(const SharedHandle& resolver); - virtual bool nameResolveFinished() const; -#endif // ENABLE_ASYNC_DNS + void setTimeout(time_t timeout) { this->timeout = timeout; } void prepareForNextAction(Command* nextCommand = 0); @@ -87,6 +95,14 @@ private: SharedHandle writeCheckTarget; bool nameResolverCheck; +#ifdef ENABLE_ASYNC_DNS + + void setNameResolverCheck(const SharedHandle& resolver); + + void disableNameResolverCheck(const SharedHandle& resolver); + bool nameResolveFinished() const; + +#endif // ENABLE_ASYNC_DNS public: AbstractCommand(int32_t cuid, const SharedHandle& req, RequestGroup* requestGroup, DownloadEngine* e, diff --git a/src/AsyncNameResolver.cc b/src/AsyncNameResolver.cc new file mode 100644 index 00000000..e4d2a6ae --- /dev/null +++ b/src/AsyncNameResolver.cc @@ -0,0 +1,137 @@ +/* */ +#include "AsyncNameResolver.h" +#include "Util.h" +#include + +namespace aria2 { + +#ifdef HAVE_LIBCARES1_5 +void callback(void* arg, int status, int timeouts, struct hostent* host) +#else +void callback(void* arg, int status, struct hostent* host) +#endif // HAVE_LIBCARES1_5 +{ + AsyncNameResolver* resolverPtr = reinterpret_cast(arg); +#ifdef HAVE_LIBARES + // This block is required since the assertion in ares_strerror fails + // if status = ARES_EDESTRUCTION is passed to ares_strerror as 1st argument. + // This does not happen in c-ares. + if(status == ARES_EDESTRUCTION) { + // we simply return in this case. + return; + } +#endif + if(status != ARES_SUCCESS) { +#ifdef HAVE_LIBCARES + resolverPtr->error = ares_strerror(status); +#else + resolverPtr->error = ares_strerror(status, 0); +#endif // HAVE_LIBCARES + resolverPtr->status = AsyncNameResolver::STATUS_ERROR; + return; + } + for(char** ap = host->h_addr_list; *ap; ++ap) { + resolverPtr->_resolvedAddresses.push_back + (inet_ntoa(*reinterpret_cast(*ap))); + } + resolverPtr->status = AsyncNameResolver::STATUS_SUCCESS; +} + +AsyncNameResolver::AsyncNameResolver(): + status(STATUS_READY) +{ + // TODO evaluate return value + ares_init(&channel); +} + +AsyncNameResolver::~AsyncNameResolver() +{ + ares_destroy(channel); +} + +void AsyncNameResolver::resolve(const std::string& name) +{ + _hostname = name; + status = STATUS_QUERYING; + ares_gethostbyname(channel, name.c_str(), AF_INET, callback, this); +} + +const std::deque& AsyncNameResolver::getResolvedAddresses() const +{ + return _resolvedAddresses; +} + +const std::string& AsyncNameResolver::getError() const +{ + return error; +} + +AsyncNameResolver::STATUS AsyncNameResolver::getStatus() const +{ + return status; +} + +int AsyncNameResolver::getFds(fd_set* rfdsPtr, fd_set* wfdsPtr) const +{ + return ares_fds(channel, rfdsPtr, wfdsPtr); +} + +void AsyncNameResolver::process(fd_set* rfdsPtr, fd_set* wfdsPtr) +{ + ares_process(channel, rfdsPtr, wfdsPtr); +} + +bool AsyncNameResolver::operator==(const AsyncNameResolver& resolver) const +{ + return this == &resolver; +} + +void AsyncNameResolver::reset() +{ + _hostname = ""; + _resolvedAddresses.clear(); + status = STATUS_READY; + ares_destroy(channel); + // TODO evaluate return value + ares_init(&channel); +} + +const std::string& AsyncNameResolver::getHostname() const +{ + return _hostname; +} + +} // namespace aria2 diff --git a/src/AsyncNameResolver.h b/src/AsyncNameResolver.h new file mode 100644 index 00000000..0b715394 --- /dev/null +++ b/src/AsyncNameResolver.h @@ -0,0 +1,103 @@ +/* */ +#ifndef _D_ASYNC_NAME_RESOLVER_H_ +#define _D_ASYNC_NAME_RESOLVER_H_ + +#include "common.h" +#include "SharedHandle.h" +#include "a2netcompat.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +namespace aria2 { + +class AsyncNameResolver { +#ifdef HAVE_LIBCARES1_5 + friend void callback(void* arg, int status, int timeouts, struct hostent* host); +#else + friend void callback(void* arg, int status, struct hostent* host); +#endif // HAVE_LIBCARES1_5 + +public: + enum STATUS { + STATUS_READY, + STATUS_QUERYING, + STATUS_SUCCESS, + STATUS_ERROR, + }; +private: + STATUS status; + ares_channel channel; + + std::deque _resolvedAddresses; + std::string error; + std::string _hostname; +public: + AsyncNameResolver(); + + ~AsyncNameResolver(); + + void resolve(const std::string& name); + + const std::deque& getResolvedAddresses() const; + + const std::string& getError() const; + + STATUS getStatus() const; + + int getFds(fd_set* rfdsPtr, fd_set* wfdsPtr) const; + + void process(fd_set* rfdsPtr, fd_set* wfdsPtr); + + bool operator==(const AsyncNameResolver& resolver) const; + + void setAddr(const std::string& addrString); + + void reset(); + + const std::string& getHostname() const; +}; + +} // namespace aria2 + +#endif // _D_ASYNC_NAME_RESOLVER_H_ diff --git a/src/DHTEntryPointNameResolveCommand.cc b/src/DHTEntryPointNameResolveCommand.cc index 9c214d30..9ee4b663 100644 --- a/src/DHTEntryPointNameResolveCommand.cc +++ b/src/DHTEntryPointNameResolveCommand.cc @@ -34,8 +34,10 @@ /* copyright --> */ #include "DHTEntryPointNameResolveCommand.h" #include "DownloadEngine.h" +#ifdef ENABLE_ASYNC_DNS +#include "AsyncNameResolver.h" +#endif // ENABLE_ASYNC_DNS #include "NameResolver.h" -#include "DNSCache.h" #include "DlAbortEx.h" #include "prefs.h" #include "message.h" @@ -55,7 +57,6 @@ namespace aria2 { DHTEntryPointNameResolveCommand::DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e, const std::deque >& entryPoints): Command(cuid), _e(e), - _resolver(new NameResolver()), _entryPoints(entryPoints), _bootstrapEnabled(false) {} @@ -72,37 +73,53 @@ bool DHTEntryPointNameResolveCommand::execute() if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) { return true; } +#ifdef ENABLE_ASYNC_DNS + if(_resolver.isNull()) { + _resolver.reset(new AsyncNameResolver()); + } +#endif // ENABLE_ASYNC_DNS try { - while(_entryPoints.size()) { - std::string hostname = _entryPoints.front().first; - try { - if(Util::isNumbersAndDotsNotation(hostname)) { - std::pair p(hostname, - _entryPoints.front().second); - _resolvedEntryPoints.push_back(p); - _entryPoints.erase(_entryPoints.begin()); - addPingTask(p); - } else { +#ifdef ENABLE_ASYNC_DNS + if(_e->option->getAsBool(PREF_ASYNC_DNS)) { + while(_entryPoints.size()) { + std::string hostname = _entryPoints.front().first; + try { if(resolveHostname(hostname, _resolver)) { - hostname = _resolver->getAddrString(); - _resolver->reset(); + hostname = _resolver->getResolvedAddresses().front(); std::pair p(hostname, _entryPoints.front().second); _resolvedEntryPoints.push_back(p); - _entryPoints.erase(_entryPoints.begin()); addPingTask(p); } else { _e->commands.push_back(this); return false; } + } catch(RecoverableException& e) { + logger->error(EX_EXCEPTION_CAUGHT, e); } - } catch(RecoverableException& e) { - logger->error(EX_EXCEPTION_CAUGHT, e); - _entryPoints.erase(_entryPoints.begin()); _resolver->reset(); + _entryPoints.erase(_entryPoints.begin()); + } + } else +#endif // ENABLE_ASYNC_DNS + { + NameResolver res; + res.setSocktype(SOCK_DGRAM); + while(_entryPoints.size()) { + std::string hostname = _entryPoints.front().first; + try { + std::deque addrs(res.resolve(hostname)); + + std::pair p(addrs.front(), + _entryPoints.front().second); + _resolvedEntryPoints.push_back(p); + addPingTask(p); + } catch(RecoverableException& e) { + logger->error(EX_EXCEPTION_CAUGHT, e); + } + _entryPoints.erase(_entryPoints.begin()); + } } - } - if(_bootstrapEnabled && _resolvedEntryPoints.size()) { _taskQueue->addPeriodicTask1(_taskFactory->createNodeLookupTask(_localNode->getID())); _taskQueue->addPeriodicTask1(_taskFactory->createBucketRefreshTask()); @@ -122,54 +139,43 @@ void DHTEntryPointNameResolveCommand::addPingTask(const std::pairaddPeriodicTask1(_taskFactory->createPingTask(entryNode, 10)); } -bool DHTEntryPointNameResolveCommand::resolveHostname(const std::string& hostname, - const NameResolverHandle& resolver) -{ - std::string ipaddr = DNSCacheSingletonHolder::instance()->find(hostname); - if(ipaddr.empty()) { #ifdef ENABLE_ASYNC_DNS - switch(resolver->getStatus()) { - case NameResolver::STATUS_READY: - logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); - resolver->resolve(hostname); - setNameResolverCheck(resolver); - return false; - case NameResolver::STATUS_SUCCESS: - logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, - hostname.c_str(), resolver->getAddrString().c_str()); - DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); - return true; - break; - case NameResolver::STATUS_ERROR: - throw DlAbortEx - (StringFormat(MSG_NAME_RESOLUTION_FAILED, cuid, - hostname.c_str(), - resolver->getError().c_str()).str()); - default: - return false; - } -#else + +bool DHTEntryPointNameResolveCommand::resolveHostname +(const std::string& hostname, + const SharedHandle& resolver) +{ + switch(resolver->getStatus()) { + case AsyncNameResolver::STATUS_READY: logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); resolver->resolve(hostname); + setNameResolverCheck(resolver); + return false; + case AsyncNameResolver::STATUS_SUCCESS: logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, - hostname.c_str(), resolver->getAddrString().c_str()); - DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); - return true; -#endif // ENABLE_ASYNC_DNS - } else { - logger->info(MSG_DNS_CACHE_HIT, cuid, - hostname.c_str(), ipaddr.c_str()); - resolver->setAddr(ipaddr); + resolver->getHostname().c_str(), + resolver->getResolvedAddresses().front().c_str()); return true; + break; + case AsyncNameResolver::STATUS_ERROR: + throw DlAbortEx + (StringFormat(MSG_NAME_RESOLUTION_FAILED, cuid, + hostname.c_str(), + resolver->getError().c_str()).str()); + default: + return false; } } -#ifdef ENABLE_ASYNC_DNS -void DHTEntryPointNameResolveCommand::setNameResolverCheck(const SharedHandle& resolver) { +void DHTEntryPointNameResolveCommand::setNameResolverCheck +(const SharedHandle& resolver) +{ _e->addNameResolverCheck(resolver, this); } -void DHTEntryPointNameResolveCommand::disableNameResolverCheck(const SharedHandle& resolver) { +void DHTEntryPointNameResolveCommand::disableNameResolverCheck +(const SharedHandle& resolver) +{ _e->deleteNameResolverCheck(resolver, this); } #endif // ENABLE_ASYNC_DNS diff --git a/src/DHTEntryPointNameResolveCommand.h b/src/DHTEntryPointNameResolveCommand.h index ad4ca2c2..4979402e 100644 --- a/src/DHTEntryPointNameResolveCommand.h +++ b/src/DHTEntryPointNameResolveCommand.h @@ -47,13 +47,17 @@ class DHTTaskFactory; class DHTRoutingTable; class DHTNode; class DownloadEngine; -class NameResolver; +#ifdef ENABLE_ASYNC_DNS +class AsyncNameResolver; +#endif // ENABLE_ASYNC_DNS class DHTEntryPointNameResolveCommand:public Command { protected: DownloadEngine* _e; private: - SharedHandle _resolver; +#ifdef ENABLE_ASYNC_DNS + SharedHandle _resolver; +#endif // ENABLE_ASYNC_DNS SharedHandle _taskQueue; @@ -71,12 +75,14 @@ private: void addPingTask(const std::pair& addr); +#ifdef ENABLE_ASYNC_DNS bool resolveHostname(const std::string& hostname, - const SharedHandle& resolver); + const SharedHandle& resolver); - void setNameResolverCheck(const SharedHandle& resolver); + void setNameResolverCheck(const SharedHandle& resolver); - void disableNameResolverCheck(const SharedHandle& resolver); + void disableNameResolverCheck(const SharedHandle& resolver); +#endif // ENABLE_ASYNC_DNS public: DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e, diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 4fbdbc2f..c36fe7ef 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -33,7 +33,9 @@ */ /* copyright --> */ #include "DownloadEngine.h" -#include "NameResolver.h" +#ifdef ENABLE_ASYNC_DNS +#include "AsyncNameResolver.h" +#endif // ENABLE_ASYNC_DNS #include "StatCalc.h" #include "RequestGroup.h" #include "RequestGroupMan.h" @@ -73,11 +75,12 @@ bool SocketEntry::operator==(const SocketEntry& entry) } #ifdef ENABLE_ASYNC_DNS -NameResolverEntry::NameResolverEntry(const NameResolverHandle& nameResolver, - Command* command): +AsyncNameResolverEntry::AsyncNameResolverEntry +(const SharedHandle& nameResolver, + Command* command): nameResolver(nameResolver), command(command) {} -bool NameResolverEntry::operator==(const NameResolverEntry& entry) +bool AsyncNameResolverEntry::operator==(const AsyncNameResolverEntry& entry) { return nameResolver == entry.nameResolver && command == entry.command; @@ -164,9 +167,9 @@ void DownloadEngine::waitData() { memcpy(&wfds, &wfdset, sizeof(fd_set)); #ifdef ENABLE_ASYNC_DNS - for(NameResolverEntries::iterator itr = nameResolverEntries.begin(); + for(AsyncNameResolverEntries::iterator itr = nameResolverEntries.begin(); itr != nameResolverEntries.end(); ++itr) { - NameResolverEntry& entry = *itr; + AsyncNameResolverEntry& entry = *itr; int fd = entry.nameResolver->getFds(&rfds, &wfds); // TODO force error if fd == 0 if(fdmax < fd) { @@ -189,13 +192,13 @@ void DownloadEngine::waitData() { } } #ifdef ENABLE_ASYNC_DNS - for(NameResolverEntries::iterator itr = nameResolverEntries.begin(); + for(AsyncNameResolverEntries::iterator itr = nameResolverEntries.begin(); itr != nameResolverEntries.end(); ++itr) { - NameResolverEntry& entry = *itr; + AsyncNameResolverEntry& entry = *itr; entry.nameResolver->process(&rfds, &wfds); switch(entry.nameResolver->getStatus()) { - case NameResolver::STATUS_SUCCESS: - case NameResolver::STATUS_ERROR: + case AsyncNameResolver::STATUS_SUCCESS: + case AsyncNameResolver::STATUS_ERROR: entry.command->setStatusActive(); break; default: @@ -323,12 +326,13 @@ void DownloadEngine::addCommand(const Commands& commands) } #ifdef ENABLE_ASYNC_DNS -bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver, - Command* command) { - NameResolverEntry entry(resolver, command); - NameResolverEntries::iterator itr = std::find(nameResolverEntries.begin(), - nameResolverEntries.end(), - entry); +bool DownloadEngine::addNameResolverCheck +(const SharedHandle& resolver, + Command* command) +{ + AsyncNameResolverEntry entry(resolver, command); + AsyncNameResolverEntries::iterator itr = + std::find(nameResolverEntries.begin(), nameResolverEntries.end(), entry); if(itr == nameResolverEntries.end()) { nameResolverEntries.push_back(entry); return true; @@ -337,12 +341,13 @@ bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver, } } -bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver, - Command* command) { - NameResolverEntry entry(resolver, command); - NameResolverEntries::iterator itr = std::find(nameResolverEntries.begin(), - nameResolverEntries.end(), - entry); +bool DownloadEngine::deleteNameResolverCheck +(const SharedHandle& resolver, + Command* command) +{ + AsyncNameResolverEntry entry(resolver, command); + AsyncNameResolverEntries::iterator itr = + std::find(nameResolverEntries.begin(), nameResolverEntries.end(), entry); if(itr == nameResolverEntries.end()) { return false; } else { @@ -388,4 +393,18 @@ DownloadEngine::popPooledSocket(const std::string& ipaddr, uint16_t port) } } +SharedHandle +DownloadEngine::popPooledSocket +(const std::deque& ipaddrs, uint16_t port) +{ + for(std::deque::const_iterator i = ipaddrs.begin(); + i != ipaddrs.end(); ++i) { + SharedHandle s = popPooledSocket(*i, port); + if(!s.isNull()) { + return s; + } + } + return SharedHandle(); +} + } // namespace aria2 diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h index 6aa519b2..70bd1f90 100644 --- a/src/DownloadEngine.h +++ b/src/DownloadEngine.h @@ -38,15 +38,17 @@ #include "common.h" #include "SharedHandle.h" #include "Command.h" +#include "a2netcompat.h" #include #include -#include "a2netcompat.h" namespace aria2 { class Logger; class Option; -class NameResolver; +#ifdef ENABLE_ASYNC_DNS +class AsyncNameResolver; +#endif // ENABLE_ASYNC_DNS class RequestGroupMan; class FileAllocationMan; class StatCalc; @@ -74,18 +76,18 @@ public: typedef std::deque SocketEntries; #ifdef ENABLE_ASYNC_DNS -class NameResolverEntry { +class AsyncNameResolverEntry { public: - SharedHandle nameResolver; + SharedHandle nameResolver; Command* command; public: - NameResolverEntry(const SharedHandle& nameResolver, - Command* command); + AsyncNameResolverEntry(const SharedHandle& nameResolver, + Command* command); - bool operator==(const NameResolverEntry& entry); + bool operator==(const AsyncNameResolverEntry& entry); }; -typedef std::deque NameResolverEntries; +typedef std::deque AsyncNameResolverEntries; #endif // ENABLE_ASYNC_DNS class DownloadEngine { @@ -93,7 +95,7 @@ private: void waitData(); SocketEntries socketEntries; #ifdef ENABLE_ASYNC_DNS - NameResolverEntries nameResolverEntries; + AsyncNameResolverEntries nameResolverEntries; #endif // ENABLE_ASYNC_DNS fd_set rfdset; fd_set wfdset; @@ -152,9 +154,9 @@ public: bool deleteSocketForWriteCheck(const SharedHandle& socket, Command* command); #ifdef ENABLE_ASYNC_DNS - bool addNameResolverCheck(const SharedHandle& resolver, + bool addNameResolverCheck(const SharedHandle& resolver, Command* command); - bool deleteNameResolverCheck(const SharedHandle& resolver, + bool deleteNameResolverCheck(const SharedHandle& resolver, Command* command); #endif // ENABLE_ASYNC_DNS @@ -180,6 +182,10 @@ public: SharedHandle popPooledSocket(const std::string& ipaddr, uint16_t port); + + + SharedHandle + popPooledSocket(const std::deque& ipaddrs, uint16_t port); }; typedef SharedHandle DownloadEngineHandle; diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc index 79bb3690..1908483f 100644 --- a/src/FtpInitiateConnectionCommand.cc +++ b/src/FtpInitiateConnectionCommand.cc @@ -33,9 +33,7 @@ */ /* copyright --> */ #include "FtpInitiateConnectionCommand.h" -#include "NameResolver.h" #include "DownloadEngine.h" -#include "RequestGroup.h" #include "Option.h" #include "Request.h" #include "FtpNegotiationCommand.h" @@ -47,58 +45,35 @@ #include "Logger.h" #include "message.h" #include "prefs.h" -#include "Util.h" #include "HttpConnection.h" #include "Socket.h" namespace aria2 { -FtpInitiateConnectionCommand::FtpInitiateConnectionCommand(int cuid, - const RequestHandle& req, - RequestGroup* requestGroup, - DownloadEngine* e) - :AbstractCommand(cuid, req, requestGroup, e), - nameResolver(new NameResolver()) +FtpInitiateConnectionCommand::FtpInitiateConnectionCommand +(int cuid, + const RequestHandle& req, + RequestGroup* requestGroup, + DownloadEngine* e) + :InitiateConnectionCommand(cuid, req, requestGroup, e) {} + +FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {} + +Command* FtpInitiateConnectionCommand::createNextCommand +(const std::deque& resolvedAddresses) { - setTimeout(e->option->getAsInt(PREF_DNS_TIMEOUT)); - setStatus(Command::STATUS_ONESHOT_REALTIME); - disableReadCheckSocket(); - disableWriteCheckSocket(); -} - -FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() { -#ifdef ENABLE_ASYNC_DNS - disableNameResolverCheck(nameResolver); -#endif // ENABLE_ASYNC_DNS -} - -bool FtpInitiateConnectionCommand::executeInternal() { - std::string hostname; - if(useHttpProxy()) { - hostname = e->option->get(PREF_HTTP_PROXY_HOST); - } else { - hostname = req->getHost(); - } - if(!Util::isNumbersAndDotsNotation(hostname)) { - if(resolveHostname(hostname, nameResolver)) { - hostname = nameResolver->getAddrString(); - } else { - e->commands.push_back(this); - return false; - } - } Command* command; - if(useHttpProxy()) { + if(useHTTPProxy()) { logger->info(MSG_CONNECTING_TO_SERVER, cuid, e->option->get(PREF_HTTP_PROXY_HOST).c_str(), e->option->getAsInt(PREF_HTTP_PROXY_PORT)); - socket->establishConnection(hostname, + socket->establishConnection(resolvedAddresses.front(), e->option->getAsInt(PREF_HTTP_PROXY_PORT)); - if(useHttpProxyGet()) { + if(useHTTPProxyGet()) { SharedHandle hc(new HttpConnection(cuid, socket, e->option)); command = new HttpRequestCommand(cuid, req, _requestGroup, hc, e, socket); - } else if(useHttpProxyConnect()) { + } else if(useHTTPProxyConnect()) { command = new FtpTunnelRequestCommand(cuid, req, _requestGroup, e, socket); } else { // TODO @@ -107,30 +82,18 @@ bool FtpInitiateConnectionCommand::executeInternal() { } else { logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(), req->getPort()); - socket->establishConnection(hostname, req->getPort()); + socket->establishConnection(resolvedAddresses.front(), req->getPort()); command = new FtpNegotiationCommand(cuid, req, _requestGroup, e, socket); } - e->commands.push_back(command); - return true; + return command; } -bool FtpInitiateConnectionCommand::useHttpProxy() const { - return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; +bool FtpInitiateConnectionCommand::useHTTPProxyGet() const { + return useHTTPProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET; } -bool FtpInitiateConnectionCommand::useHttpProxyGet() const { - return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET; +bool FtpInitiateConnectionCommand::useHTTPProxyConnect() const { + return useHTTPProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL; } -bool FtpInitiateConnectionCommand::useHttpProxyConnect() const { - return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL; -} - -#ifdef ENABLE_ASYNC_DNS -bool FtpInitiateConnectionCommand::nameResolveFinished() const { - return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS || - nameResolver->getStatus() == NameResolver::STATUS_ERROR; -} -#endif // ENABLE_ASYNC_DNS - } // namespace aria2 diff --git a/src/FtpInitiateConnectionCommand.h b/src/FtpInitiateConnectionCommand.h index 9d6e29ab..6ab962c2 100644 --- a/src/FtpInitiateConnectionCommand.h +++ b/src/FtpInitiateConnectionCommand.h @@ -35,21 +35,17 @@ #ifndef _D_FTP_INITIATE_CONNECTION_COMMAND_H_ #define _D_FTP_INITIATE_CONNECTION_COMMAND_H_ -#include "AbstractCommand.h" +#include "InitiateConnectionCommand.h" namespace aria2 { -class FtpInitiateConnectionCommand : public AbstractCommand { +class FtpInitiateConnectionCommand : public InitiateConnectionCommand { private: - SharedHandle nameResolver; - bool useHttpProxy() const; - bool useHttpProxyGet() const; - bool useHttpProxyConnect() const; -#ifdef ENABLE_ASYNC_DNS - virtual bool nameResolveFinished() const; -#endif // ENABLE_ASYNC_DNS + bool useHTTPProxyGet() const; + bool useHTTPProxyConnect() const; protected: - virtual bool executeInternal(); + virtual Command* createNextCommand + (const std::deque& resolvedAddresses); public: FtpInitiateConnectionCommand(int cuid, const SharedHandle& req, RequestGroup* requestGroup, DownloadEngine* e); diff --git a/src/HelpItemFactory.cc b/src/HelpItemFactory.cc index d8295187..5f42888e 100644 --- a/src/HelpItemFactory.cc +++ b/src/HelpItemFactory.cc @@ -458,6 +458,13 @@ TagContainerHandle HelpItemFactory::createHelpItems(const Option* op) item->addTag(TAG_ADVANCED); tc->addItem(item); } +#ifdef ENABLE_ASYNC_DNS + { + HelpItemHandle item(new HelpItem(PREF_ASYNC_DNS, TEXT_ASYNC_DNS, op->get(PREF_ASYNC_DNS))); + item->addTag(TAG_ADVANCED); + tc->addItem(item); + } +#endif // ENABLE_ASYNC_DNS { HelpItemHandle item(new HelpItem("help", TEXT_HELP, TAG_BASIC)); item->setAvailableValues diff --git a/src/HttpInitiateConnectionCommand.cc b/src/HttpInitiateConnectionCommand.cc index cb4f35d9..76400187 100644 --- a/src/HttpInitiateConnectionCommand.cc +++ b/src/HttpInitiateConnectionCommand.cc @@ -33,7 +33,6 @@ */ /* copyright --> */ #include "HttpInitiateConnectionCommand.h" -#include "NameResolver.h" #include "Request.h" #include "DownloadEngine.h" #include "HttpConnection.h" @@ -43,7 +42,6 @@ #include "HttpProxyRequestCommand.h" #include "DlAbortEx.h" #include "Option.h" -#include "Util.h" #include "Logger.h" #include "Socket.h" #include "message.h" @@ -51,46 +49,24 @@ namespace aria2 { -HttpInitiateConnectionCommand::HttpInitiateConnectionCommand(int cuid, - const RequestHandle& req, - RequestGroup* requestGroup, - DownloadEngine* e): - AbstractCommand(cuid, req, requestGroup, e), - nameResolver(new NameResolver()) +HttpInitiateConnectionCommand::HttpInitiateConnectionCommand +(int cuid, + const RequestHandle& req, + RequestGroup* requestGroup, + DownloadEngine* e): + InitiateConnectionCommand(cuid, req, requestGroup, e) {} + +HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() {} + +Command* HttpInitiateConnectionCommand::createNextCommand +(const std::deque& resolvedAddresses) { - setTimeout(e->option->getAsInt(PREF_DNS_TIMEOUT)); - setStatus(Command::STATUS_ONESHOT_REALTIME); - disableReadCheckSocket(); - disableWriteCheckSocket(); -} - -HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() { -#ifdef ENABLE_ASYNC_DNS - disableNameResolverCheck(nameResolver); -#endif // ENABLE_ASYNC_DNS -} - -bool HttpInitiateConnectionCommand::executeInternal() { - std::string hostname; - if(useProxy()) { - hostname = e->option->get(PREF_HTTP_PROXY_HOST); - } else { - hostname = req->getHost(); - } - if(!Util::isNumbersAndDotsNotation(hostname)) { - if(resolveHostname(hostname, nameResolver)) { - hostname = nameResolver->getAddrString(); - } else { - e->commands.push_back(this); - return false; - } - } Command* command; - if(useProxy()) { + if(useHTTPProxy()) { logger->info(MSG_CONNECTING_TO_SERVER, cuid, e->option->get(PREF_HTTP_PROXY_HOST).c_str(), e->option->getAsInt(PREF_HTTP_PROXY_PORT)); - socket->establishConnection(hostname, + socket->establishConnection(resolvedAddresses.front(), e->option->getAsInt(PREF_HTTP_PROXY_PORT)); if(useProxyTunnel()) { command = new HttpProxyRequestCommand(cuid, req, _requestGroup, e, socket); @@ -104,12 +80,11 @@ bool HttpInitiateConnectionCommand::executeInternal() { } } else { SharedHandle pooledSocket = - e->popPooledSocket(hostname, req->getPort()); - + e->popPooledSocket(resolvedAddresses, req->getPort()); if(pooledSocket.isNull()) { logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(), req->getPort()); - socket->establishConnection(hostname, req->getPort()); + socket->establishConnection(resolvedAddresses.front(), req->getPort()); } else { socket = pooledSocket; } @@ -117,27 +92,17 @@ bool HttpInitiateConnectionCommand::executeInternal() { command = new HttpRequestCommand(cuid, req, _requestGroup, httpConnection, e, socket); } - e->commands.push_back(command); - return true; + return command; } -bool HttpInitiateConnectionCommand::useProxy() { - return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; -} - -bool HttpInitiateConnectionCommand::useProxyGet() { +bool HttpInitiateConnectionCommand::useProxyGet() const +{ return e->option->get(PREF_HTTP_PROXY_METHOD) == V_GET; } -bool HttpInitiateConnectionCommand::useProxyTunnel() { +bool HttpInitiateConnectionCommand::useProxyTunnel() const +{ return e->option->get(PREF_HTTP_PROXY_METHOD) == V_TUNNEL; } -#ifdef ENABLE_ASYNC_DNS -bool HttpInitiateConnectionCommand::nameResolveFinished() const { - return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS || - nameResolver->getStatus() == NameResolver::STATUS_ERROR; -} -#endif // ENABLE_ASYNC_DNS - } // namespace aria2 diff --git a/src/HttpInitiateConnectionCommand.h b/src/HttpInitiateConnectionCommand.h index b9579c38..c737c6cc 100644 --- a/src/HttpInitiateConnectionCommand.h +++ b/src/HttpInitiateConnectionCommand.h @@ -35,29 +35,17 @@ #ifndef _D_HTTP_INITIATE_CONNECTION_COMMAND_H_ #define _D_HTTP_INITIATE_CONNECTION_COMMAND_H_ -#include "AbstractCommand.h" +#include "InitiateConnectionCommand.h" namespace aria2 { -class HttpInitiateConnectionCommand : public AbstractCommand { +class HttpInitiateConnectionCommand : public InitiateConnectionCommand { private: - SharedHandle nameResolver; - bool useProxy(); - bool useProxyGet(); - bool useProxyTunnel(); + bool useProxyGet() const; + bool useProxyTunnel() const; protected: - /** - * Connect to the server. - * This method just send connection request to the server. - * Using nonblocking mode of socket, this funtion returns immediately - * after send connection packet to the server. - * Whether or not the connection is established successfully is - * evaluated by RequestCommand. - */ - virtual bool executeInternal(); -#ifdef ENABLE_ASYNC_DNS - virtual bool nameResolveFinished() const; -#endif // ENABLE_ASYNC_DNS + virtual Command* createNextCommand + (const std::deque& resolvedAddresses); public: HttpInitiateConnectionCommand(int cuid, const SharedHandle& req, RequestGroup* requestGroup, diff --git a/src/InitiateConnectionCommand.cc b/src/InitiateConnectionCommand.cc new file mode 100644 index 00000000..0c651a8e --- /dev/null +++ b/src/InitiateConnectionCommand.cc @@ -0,0 +1,109 @@ +/* */ +#include "InitiateConnectionCommand.h" +#include "Request.h" +#include "DownloadEngine.h" +#include "Option.h" +#include "Logger.h" +#include "message.h" +#include "prefs.h" +#include "NameResolver.h" +#include "DNSCache.h" + +namespace aria2 { + +InitiateConnectionCommand::InitiateConnectionCommand +(int cuid, + const RequestHandle& req, + RequestGroup* requestGroup, + DownloadEngine* e): + AbstractCommand(cuid, req, requestGroup, e) +{ + setTimeout(e->option->getAsInt(PREF_DNS_TIMEOUT)); + setStatus(Command::STATUS_ONESHOT_REALTIME); + disableReadCheckSocket(); + disableWriteCheckSocket(); +} + +InitiateConnectionCommand::~InitiateConnectionCommand() {} + +bool InitiateConnectionCommand::executeInternal() { + std::string hostname; + if(useHTTPProxy()) { + hostname = e->option->get(PREF_HTTP_PROXY_HOST); + } else { + hostname = req->getHost(); + } + std::deque addrs; + std::string ipaddr = DNSCacheSingletonHolder::instance()->find(hostname); + if(ipaddr.empty()) { +#ifdef ENABLE_ASYNC_DNS + if(e->option->getAsBool(PREF_ASYNC_DNS)) { + if(!isAsyncNameResolverInitialized()) { + initAsyncNameResolver(hostname); + } + if(asyncResolveHostname()) { + addrs = getResolvedAddresses(); + } else { + e->commands.push_back(this); + return false; + } + } else +#endif // ENABLE_ASYNC_DNS + { + NameResolver res; + res.setSocktype(SOCK_STREAM); + addrs = res.resolve(hostname); + } + logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, + hostname.c_str(), + addrs.front().c_str()); + DNSCacheSingletonHolder::instance()->put(hostname, addrs.front()); + } else { + logger->info(MSG_DNS_CACHE_HIT, cuid, hostname.c_str(), ipaddr.c_str()); + addrs.push_back(ipaddr); + } + + Command* command = createNextCommand(addrs); + e->commands.push_back(command); + return true; +} + +bool InitiateConnectionCommand::useHTTPProxy() const +{ + return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; +} + +} // namespace aria2 diff --git a/src/InitiateConnectionCommand.h b/src/InitiateConnectionCommand.h new file mode 100644 index 00000000..f173abd4 --- /dev/null +++ b/src/InitiateConnectionCommand.h @@ -0,0 +1,66 @@ +/* */ +#ifndef _D_INITIATE_CONNECTION_COMMAND_H_ +#define _D_INITIATE_CONNECTION_COMMAND_H_ + +#include "AbstractCommand.h" + +namespace aria2 { + +class InitiateConnectionCommand : public AbstractCommand { +protected: + bool useHTTPProxy() const; + + /** + * Connect to the server. + * This method just send connection request to the server. + * Using nonblocking mode of socket, this funtion returns immediately + * after send connection packet to the server. + */ + virtual bool executeInternal(); + + virtual Command* createNextCommand + (const std::deque& resolvedAddresses) = 0; +public: + InitiateConnectionCommand(int cuid, const SharedHandle& req, + RequestGroup* requestGroup, + DownloadEngine* e); + + virtual ~InitiateConnectionCommand(); +}; + +} // namespace aria2 + +#endif // _D_INITIATE_CONNECTION_COMMAND_H_ diff --git a/src/Makefile.am b/src/Makefile.am index 2e9bdf1b..a5e107e1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -184,7 +184,12 @@ SRCS = Socket.h\ ProtocolDetector.cc ProtocolDetector.h\ NullStatCalc.h\ StringFormat.cc StringFormat.h\ - HttpNullDownloadCommand.cc HttpNullDownloadCommand.h + HttpNullDownloadCommand.cc HttpNullDownloadCommand.h\ + InitiateConnectionCommand.cc InitiateConnectionCommand.h + +if ENABLE_ASYNC_DNS +SRCS += AsyncNameResolver.cc AsyncNameResolver.h +endif # ENABLE_ASYNC_DNS if ENABLE_MESSAGE_DIGEST SRCS += IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ diff --git a/src/Makefile.in b/src/Makefile.in index b46262e2..384f906f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -39,7 +39,8 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = aria2c$(EXEEXT) -@ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ +@ENABLE_ASYNC_DNS_TRUE@am__append_1 = AsyncNameResolver.cc AsyncNameResolver.h +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_2 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.cc ChecksumCheckIntegrityEntry.h\ @@ -48,7 +49,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_MESSAGE_DIGEST_TRUE@ Checksum.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ ChunkChecksum.h -@ENABLE_BITTORRENT_TRUE@am__append_2 = MetaEntry.h\ +@ENABLE_BITTORRENT_TRUE@am__append_3 = MetaEntry.h\ @ENABLE_BITTORRENT_TRUE@ Data.cc Data.h\ @ENABLE_BITTORRENT_TRUE@ Dictionary.cc Dictionary.h\ @ENABLE_BITTORRENT_TRUE@ List.cc List.h\ @@ -225,7 +226,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.cc BtLeecherStateChoke.h\ @ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.cc BtSeederStateChoke.h -@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\ +@ENABLE_METALINK_TRUE@am__append_4 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ @@ -253,17 +254,17 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ @ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h -@ENABLE_LIBXML2_TRUE@am__append_4 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h -@ENABLE_LIBEXPAT_TRUE@am__append_5 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h -@HAVE_BASENAME_FALSE@am__append_6 = libgen.c libgen.h -@HAVE_GETADDRINFO_FALSE@am__append_7 = getaddrinfo.c getaddrinfo.h -@HAVE_GAI_STRERROR_FALSE@am__append_8 = gai_strerror.c gai_strerror.h -@HAVE_GETTIMEOFDAY_FALSE@am__append_9 = gettimeofday.c gettimeofday.h \ +@ENABLE_LIBXML2_TRUE@am__append_5 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h +@ENABLE_LIBEXPAT_TRUE@am__append_6 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h +@HAVE_BASENAME_FALSE@am__append_7 = libgen.c libgen.h +@HAVE_GETADDRINFO_FALSE@am__append_8 = getaddrinfo.c getaddrinfo.h +@HAVE_GAI_STRERROR_FALSE@am__append_9 = gai_strerror.c gai_strerror.h +@HAVE_GETTIMEOFDAY_FALSE@am__append_10 = gettimeofday.c gettimeofday.h \ @HAVE_GETTIMEOFDAY_FALSE@ gettimeofday.c gettimeofday.h -@HAVE_INET_ATON_FALSE@am__append_10 = inet_aton.c inet_aton.h -@HAVE_LOCALTIME_R_FALSE@am__append_11 = localtime_r.c localtime_r.h -@HAVE_STRPTIME_FALSE@am__append_12 = strptime.c strptime.h -@HAVE_TIMEGM_FALSE@am__append_13 = timegm.c timegm.h +@HAVE_INET_ATON_FALSE@am__append_11 = inet_aton.c inet_aton.h +@HAVE_LOCALTIME_R_FALSE@am__append_12 = localtime_r.c localtime_r.h +@HAVE_STRPTIME_FALSE@am__append_13 = strptime.c strptime.h +@HAVE_TIMEGM_FALSE@am__append_14 = timegm.c timegm.h subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -406,6 +407,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ usage_text.h ProtocolDetector.cc ProtocolDetector.h \ NullStatCalc.h StringFormat.cc StringFormat.h \ HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \ + InitiateConnectionCommand.cc InitiateConnectionCommand.h \ + AsyncNameResolver.cc AsyncNameResolver.h \ IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ @@ -560,13 +563,14 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ getaddrinfo.h gai_strerror.c gai_strerror.h gettimeofday.c \ gettimeofday.h inet_aton.c inet_aton.h localtime_r.c \ localtime_r.h strptime.c strptime.h timegm.c timegm.h -@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = IteratableChunkChecksumValidator.$(OBJEXT) \ +@ENABLE_ASYNC_DNS_TRUE@am__objects_1 = AsyncNameResolver.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_2 = IteratableChunkChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT) -@ENABLE_BITTORRENT_TRUE@am__objects_2 = Data.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@am__objects_3 = Data.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BencodeVisitor.$(OBJEXT) \ @@ -677,7 +681,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ MSEHandshake.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@am__objects_4 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkProcessorFactory.$(OBJEXT) \ @@ -702,20 +706,20 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroup.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT) -@ENABLE_LIBXML2_TRUE@am__objects_4 = \ +@ENABLE_LIBXML2_TRUE@am__objects_5 = \ @ENABLE_LIBXML2_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT) -@ENABLE_LIBEXPAT_TRUE@am__objects_5 = \ +@ENABLE_LIBEXPAT_TRUE@am__objects_6 = \ @ENABLE_LIBEXPAT_TRUE@ ExpatMetalinkProcessor.$(OBJEXT) -@HAVE_BASENAME_FALSE@am__objects_6 = libgen.$(OBJEXT) -@HAVE_GETADDRINFO_FALSE@am__objects_7 = getaddrinfo.$(OBJEXT) -@HAVE_GAI_STRERROR_FALSE@am__objects_8 = gai_strerror.$(OBJEXT) -@HAVE_GETTIMEOFDAY_FALSE@am__objects_9 = gettimeofday.$(OBJEXT) \ +@HAVE_BASENAME_FALSE@am__objects_7 = libgen.$(OBJEXT) +@HAVE_GETADDRINFO_FALSE@am__objects_8 = getaddrinfo.$(OBJEXT) +@HAVE_GAI_STRERROR_FALSE@am__objects_9 = gai_strerror.$(OBJEXT) +@HAVE_GETTIMEOFDAY_FALSE@am__objects_10 = gettimeofday.$(OBJEXT) \ @HAVE_GETTIMEOFDAY_FALSE@ gettimeofday.$(OBJEXT) -@HAVE_INET_ATON_FALSE@am__objects_10 = inet_aton.$(OBJEXT) -@HAVE_LOCALTIME_R_FALSE@am__objects_11 = localtime_r.$(OBJEXT) -@HAVE_STRPTIME_FALSE@am__objects_12 = strptime.$(OBJEXT) -@HAVE_TIMEGM_FALSE@am__objects_13 = timegm.$(OBJEXT) -am__objects_14 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ +@HAVE_INET_ATON_FALSE@am__objects_11 = inet_aton.$(OBJEXT) +@HAVE_LOCALTIME_R_FALSE@am__objects_12 = localtime_r.$(OBJEXT) +@HAVE_STRPTIME_FALSE@am__objects_13 = strptime.$(OBJEXT) +@HAVE_TIMEGM_FALSE@am__objects_14 = timegm.$(OBJEXT) +am__objects_15 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \ DownloadCommand.$(OBJEXT) \ @@ -783,12 +787,13 @@ am__objects_14 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ HelpItemFactory.$(OBJEXT) SingleFileDownloadContext.$(OBJEXT) \ TimedHaltCommand.$(OBJEXT) ProtocolDetector.$(OBJEXT) \ StringFormat.$(OBJEXT) HttpNullDownloadCommand.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) $(am__objects_5) $(am__objects_6) \ - $(am__objects_7) $(am__objects_8) $(am__objects_9) \ - $(am__objects_10) $(am__objects_11) $(am__objects_12) \ - $(am__objects_13) -am_libaria2c_a_OBJECTS = $(am__objects_14) + InitiateConnectionCommand.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) \ + $(am__objects_5) $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) $(am__objects_9) $(am__objects_10) \ + $(am__objects_11) $(am__objects_12) $(am__objects_13) \ + $(am__objects_14) +am_libaria2c_a_OBJECTS = $(am__objects_15) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -1124,11 +1129,12 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ usage_text.h ProtocolDetector.cc ProtocolDetector.h \ NullStatCalc.h StringFormat.cc StringFormat.h \ HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \ + InitiateConnectionCommand.cc InitiateConnectionCommand.h \ $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) + $(am__append_13) $(am__append_14) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -1225,6 +1231,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractSingleDiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActivePeerConnectionCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceList.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AsyncNameResolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AutoSaveCommand.Po@am__quote@ @@ -1390,6 +1397,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitialMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommandFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiatorMSEHandshakeCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidator.Po@am__quote@ diff --git a/src/NameResolver.cc b/src/NameResolver.cc index 3b6ecada..1b7f4e50 100644 --- a/src/NameResolver.cc +++ b/src/NameResolver.cc @@ -36,98 +36,43 @@ #include "DlAbortEx.h" #include "message.h" #include "StringFormat.h" +#include "Util.h" #include namespace aria2 { -#ifdef ENABLE_ASYNC_DNS +NameResolver::NameResolver():_socktype(0) {} -#ifdef HAVE_LIBCARES1_5 -void callback(void* arg, int status, int timeouts, struct hostent* host) -#else -void callback(void* arg, int status, struct hostent* host) -#endif // HAVE_LIBCARES1_5 +std::deque NameResolver::resolve(const std::string& hostname) { - NameResolver* resolverPtr = (NameResolver*)arg; -#ifdef HAVE_LIBARES - // This block is required since the assertion in ares_strerror fails - // if status = ARES_EDESTRUCTION is passed to ares_strerror as 1st argument. - // This does not happen in c-ares. - if(status == ARES_EDESTRUCTION) { - // we simply return in this case. - return; - } -#endif - if(status != ARES_SUCCESS) { -#ifdef HAVE_LIBCARES - resolverPtr->error = ares_strerror(status); -#else - resolverPtr->error = ares_strerror(status, 0); -#endif // HAVE_LIBCARES - resolverPtr->status = NameResolver::STATUS_ERROR; - return; - } - memcpy(&resolverPtr->addr, *host->h_addr_list, sizeof(struct in_addr)); - resolverPtr->status = NameResolver::STATUS_SUCCESS; -} - -void NameResolver::resolve(const std::string& name) -{ - status = STATUS_QUERYING; - ares_gethostbyname(channel, name.c_str(), AF_INET, callback, this); -} - -std::string NameResolver::getAddrString() const -{ - return inet_ntoa(addr); -} - -void NameResolver::setAddr(const std::string& addrString) -{ - inet_aton(addrString.c_str(), &addr); -} - -void NameResolver::reset() -{ - status = STATUS_READY; - ares_destroy(channel); - // TODO evaluate return value - ares_init(&channel); -} - -#else // ENABLE_ASYNC_DNS - -void NameResolver::resolve(const std::string& hostname) -{ - memset(&_addr, 0, sizeof(in_addr)); - struct addrinfo ai; - memset((char*)&ai, 0, sizeof(ai)); - ai.ai_flags = 0; - ai.ai_family = PF_INET; - ai.ai_socktype = SOCK_STREAM; - ai.ai_protocol = 0; + struct addrinfo hints; struct addrinfo* res; - int ec; - if((ec = getaddrinfo(hostname.c_str(), 0, &ai, &res)) != 0) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = _socktype; + hints.ai_flags = 0; + hints.ai_protocol = 0; + int s; + s = getaddrinfo(hostname.c_str(), "0", &hints, &res); + if(s) { throw DlAbortEx(StringFormat(EX_RESOLVE_HOSTNAME, - hostname.c_str(), gai_strerror(ec)).str()); + hostname.c_str(), gai_strerror(s)).str()); + } + std::deque addrs; + struct addrinfo* rp; + for(rp = res; rp; rp = rp->ai_next) { + std::pair addressPort + = Util::getNumericNameInfo(rp->ai_addr, rp->ai_addrlen); + addrs.push_back(addressPort.first); } - _addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr; freeaddrinfo(res); + + return addrs; } -std::string NameResolver::getAddrString() const +void NameResolver::setSocktype(int socktype) { - return inet_ntoa(_addr); + _socktype = socktype; } -void NameResolver::setAddr(const std::string& addrString) -{ - inet_aton(addrString.c_str(), &_addr); -} - -void NameResolver::reset() {} - -#endif // ENABLE_ASYNC_DNS - } // namespace aria2 diff --git a/src/NameResolver.h b/src/NameResolver.h index 203496ba..814d8732 100644 --- a/src/NameResolver.h +++ b/src/NameResolver.h @@ -36,115 +36,23 @@ #define _D_NAME_RESOLVER_H_ #include "common.h" -#include "SharedHandle.h" -#include "a2netcompat.h" #include - -#ifdef ENABLE_ASYNC_DNS - -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} /* end of extern "C" */ -#endif - -#endif // ENABLE_ASYNC_DNS +#include namespace aria2 { -#ifdef ENABLE_ASYNC_DNS - -#ifdef HAVE_LIBCARES1_5 -void callback(void* arg, int status, int timeouts, struct hostent* host); -#else -void callback(void* arg, int status, struct hostent* host); -#endif // HAVE_LIBCARES1_5 - -class NameResolver { -#ifdef HAVE_LIBCARES1_5 - friend void callback(void* arg, int status, int timeouts, struct hostent* host); -#else - friend void callback(void* arg, int status, struct hostent* host); -#endif // HAVE_LIBCARES1_5 - -public: - enum STATUS { - STATUS_READY, - STATUS_QUERYING, - STATUS_SUCCESS, - STATUS_ERROR, - }; -private: - STATUS status; - ares_channel channel; - struct in_addr addr; - std::string error; -public: - NameResolver(): - status(STATUS_READY) - { - // TODO evaluate return value - ares_init(&channel); - } - - ~NameResolver() { - ares_destroy(channel); - } - - void resolve(const std::string& name); - - std::string getAddrString() const; - - const struct in_addr& getAddr() const { - return addr; - } - - const std::string& getError() const { - return error; - } - - STATUS getStatus() const { - return status; - } - - int getFds(fd_set* rfdsPtr, fd_set* wfdsPtr) const { - return ares_fds(channel, rfdsPtr, wfdsPtr); - } - - void process(fd_set* rfdsPtr, fd_set* wfdsPtr) { - ares_process(channel, rfdsPtr, wfdsPtr); - } - - bool operator==(const NameResolver& resolver) { - return this == &resolver; - } - - void setAddr(const std::string& addrString); - - void reset(); -}; - -#else // ENABLE_ASYNC_DNS - class NameResolver { private: - struct in_addr _addr; + int _socktype; public: - void resolve(const std::string& hostname); + NameResolver(); - std::string getAddrString() const; - - void setAddr(const std::string& addrString); + std::deque resolve(const std::string& hostname); - void reset(); + // specify SOCK_STREAM or SOCK_DGRAM + void setSocktype(int socktype); }; -#endif // ENABLE_ASYNC_DNS - -typedef SharedHandle NameResolverHandle; - } // namespace aria2 #endif // _D_NAME_RESOLVER_H_ diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 89c34336..9baa9bea 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -128,6 +128,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(SH(new BooleanOptionHandler(PREF_BT_REQUIRE_CRYPTO))); handlers.push_back(SH(new CumulativeOptionHandler(PREF_HEADER, "\n"))); handlers.push_back(SH(new BooleanOptionHandler(PREF_QUIET))); +#ifdef ENABLE_ASYNC_DNS + handlers.push_back(SH(new BooleanOptionHandler(PREF_ASYNC_DNS))); +#endif // ENABLE_ASYNC_DNS return handlers; } diff --git a/src/SocketCore.cc b/src/SocketCore.cc index 76f00d4c..b5ddf701 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -38,6 +38,7 @@ #include "DlRetryEx.h" #include "DlAbortEx.h" #include "StringFormat.h" +#include "Util.h" #include #include #include @@ -169,20 +170,6 @@ SocketCore* SocketCore::acceptConnection() const return new SocketCore(fd, _sockType); } -std::pair -SocketCore::getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len) -{ - char host[NI_MAXHOST]; - char service[NI_MAXSERV]; - int s = getnameinfo(sockaddr, len, host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICHOST|NI_NUMERICSERV); - if(s != 0) { - throw DlAbortEx(StringFormat("Failed to get hostname and port. cause: %s", - gai_strerror(s)).str()); - } - return std::pair(host, atoi(service)); // TODO -} - void SocketCore::getAddrInfo(std::pair& addrinfo) const { struct sockaddr_storage sockaddr; @@ -191,7 +178,7 @@ void SocketCore::getAddrInfo(std::pair& addrinfo) const if(getsockname(sockfd, addrp, &len) == -1) { throw DlAbortEx(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); } - addrinfo = SocketCore::getNameInfoInNumeric(addrp, len); + addrinfo = Util::getNumericNameInfo(addrp, len); } void SocketCore::getPeerInfo(std::pair& peerinfo) const @@ -202,7 +189,7 @@ void SocketCore::getPeerInfo(std::pair& peerinfo) const if(getpeername(sockfd, addrp, &len) == -1) { throw DlAbortEx(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); } - peerinfo = SocketCore::getNameInfoInNumeric(addrp, len); + peerinfo = Util::getNumericNameInfo(addrp, len); } void SocketCore::establishConnection(const std::string& host, uint16_t port) @@ -679,7 +666,7 @@ ssize_t SocketCore::readDataFrom(char* data, size_t len, if(r == -1) { throw DlAbortEx(StringFormat(EX_SOCKET_RECV, errorMsg()).str()); } - sender = SocketCore::getNameInfoInNumeric(addrp, sockaddrlen); + sender = Util::getNumericNameInfo(addrp, sockaddrlen); return r; } diff --git a/src/SocketCore.h b/src/SocketCore.h index e7222538..7d605de6 100644 --- a/src/SocketCore.h +++ b/src/SocketCore.h @@ -87,9 +87,6 @@ private: static int error(); static const char *errorMsg(); static const char *errorMsg(const int err); - - static std::pair - getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len); public: SocketCore(int sockType = SOCK_STREAM); ~SocketCore(); diff --git a/src/Util.cc b/src/Util.cc index 106dae57..46e2a928 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -858,4 +858,18 @@ void* Util::allocateAlignedMemory(size_t alignment, size_t size) } #endif // HAVE_POSIX_MEMALIGN +std::pair +Util::getNumericNameInfo(const struct sockaddr* sockaddr, socklen_t len) +{ + char host[NI_MAXHOST]; + char service[NI_MAXSERV]; + int s = getnameinfo(sockaddr, len, host, NI_MAXHOST, service, NI_MAXSERV, + NI_NUMERICHOST|NI_NUMERICSERV); + if(s != 0) { + throw DlAbortEx(StringFormat("Failed to get hostname and port. cause: %s", + gai_strerror(s)).str()); + } + return std::pair(host, atoi(service)); // TODO +} + } // namespace aria2 diff --git a/src/Util.h b/src/Util.h index a9422575..25ba6abe 100644 --- a/src/Util.h +++ b/src/Util.h @@ -39,6 +39,7 @@ #include "SharedHandle.h" #include "IntSequence.h" #include "a2time.h" +#include "a2netcompat.h" #include #include #include @@ -236,6 +237,9 @@ public: #ifdef HAVE_POSIX_MEMALIGN static void* allocateAlignedMemory(size_t alignment, size_t size); #endif // HAVE_POSIX_MEMALIGN + + static std::pair + getNumericNameInfo(const struct sockaddr* sockaddr, socklen_t len); }; } // namespace aria2 diff --git a/src/option_processing.cc b/src/option_processing.cc index 4a97ddd3..234f9581 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -144,6 +144,11 @@ Option* createDefaultOption() op->put(PREF_BT_REQUIRE_CRYPTO, V_FALSE); op->put(PREF_QUIET, V_FALSE); op->put(PREF_STOP, "0"); +#ifdef ENABLE_ASYNC_DNS + op->put(PREF_ASYNC_DNS, V_TRUE); +#else + op->put(PREF_ASYNC_DNS, V_FALSE); +#endif // ENABLE_ASYNC_DNS return op; } @@ -215,6 +220,9 @@ Option* option_processing(int argc, char* const argv[]) { PREF_STOP, required_argument, &lopt, 214 }, { PREF_HEADER, required_argument, &lopt, 215 }, { PREF_QUIET, optional_argument, 0, 'q' }, +#ifdef ENABLE_ASYNC_DNS + { PREF_ASYNC_DNS, optional_argument, &lopt, 216 }, +#endif // ENABLE_ASYNC_DNS #if defined ENABLE_BITTORRENT || ENABLE_METALINK { PREF_SHOW_FILES, no_argument, NULL, 'S' }, { PREF_SELECT_FILE, required_argument, &lopt, 21 }, @@ -416,6 +424,11 @@ Option* option_processing(int argc, char* const argv[]) case 215: cmdstream << PREF_HEADER << "=" << optarg << "\n"; break; +#ifdef ENABLE_ASYNC_DNS + case 216: + cmdstream << PREF_ASYNC_DNS << "=" << toBoolArg(optarg) << "\n"; + break; +#endif // ENABLE_ASYNC_DNS } break; } diff --git a/src/prefs.h b/src/prefs.h index 66e034ff..7515b18b 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -128,6 +128,8 @@ #define PREF_STOP "stop" // value: true | false #define PREF_QUIET "quiet" +// value: true | false +#define PREF_ASYNC_DNS "async-dns" /** * FTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 6d712354..128bb06e 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -336,3 +336,5 @@ _(" --header=HEADER Append HEADER to HTTP request header. You can u " http://host/file") #define TEXT_QUIET \ _(" -q, --quiet[=true|false] Make aria2 quite (no console output).") +#define TEXT_ASYNC_DNS \ +_(" --async-dns[=true|false] Enable asynchronous DNS.")