summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-05-08 11:18:36 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-05-08 11:18:36 +0000
commitd52bce74d3a40d75dcfa3496e67abbed9f1fcba8 (patch)
tree09c82779bd07f661340800db790e68fe612ca56c
parentd8f911b5815f2f6857b1c0035182391e5d6ecaf5 (diff)
2008-05-08 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
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
-rw-r--r--ChangeLog35
-rw-r--r--src/AbstractCommand.cc99
-rw-r--r--src/AbstractCommand.h32
-rw-r--r--src/AsyncNameResolver.cc137
-rw-r--r--src/AsyncNameResolver.h103
-rw-r--r--src/DHTEntryPointNameResolveCommand.cc120
-rw-r--r--src/DHTEntryPointNameResolveCommand.h16
-rw-r--r--src/DownloadEngine.cc63
-rw-r--r--src/DownloadEngine.h28
-rw-r--r--src/FtpInitiateConnectionCommand.cc77
-rw-r--r--src/FtpInitiateConnectionCommand.h16
-rw-r--r--src/HelpItemFactory.cc7
-rw-r--r--src/HttpInitiateConnectionCommand.cc73
-rw-r--r--src/HttpInitiateConnectionCommand.h24
-rw-r--r--src/InitiateConnectionCommand.cc109
-rw-r--r--src/InitiateConnectionCommand.h66
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.in76
-rw-r--r--src/NameResolver.cc101
-rw-r--r--src/NameResolver.h104
-rw-r--r--src/OptionHandlerFactory.cc3
-rw-r--r--src/SocketCore.cc21
-rw-r--r--src/SocketCore.h3
-rw-r--r--src/Util.cc14
-rw-r--r--src/Util.h4
-rw-r--r--src/option_processing.cc13
-rw-r--r--src/prefs.h2
-rw-r--r--src/usage_text.h2
28 files changed, 838 insertions, 517 deletions
diff --git a/ChangeLog b/ChangeLog
index d82d5b0c..aa1e8c26 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2008-05-08 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+
+ 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 <tujikawa at rednoah dot com>
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<Request>& 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<std::string>& AbstractCommand::getResolvedAddresses()
+{
+ return _asyncNameResolver->getResolvedAddresses();
+}
+
+void AbstractCommand::setNameResolverCheck
+(const SharedHandle<AsyncNameResolver>& resolver) {
+ if(!resolver.isNull()) {
+ nameResolverCheck = true;
+ e->addNameResolverCheck(resolver, this);
+ }
}
-void AbstractCommand::disableNameResolverCheck(const NameResolverHandle& resolver) {
- nameResolverCheck = false;
- e->deleteNameResolverCheck(resolver, this);
+void AbstractCommand::disableNameResolverCheck
+(const SharedHandle<AsyncNameResolver>& 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<SocketCore> socket;
std::deque<SharedHandle<Segment> > _segments;
+#ifdef ENABLE_ASYNC_DNS
+ SharedHandle<AsyncNameResolver> _asyncNameResolver;
+
+ bool isAsyncNameResolverInitialized() const;
+
+ void initAsyncNameResolver(const std::string& hostname);
+
+ bool asyncResolveHostname();
+
+ const std::deque<std::string>& 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<SocketCore>& socket);
void disableReadCheckSocket();
void disableWriteCheckSocket();
- bool resolveHostname(const std::string& hostname,
- const SharedHandle<NameResolver>& nameResolver);
-#ifdef ENABLE_ASYNC_DNS
- void setNameResolverCheck(const SharedHandle<NameResolver>& resolver);
- void disableNameResolverCheck(const SharedHandle<NameResolver>& 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<SocketCore> writeCheckTarget;
bool nameResolverCheck;
+#ifdef ENABLE_ASYNC_DNS
+
+ void setNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
+
+ void disableNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
+ bool nameResolveFinished() const;
+
+#endif // ENABLE_ASYNC_DNS
public:
AbstractCommand(int32_t cuid, const SharedHandle<Request>& 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 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "AsyncNameResolver.h"
+#include "Util.h"
+#include <cstring>
+
+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<AsyncNameResolver*>(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<struct in_addr*>(*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<std::string>& 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 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_ASYNC_NAME_RESOLVER_H_
+#define _D_ASYNC_NAME_RESOLVER_H_
+
+#include "common.h"
+#include "SharedHandle.h"
+#include "a2netcompat.h"
+#include <string>
+#include <deque>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <ares.h>
+#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<std::string> _resolvedAddresses;
+ std::string error;
+ std::string _hostname;
+public:
+ AsyncNameResolver();
+
+ ~AsyncNameResolver();
+
+ void resolve(const std::string& name);
+
+ const std::deque<std::string>& 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<std::pair<std::string, uint16_t> >& 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<std::string, uint16_t> 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<std::string, uint16_t> 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<std::string> addrs(res.resolve(hostname));
+
+ std::pair<std::string, uint16_t> 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::pair<std::string, u
_taskQueue->addPeriodicTask1(_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<AsyncNameResolver>& 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<NameResolver>& resolver) {
+void DHTEntryPointNameResolveCommand::setNameResolverCheck
+(const SharedHandle<AsyncNameResolver>& resolver)
+{
_e->addNameResolverCheck(resolver, this);
}
-void DHTEntryPointNameResolveCommand::disableNameResolverCheck(const SharedHandle<NameResolver>& resolver) {
+void DHTEntryPointNameResolveCommand::disableNameResolverCheck
+(const SharedHandle<AsyncNameResolver>& 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<NameResolver> _resolver;
+#ifdef ENABLE_ASYNC_DNS
+ SharedHandle<AsyncNameResolver> _resolver;
+#endif // ENABLE_ASYNC_DNS
SharedHandle<DHTTaskQueue> _taskQueue;
@@ -71,12 +75,14 @@ private:
void addPingTask(const std::pair<std::string, uint16_t>& addr);
+#ifdef ENABLE_ASYNC_DNS
bool resolveHostname(const std::string& hostname,
- const SharedHandle<NameResolver>& resolver);
+ const SharedHandle<AsyncNameResolver>& resolver);
- void setNameResolverCheck(const SharedHandle<NameResolver>& resolver);
+ void setNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
- void disableNameResolverCheck(const SharedHandle<NameResolver>& resolver);
+ void disableNameResolverCheck(const SharedHandle<AsyncNameResolver>& 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<AsyncNameResolver>& 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<AsyncNameResolver>& 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<AsyncNameResolver>& 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<SocketCore>
+DownloadEngine::popPooledSocket
+(const std::deque<std::string>& ipaddrs, uint16_t port)
+{
+ for(std::deque<std::string>::const_iterator i = ipaddrs.begin();
+ i != ipaddrs.end(); ++i) {
+ SharedHandle<SocketCore> s = popPooledSocket(*i, port);
+ if(!s.isNull()) {
+ return s;
+ }
+ }
+ return SharedHandle<SocketCore>();
+}
+
} // 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 <deque>
#include <map>
-#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<SocketEntry> SocketEntries;
#ifdef ENABLE_ASYNC_DNS
-class NameResolverEntry {
+class AsyncNameResolverEntry {
public:
- SharedHandle<NameResolver> nameResolver;
+ SharedHandle<AsyncNameResolver> nameResolver;
Command* command;
public:
- NameResolverEntry(const SharedHandle<NameResolver>& nameResolver,
- Command* command);
+ AsyncNameResolverEntry(const SharedHandle<AsyncNameResolver>& nameResolver,
+ Command* command);
- bool operator==(const NameResolverEntry& entry);
+ bool operator==(const AsyncNameResolverEntry& entry);
};
-typedef std::deque<NameResolverEntry> NameResolverEntries;
+typedef std::deque<AsyncNameResolverEntry> 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<SocketCore>& socket,
Command* command);
#ifdef ENABLE_ASYNC_DNS
- bool addNameResolverCheck(const SharedHandle<NameResolver>& resolver,
+ bool addNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver,
Command* command);
- bool deleteNameResolverCheck(const SharedHandle<NameResolver>& resolver,
+ bool deleteNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver,
Command* command);
#endif // ENABLE_ASYNC_DNS
@@ -180,6 +182,10 @@ public:
SharedHandle<SocketCore> popPooledSocket(const std::string& ipaddr,
uint16_t port);
+
+
+ SharedHandle<SocketCore>
+ popPooledSocket(const std::deque<std::string>& ipaddrs, uint16_t port);
};
typedef SharedHandle<DownloadEngine> 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())
-{
- setTimeout(e->option->getAsInt(PREF_DNS_TIMEOUT));
- setStatus(Command::STATUS_ONESHOT_REALTIME);
- disableReadCheckSocket();
- disableWriteCheckSocket();
-}
+FtpInitiateConnectionCommand::FtpInitiateConnectionCommand
+(int cuid,
+ const RequestHandle& req,
+ RequestGroup* requestGroup,
+ DownloadEngine* e)
+ :InitiateConnectionCommand(cuid, req, requestGroup, e) {}
-FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {
-#ifdef ENABLE_ASYNC_DNS
- disableNameResolverCheck(nameResolver);
-#endif // ENABLE_ASYNC_DNS
-}
+FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {}
-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* FtpInitiateConnectionCommand::createNextCommand
+(const std::deque<std::string>& resolvedAddresses)
+{
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<HttpConnection> 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;
-}
-
-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;
+ return command;
}
-bool FtpInitiateConnectionCommand::useHttpProxyConnect() const {
- return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL;
+bool FtpInitiateConnectionCommand::useHTTPProxyGet() const {
+ return useHTTPProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET;
}
-#ifdef ENABLE_ASYNC_DNS
-bool FtpInitiateConnectionCommand::nameResolveFinished() const {
- return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS ||
- nameResolver->getStatus() == NameResolver::STATUS_ERROR;
+bool FtpInitiateConnectionCommand::useHTTPProxyConnect() const {
+ return useHTTPProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL;
}
-#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> 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<std::string>& resolvedAddresses);
public:
FtpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& 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())
-{
- setTimeout(e->option->getAsInt(PREF_DNS_TIMEOUT));
- setStatus(Command::STATUS_ONESHOT_REALTIME);
- disableReadCheckSocket();
- disableWriteCheckSocket();
-}
+HttpInitiateConnectionCommand::HttpInitiateConnectionCommand
+(int cuid,
+ const RequestHandle& req,
+ RequestGroup* requestGroup,
+ DownloadEngine* e):
+ InitiateConnectionCommand(cuid, req, requestGroup, e) {}
-HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() {
-#ifdef ENABLE_ASYNC_DNS
- disableNameResolverCheck(nameResolver);
-#endif // ENABLE_ASYNC_DNS
-}
+HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() {}
-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* HttpInitiateConnectionCommand::createNextCommand
+(const std::deque<std::string>& resolvedAddresses)
+{
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<SocketCore> 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;
-}
-
-bool HttpInitiateConnectionCommand::useProxy() {
- return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE;
+ return command;
}
-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> 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<std::string>& resolvedAddresses);
public:
HttpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& 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 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#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<std::string> 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 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#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<std::string>& resolvedAddresses) = 0;
+public:
+ InitiateConnectionCommand(int cuid, const SharedHandle<Request>& 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 <cstring>
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<std::string> 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<std::string> addrs;
+ struct addrinfo* rp;
+ for(rp = res; rp; rp = rp->ai_next) {
+ std::pair<std::string, uint16_t> 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);
-}
-std::string NameResolver::getAddrString() const
-{
- return inet_ntoa(_addr);
+ return addrs;
}
-void NameResolver::setAddr(const std::string& addrString)
+void NameResolver::setSocktype(int socktype)
{
- inet_aton(addrString.c_str(), &_addr);
+ _socktype = socktype;
}
-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 <string>
-
-#ifdef ENABLE_ASYNC_DNS
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <ares.h>
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
-#endif // ENABLE_ASYNC_DNS
+#include <deque>
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<std::string> resolve(const std::string& hostname);
- void reset();
+ // specify SOCK_STREAM or SOCK_DGRAM
+ void setSocktype(int socktype);
};
-#endif // ENABLE_ASYNC_DNS
-
-typedef SharedHandle<NameResolver> 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 <unistd.h>
#include <cerrno>
#include <cstring>
@@ -169,20 +170,6 @@ SocketCore* SocketCore::acceptConnection() const
return new SocketCore(fd, _sockType);
}
-std::pair<std::string, uint16_t>
-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<std::string, uint16_t>(host, atoi(service)); // TODO
-}
-
void SocketCore::getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const
{
struct sockaddr_storage sockaddr;
@@ -191,7 +178,7 @@ void SocketCore::getAddrInfo(std::pair<std::string, uint16_t>& 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<std::string, uint16_t>& peerinfo) const
@@ -202,7 +189,7 @@ void SocketCore::getPeerInfo(std::pair<std::string, uint16_t>& 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<std::string, uint16_t>
- 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<std::string, uint16_t>
+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<std::string, uint16_t>(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 <sys/time.h>
#include <string>
#include <utility>
@@ -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<std::string, uint16_t>
+ 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.")