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
pull/1/head
Tatsuhiro Tsujikawa 2008-05-08 11:18:36 +00:00
parent d8f911b581
commit d52bce74d3
28 changed files with 841 additions and 520 deletions

View File

@ -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> 2008-05-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Updated man page: --quiet, --header were added. Updated man page: --quiet, --header were added.

View File

@ -46,8 +46,9 @@
#include "DownloadFailureException.h" #include "DownloadFailureException.h"
#include "InitiateConnectionCommandFactory.h" #include "InitiateConnectionCommandFactory.h"
#include "SleepCommand.h" #include "SleepCommand.h"
#include "NameResolver.h" #ifdef ENABLE_ASYNC_DNS
#include "DNSCache.h" #include "AsyncNameResolver.h"
#endif // ENABLE_ASYNC_DNS
#include "StreamCheckIntegrityEntry.h" #include "StreamCheckIntegrityEntry.h"
#include "PieceStorage.h" #include "PieceStorage.h"
#include "Socket.h" #include "Socket.h"
@ -57,6 +58,8 @@
namespace aria2 { namespace aria2 {
// TODO $$$$$$$$$$$ fix two nearly identical constructor. $$$$$$$$$$$$$$
// Modify two constructor at the same time!
AbstractCommand::AbstractCommand(int32_t cuid, AbstractCommand::AbstractCommand(int32_t cuid,
const SharedHandle<Request>& req, const SharedHandle<Request>& req,
RequestGroup* requestGroup, RequestGroup* requestGroup,
@ -89,6 +92,9 @@ AbstractCommand::AbstractCommand(int32_t cuid,
AbstractCommand::~AbstractCommand() { AbstractCommand::~AbstractCommand() {
disableReadCheckSocket(); disableReadCheckSocket();
disableWriteCheckSocket(); disableWriteCheckSocket();
#ifdef ENABLE_ASYNC_DNS
disableNameResolverCheck(_asyncNameResolver);
#endif // ENABLE_ASYNC_DNS
_requestGroup->decreaseStreamConnection(); _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 #ifdef ENABLE_ASYNC_DNS
switch(resolver->getStatus()) {
case NameResolver::STATUS_READY: bool AbstractCommand::isAsyncNameResolverInitialized() const
logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); {
resolver->resolve(hostname); return !_asyncNameResolver.isNull();
setNameResolverCheck(resolver); }
return false;
case NameResolver::STATUS_SUCCESS: void AbstractCommand::initAsyncNameResolver(const std::string& hostname)
logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, {
hostname.c_str(), resolver->getAddrString().c_str()); _asyncNameResolver.reset(new AsyncNameResolver());
DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str());
return true; _asyncNameResolver->resolve(hostname);
break; setNameResolverCheck(_asyncNameResolver);
case NameResolver::STATUS_ERROR: }
throw DlAbortEx(StringFormat(MSG_NAME_RESOLUTION_FAILED, cuid,
hostname.c_str(), bool AbstractCommand::asyncResolveHostname()
resolver->getError().c_str()).str()); {
default: switch(_asyncNameResolver->getStatus()) {
return false; case AsyncNameResolver::STATUS_SUCCESS:
}
#else
logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str());
resolver->resolve(hostname);
logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid,
hostname.c_str(), resolver->getAddrString().c_str()); _asyncNameResolver->getHostname().c_str(),
DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); _asyncNameResolver->getResolvedAddresses().front().c_str());
return true;
#endif // ENABLE_ASYNC_DNS
} else {
logger->info(MSG_DNS_CACHE_HIT, cuid,
hostname.c_str(), ipaddr.c_str());
resolver->setAddr(ipaddr);
return true; 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 const std::deque<std::string>& AbstractCommand::getResolvedAddresses()
void AbstractCommand::setNameResolverCheck(const NameResolverHandle& resolver) { {
nameResolverCheck = true; return _asyncNameResolver->getResolvedAddresses();
e->addNameResolverCheck(resolver, this);
} }
void AbstractCommand::disableNameResolverCheck(const NameResolverHandle& resolver) { void AbstractCommand::setNameResolverCheck
nameResolverCheck = false; (const SharedHandle<AsyncNameResolver>& resolver) {
e->deleteNameResolverCheck(resolver, this); if(!resolver.isNull()) {
nameResolverCheck = true;
e->addNameResolverCheck(resolver, this);
}
}
void AbstractCommand::disableNameResolverCheck
(const SharedHandle<AsyncNameResolver>& resolver) {
if(!resolver.isNull()) {
nameResolverCheck = false;
e->deleteNameResolverCheck(resolver, this);
}
} }
bool AbstractCommand::nameResolveFinished() const { bool AbstractCommand::nameResolveFinished() const {
return false; return
_asyncNameResolver->getStatus() == AsyncNameResolver::STATUS_SUCCESS ||
_asyncNameResolver->getStatus() == AsyncNameResolver::STATUS_ERROR;
} }
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS

View File

@ -46,9 +46,11 @@ class Request;
class DownloadEngine; class DownloadEngine;
class RequestGroup; class RequestGroup;
class Segment; class Segment;
class NameResolver;
class Exception; class Exception;
class SocketCore; class SocketCore;
#ifdef ENABLE_ASYNC_DNS
class AsyncNameResolver;
#endif // ENABLE_ASYNC_DNS
class AbstractCommand : public Command, public RequestGroupAware { class AbstractCommand : public Command, public RequestGroupAware {
private: private:
@ -60,6 +62,18 @@ protected:
SharedHandle<SocketCore> socket; SharedHandle<SocketCore> socket;
std::deque<SharedHandle<Segment> > _segments; 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(); void tryReserved();
virtual bool prepareForRetry(time_t wait); virtual bool prepareForRetry(time_t wait);
virtual void onAbort(); virtual void onAbort();
@ -69,13 +83,7 @@ protected:
void setWriteCheckSocket(const SharedHandle<SocketCore>& socket); void setWriteCheckSocket(const SharedHandle<SocketCore>& socket);
void disableReadCheckSocket(); void disableReadCheckSocket();
void disableWriteCheckSocket(); 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 setTimeout(time_t timeout) { this->timeout = timeout; }
void prepareForNextAction(Command* nextCommand = 0); void prepareForNextAction(Command* nextCommand = 0);
@ -87,6 +95,14 @@ private:
SharedHandle<SocketCore> writeCheckTarget; SharedHandle<SocketCore> writeCheckTarget;
bool nameResolverCheck; 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: public:
AbstractCommand(int32_t cuid, const SharedHandle<Request>& req, AbstractCommand(int32_t cuid, const SharedHandle<Request>& req,
RequestGroup* requestGroup, DownloadEngine* e, RequestGroup* requestGroup, DownloadEngine* e,

137
src/AsyncNameResolver.cc Normal file
View File

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

103
src/AsyncNameResolver.h Normal file
View File

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

View File

@ -34,8 +34,10 @@
/* copyright --> */ /* copyright --> */
#include "DHTEntryPointNameResolveCommand.h" #include "DHTEntryPointNameResolveCommand.h"
#include "DownloadEngine.h" #include "DownloadEngine.h"
#ifdef ENABLE_ASYNC_DNS
#include "AsyncNameResolver.h"
#endif // ENABLE_ASYNC_DNS
#include "NameResolver.h" #include "NameResolver.h"
#include "DNSCache.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "prefs.h" #include "prefs.h"
#include "message.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): DHTEntryPointNameResolveCommand::DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e, const std::deque<std::pair<std::string, uint16_t> >& entryPoints):
Command(cuid), Command(cuid),
_e(e), _e(e),
_resolver(new NameResolver()),
_entryPoints(entryPoints), _entryPoints(entryPoints),
_bootstrapEnabled(false) _bootstrapEnabled(false)
{} {}
@ -72,37 +73,53 @@ bool DHTEntryPointNameResolveCommand::execute()
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) { if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true; return true;
} }
#ifdef ENABLE_ASYNC_DNS
if(_resolver.isNull()) {
_resolver.reset(new AsyncNameResolver());
}
#endif // ENABLE_ASYNC_DNS
try { try {
while(_entryPoints.size()) { #ifdef ENABLE_ASYNC_DNS
std::string hostname = _entryPoints.front().first; if(_e->option->getAsBool(PREF_ASYNC_DNS)) {
try { while(_entryPoints.size()) {
if(Util::isNumbersAndDotsNotation(hostname)) { std::string hostname = _entryPoints.front().first;
std::pair<std::string, uint16_t> p(hostname, try {
_entryPoints.front().second);
_resolvedEntryPoints.push_back(p);
_entryPoints.erase(_entryPoints.begin());
addPingTask(p);
} else {
if(resolveHostname(hostname, _resolver)) { if(resolveHostname(hostname, _resolver)) {
hostname = _resolver->getAddrString(); hostname = _resolver->getResolvedAddresses().front();
_resolver->reset();
std::pair<std::string, uint16_t> p(hostname, std::pair<std::string, uint16_t> p(hostname,
_entryPoints.front().second); _entryPoints.front().second);
_resolvedEntryPoints.push_back(p); _resolvedEntryPoints.push_back(p);
_entryPoints.erase(_entryPoints.begin());
addPingTask(p); addPingTask(p);
} else { } else {
_e->commands.push_back(this); _e->commands.push_back(this);
return false; 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(); _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()) { if(_bootstrapEnabled && _resolvedEntryPoints.size()) {
_taskQueue->addPeriodicTask1(_taskFactory->createNodeLookupTask(_localNode->getID())); _taskQueue->addPeriodicTask1(_taskFactory->createNodeLookupTask(_localNode->getID()));
_taskQueue->addPeriodicTask1(_taskFactory->createBucketRefreshTask()); _taskQueue->addPeriodicTask1(_taskFactory->createBucketRefreshTask());
@ -122,54 +139,43 @@ void DHTEntryPointNameResolveCommand::addPingTask(const std::pair<std::string, u
_taskQueue->addPeriodicTask1(_taskFactory->createPingTask(entryNode, 10)); _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 #ifdef ENABLE_ASYNC_DNS
switch(resolver->getStatus()) {
case NameResolver::STATUS_READY: bool DHTEntryPointNameResolveCommand::resolveHostname
logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str()); (const std::string& hostname,
resolver->resolve(hostname); const SharedHandle<AsyncNameResolver>& resolver)
setNameResolverCheck(resolver); {
return false; switch(resolver->getStatus()) {
case NameResolver::STATUS_SUCCESS: case AsyncNameResolver::STATUS_READY:
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()); logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str());
resolver->resolve(hostname); resolver->resolve(hostname);
setNameResolverCheck(resolver);
return false;
case AsyncNameResolver::STATUS_SUCCESS:
logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid, logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid,
hostname.c_str(), resolver->getAddrString().c_str()); resolver->getHostname().c_str(),
DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString()); resolver->getResolvedAddresses().front().c_str());
return true;
#endif // ENABLE_ASYNC_DNS
} else {
logger->info(MSG_DNS_CACHE_HIT, cuid,
hostname.c_str(), ipaddr.c_str());
resolver->setAddr(ipaddr);
return true; 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
void DHTEntryPointNameResolveCommand::setNameResolverCheck(const SharedHandle<NameResolver>& resolver) { (const SharedHandle<AsyncNameResolver>& resolver)
{
_e->addNameResolverCheck(resolver, this); _e->addNameResolverCheck(resolver, this);
} }
void DHTEntryPointNameResolveCommand::disableNameResolverCheck(const SharedHandle<NameResolver>& resolver) { void DHTEntryPointNameResolveCommand::disableNameResolverCheck
(const SharedHandle<AsyncNameResolver>& resolver)
{
_e->deleteNameResolverCheck(resolver, this); _e->deleteNameResolverCheck(resolver, this);
} }
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS

View File

@ -47,13 +47,17 @@ class DHTTaskFactory;
class DHTRoutingTable; class DHTRoutingTable;
class DHTNode; class DHTNode;
class DownloadEngine; class DownloadEngine;
class NameResolver; #ifdef ENABLE_ASYNC_DNS
class AsyncNameResolver;
#endif // ENABLE_ASYNC_DNS
class DHTEntryPointNameResolveCommand:public Command { class DHTEntryPointNameResolveCommand:public Command {
protected: protected:
DownloadEngine* _e; DownloadEngine* _e;
private: private:
SharedHandle<NameResolver> _resolver; #ifdef ENABLE_ASYNC_DNS
SharedHandle<AsyncNameResolver> _resolver;
#endif // ENABLE_ASYNC_DNS
SharedHandle<DHTTaskQueue> _taskQueue; SharedHandle<DHTTaskQueue> _taskQueue;
@ -71,12 +75,14 @@ private:
void addPingTask(const std::pair<std::string, uint16_t>& addr); void addPingTask(const std::pair<std::string, uint16_t>& addr);
#ifdef ENABLE_ASYNC_DNS
bool resolveHostname(const std::string& hostname, 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: public:
DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e, DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e,

View File

@ -33,7 +33,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "NameResolver.h" #ifdef ENABLE_ASYNC_DNS
#include "AsyncNameResolver.h"
#endif // ENABLE_ASYNC_DNS
#include "StatCalc.h" #include "StatCalc.h"
#include "RequestGroup.h" #include "RequestGroup.h"
#include "RequestGroupMan.h" #include "RequestGroupMan.h"
@ -73,11 +75,12 @@ bool SocketEntry::operator==(const SocketEntry& entry)
} }
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
NameResolverEntry::NameResolverEntry(const NameResolverHandle& nameResolver, AsyncNameResolverEntry::AsyncNameResolverEntry
Command* command): (const SharedHandle<AsyncNameResolver>& nameResolver,
Command* command):
nameResolver(nameResolver), command(command) {} nameResolver(nameResolver), command(command) {}
bool NameResolverEntry::operator==(const NameResolverEntry& entry) bool AsyncNameResolverEntry::operator==(const AsyncNameResolverEntry& entry)
{ {
return nameResolver == entry.nameResolver && return nameResolver == entry.nameResolver &&
command == entry.command; command == entry.command;
@ -164,9 +167,9 @@ void DownloadEngine::waitData() {
memcpy(&wfds, &wfdset, sizeof(fd_set)); memcpy(&wfds, &wfdset, sizeof(fd_set));
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
for(NameResolverEntries::iterator itr = nameResolverEntries.begin(); for(AsyncNameResolverEntries::iterator itr = nameResolverEntries.begin();
itr != nameResolverEntries.end(); ++itr) { itr != nameResolverEntries.end(); ++itr) {
NameResolverEntry& entry = *itr; AsyncNameResolverEntry& entry = *itr;
int fd = entry.nameResolver->getFds(&rfds, &wfds); int fd = entry.nameResolver->getFds(&rfds, &wfds);
// TODO force error if fd == 0 // TODO force error if fd == 0
if(fdmax < fd) { if(fdmax < fd) {
@ -189,13 +192,13 @@ void DownloadEngine::waitData() {
} }
} }
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
for(NameResolverEntries::iterator itr = nameResolverEntries.begin(); for(AsyncNameResolverEntries::iterator itr = nameResolverEntries.begin();
itr != nameResolverEntries.end(); ++itr) { itr != nameResolverEntries.end(); ++itr) {
NameResolverEntry& entry = *itr; AsyncNameResolverEntry& entry = *itr;
entry.nameResolver->process(&rfds, &wfds); entry.nameResolver->process(&rfds, &wfds);
switch(entry.nameResolver->getStatus()) { switch(entry.nameResolver->getStatus()) {
case NameResolver::STATUS_SUCCESS: case AsyncNameResolver::STATUS_SUCCESS:
case NameResolver::STATUS_ERROR: case AsyncNameResolver::STATUS_ERROR:
entry.command->setStatusActive(); entry.command->setStatusActive();
break; break;
default: default:
@ -323,12 +326,13 @@ void DownloadEngine::addCommand(const Commands& commands)
} }
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver, bool DownloadEngine::addNameResolverCheck
Command* command) { (const SharedHandle<AsyncNameResolver>& resolver,
NameResolverEntry entry(resolver, command); Command* command)
NameResolverEntries::iterator itr = std::find(nameResolverEntries.begin(), {
nameResolverEntries.end(), AsyncNameResolverEntry entry(resolver, command);
entry); AsyncNameResolverEntries::iterator itr =
std::find(nameResolverEntries.begin(), nameResolverEntries.end(), entry);
if(itr == nameResolverEntries.end()) { if(itr == nameResolverEntries.end()) {
nameResolverEntries.push_back(entry); nameResolverEntries.push_back(entry);
return true; return true;
@ -337,12 +341,13 @@ bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
} }
} }
bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver, bool DownloadEngine::deleteNameResolverCheck
Command* command) { (const SharedHandle<AsyncNameResolver>& resolver,
NameResolverEntry entry(resolver, command); Command* command)
NameResolverEntries::iterator itr = std::find(nameResolverEntries.begin(), {
nameResolverEntries.end(), AsyncNameResolverEntry entry(resolver, command);
entry); AsyncNameResolverEntries::iterator itr =
std::find(nameResolverEntries.begin(), nameResolverEntries.end(), entry);
if(itr == nameResolverEntries.end()) { if(itr == nameResolverEntries.end()) {
return false; return false;
} else { } 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 } // namespace aria2

View File

@ -38,15 +38,17 @@
#include "common.h" #include "common.h"
#include "SharedHandle.h" #include "SharedHandle.h"
#include "Command.h" #include "Command.h"
#include "a2netcompat.h"
#include <deque> #include <deque>
#include <map> #include <map>
#include "a2netcompat.h"
namespace aria2 { namespace aria2 {
class Logger; class Logger;
class Option; class Option;
class NameResolver; #ifdef ENABLE_ASYNC_DNS
class AsyncNameResolver;
#endif // ENABLE_ASYNC_DNS
class RequestGroupMan; class RequestGroupMan;
class FileAllocationMan; class FileAllocationMan;
class StatCalc; class StatCalc;
@ -74,18 +76,18 @@ public:
typedef std::deque<SocketEntry> SocketEntries; typedef std::deque<SocketEntry> SocketEntries;
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
class NameResolverEntry { class AsyncNameResolverEntry {
public: public:
SharedHandle<NameResolver> nameResolver; SharedHandle<AsyncNameResolver> nameResolver;
Command* command; Command* command;
public: public:
NameResolverEntry(const SharedHandle<NameResolver>& nameResolver, AsyncNameResolverEntry(const SharedHandle<AsyncNameResolver>& nameResolver,
Command* command); 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 #endif // ENABLE_ASYNC_DNS
class DownloadEngine { class DownloadEngine {
@ -93,7 +95,7 @@ private:
void waitData(); void waitData();
SocketEntries socketEntries; SocketEntries socketEntries;
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
NameResolverEntries nameResolverEntries; AsyncNameResolverEntries nameResolverEntries;
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
fd_set rfdset; fd_set rfdset;
fd_set wfdset; fd_set wfdset;
@ -152,9 +154,9 @@ public:
bool deleteSocketForWriteCheck(const SharedHandle<SocketCore>& socket, bool deleteSocketForWriteCheck(const SharedHandle<SocketCore>& socket,
Command* command); Command* command);
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
bool addNameResolverCheck(const SharedHandle<NameResolver>& resolver, bool addNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver,
Command* command); Command* command);
bool deleteNameResolverCheck(const SharedHandle<NameResolver>& resolver, bool deleteNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver,
Command* command); Command* command);
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
@ -180,6 +182,10 @@ public:
SharedHandle<SocketCore> popPooledSocket(const std::string& ipaddr, SharedHandle<SocketCore> popPooledSocket(const std::string& ipaddr,
uint16_t port); uint16_t port);
SharedHandle<SocketCore>
popPooledSocket(const std::deque<std::string>& ipaddrs, uint16_t port);
}; };
typedef SharedHandle<DownloadEngine> DownloadEngineHandle; typedef SharedHandle<DownloadEngine> DownloadEngineHandle;

View File

@ -33,9 +33,7 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "FtpInitiateConnectionCommand.h" #include "FtpInitiateConnectionCommand.h"
#include "NameResolver.h"
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "RequestGroup.h"
#include "Option.h" #include "Option.h"
#include "Request.h" #include "Request.h"
#include "FtpNegotiationCommand.h" #include "FtpNegotiationCommand.h"
@ -47,58 +45,35 @@
#include "Logger.h" #include "Logger.h"
#include "message.h" #include "message.h"
#include "prefs.h" #include "prefs.h"
#include "Util.h"
#include "HttpConnection.h" #include "HttpConnection.h"
#include "Socket.h" #include "Socket.h"
namespace aria2 { namespace aria2 {
FtpInitiateConnectionCommand::FtpInitiateConnectionCommand(int cuid, FtpInitiateConnectionCommand::FtpInitiateConnectionCommand
const RequestHandle& req, (int cuid,
RequestGroup* requestGroup, const RequestHandle& req,
DownloadEngine* e) RequestGroup* requestGroup,
:AbstractCommand(cuid, req, requestGroup, e), DownloadEngine* e)
nameResolver(new NameResolver()) :InitiateConnectionCommand(cuid, req, requestGroup, e) {}
FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {}
Command* FtpInitiateConnectionCommand::createNextCommand
(const std::deque<std::string>& 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; Command* command;
if(useHttpProxy()) { if(useHTTPProxy()) {
logger->info(MSG_CONNECTING_TO_SERVER, cuid, logger->info(MSG_CONNECTING_TO_SERVER, cuid,
e->option->get(PREF_HTTP_PROXY_HOST).c_str(), e->option->get(PREF_HTTP_PROXY_HOST).c_str(),
e->option->getAsInt(PREF_HTTP_PROXY_PORT)); e->option->getAsInt(PREF_HTTP_PROXY_PORT));
socket->establishConnection(hostname, socket->establishConnection(resolvedAddresses.front(),
e->option->getAsInt(PREF_HTTP_PROXY_PORT)); e->option->getAsInt(PREF_HTTP_PROXY_PORT));
if(useHttpProxyGet()) { if(useHTTPProxyGet()) {
SharedHandle<HttpConnection> hc(new HttpConnection(cuid, socket, e->option)); SharedHandle<HttpConnection> hc(new HttpConnection(cuid, socket, e->option));
command = new HttpRequestCommand(cuid, req, _requestGroup, hc, e, socket); command = new HttpRequestCommand(cuid, req, _requestGroup, hc, e, socket);
} else if(useHttpProxyConnect()) { } else if(useHTTPProxyConnect()) {
command = new FtpTunnelRequestCommand(cuid, req, _requestGroup, e, socket); command = new FtpTunnelRequestCommand(cuid, req, _requestGroup, e, socket);
} else { } else {
// TODO // TODO
@ -107,30 +82,18 @@ bool FtpInitiateConnectionCommand::executeInternal() {
} else { } else {
logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(), logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(),
req->getPort()); req->getPort());
socket->establishConnection(hostname, req->getPort()); socket->establishConnection(resolvedAddresses.front(), req->getPort());
command = new FtpNegotiationCommand(cuid, req, _requestGroup, e, socket); command = new FtpNegotiationCommand(cuid, req, _requestGroup, e, socket);
} }
e->commands.push_back(command); return command;
return true;
} }
bool FtpInitiateConnectionCommand::useHttpProxy() const { bool FtpInitiateConnectionCommand::useHTTPProxyGet() const {
return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; return useHTTPProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET;
} }
bool FtpInitiateConnectionCommand::useHttpProxyGet() const { bool FtpInitiateConnectionCommand::useHTTPProxyConnect() const {
return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET; 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 } // namespace aria2

View File

@ -35,21 +35,17 @@
#ifndef _D_FTP_INITIATE_CONNECTION_COMMAND_H_ #ifndef _D_FTP_INITIATE_CONNECTION_COMMAND_H_
#define _D_FTP_INITIATE_CONNECTION_COMMAND_H_ #define _D_FTP_INITIATE_CONNECTION_COMMAND_H_
#include "AbstractCommand.h" #include "InitiateConnectionCommand.h"
namespace aria2 { namespace aria2 {
class FtpInitiateConnectionCommand : public AbstractCommand { class FtpInitiateConnectionCommand : public InitiateConnectionCommand {
private: private:
SharedHandle<NameResolver> nameResolver; bool useHTTPProxyGet() const;
bool useHttpProxy() const; bool useHTTPProxyConnect() const;
bool useHttpProxyGet() const;
bool useHttpProxyConnect() const;
#ifdef ENABLE_ASYNC_DNS
virtual bool nameResolveFinished() const;
#endif // ENABLE_ASYNC_DNS
protected: protected:
virtual bool executeInternal(); virtual Command* createNextCommand
(const std::deque<std::string>& resolvedAddresses);
public: public:
FtpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& req, FtpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& req,
RequestGroup* requestGroup, DownloadEngine* e); RequestGroup* requestGroup, DownloadEngine* e);

View File

@ -458,6 +458,13 @@ TagContainerHandle HelpItemFactory::createHelpItems(const Option* op)
item->addTag(TAG_ADVANCED); item->addTag(TAG_ADVANCED);
tc->addItem(item); 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)); HelpItemHandle item(new HelpItem("help", TEXT_HELP, TAG_BASIC));
item->setAvailableValues item->setAvailableValues

View File

@ -33,7 +33,6 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "HttpInitiateConnectionCommand.h" #include "HttpInitiateConnectionCommand.h"
#include "NameResolver.h"
#include "Request.h" #include "Request.h"
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "HttpConnection.h" #include "HttpConnection.h"
@ -43,7 +42,6 @@
#include "HttpProxyRequestCommand.h" #include "HttpProxyRequestCommand.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "Option.h" #include "Option.h"
#include "Util.h"
#include "Logger.h" #include "Logger.h"
#include "Socket.h" #include "Socket.h"
#include "message.h" #include "message.h"
@ -51,46 +49,24 @@
namespace aria2 { namespace aria2 {
HttpInitiateConnectionCommand::HttpInitiateConnectionCommand(int cuid, HttpInitiateConnectionCommand::HttpInitiateConnectionCommand
const RequestHandle& req, (int cuid,
RequestGroup* requestGroup, const RequestHandle& req,
DownloadEngine* e): RequestGroup* requestGroup,
AbstractCommand(cuid, req, requestGroup, e), DownloadEngine* e):
nameResolver(new NameResolver()) InitiateConnectionCommand(cuid, req, requestGroup, e) {}
HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() {}
Command* HttpInitiateConnectionCommand::createNextCommand
(const std::deque<std::string>& 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; Command* command;
if(useProxy()) { if(useHTTPProxy()) {
logger->info(MSG_CONNECTING_TO_SERVER, cuid, logger->info(MSG_CONNECTING_TO_SERVER, cuid,
e->option->get(PREF_HTTP_PROXY_HOST).c_str(), e->option->get(PREF_HTTP_PROXY_HOST).c_str(),
e->option->getAsInt(PREF_HTTP_PROXY_PORT)); e->option->getAsInt(PREF_HTTP_PROXY_PORT));
socket->establishConnection(hostname, socket->establishConnection(resolvedAddresses.front(),
e->option->getAsInt(PREF_HTTP_PROXY_PORT)); e->option->getAsInt(PREF_HTTP_PROXY_PORT));
if(useProxyTunnel()) { if(useProxyTunnel()) {
command = new HttpProxyRequestCommand(cuid, req, _requestGroup, e, socket); command = new HttpProxyRequestCommand(cuid, req, _requestGroup, e, socket);
@ -104,12 +80,11 @@ bool HttpInitiateConnectionCommand::executeInternal() {
} }
} else { } else {
SharedHandle<SocketCore> pooledSocket = SharedHandle<SocketCore> pooledSocket =
e->popPooledSocket(hostname, req->getPort()); e->popPooledSocket(resolvedAddresses, req->getPort());
if(pooledSocket.isNull()) { if(pooledSocket.isNull()) {
logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(), logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(),
req->getPort()); req->getPort());
socket->establishConnection(hostname, req->getPort()); socket->establishConnection(resolvedAddresses.front(), req->getPort());
} else { } else {
socket = pooledSocket; socket = pooledSocket;
} }
@ -117,27 +92,17 @@ bool HttpInitiateConnectionCommand::executeInternal() {
command = new HttpRequestCommand(cuid, req, _requestGroup, httpConnection, command = new HttpRequestCommand(cuid, req, _requestGroup, httpConnection,
e, socket); e, socket);
} }
e->commands.push_back(command); return command;
return true;
} }
bool HttpInitiateConnectionCommand::useProxy() { bool HttpInitiateConnectionCommand::useProxyGet() const
return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; {
}
bool HttpInitiateConnectionCommand::useProxyGet() {
return e->option->get(PREF_HTTP_PROXY_METHOD) == V_GET; 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; 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 } // namespace aria2

View File

@ -35,29 +35,17 @@
#ifndef _D_HTTP_INITIATE_CONNECTION_COMMAND_H_ #ifndef _D_HTTP_INITIATE_CONNECTION_COMMAND_H_
#define _D_HTTP_INITIATE_CONNECTION_COMMAND_H_ #define _D_HTTP_INITIATE_CONNECTION_COMMAND_H_
#include "AbstractCommand.h" #include "InitiateConnectionCommand.h"
namespace aria2 { namespace aria2 {
class HttpInitiateConnectionCommand : public AbstractCommand { class HttpInitiateConnectionCommand : public InitiateConnectionCommand {
private: private:
SharedHandle<NameResolver> nameResolver; bool useProxyGet() const;
bool useProxy(); bool useProxyTunnel() const;
bool useProxyGet();
bool useProxyTunnel();
protected: protected:
/** virtual Command* createNextCommand
* Connect to the server. (const std::deque<std::string>& resolvedAddresses);
* 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
public: public:
HttpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& req, HttpInitiateConnectionCommand(int cuid, const SharedHandle<Request>& req,
RequestGroup* requestGroup, RequestGroup* requestGroup,

View File

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

View File

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

View File

@ -184,7 +184,12 @@ SRCS = Socket.h\
ProtocolDetector.cc ProtocolDetector.h\ ProtocolDetector.cc ProtocolDetector.h\
NullStatCalc.h\ NullStatCalc.h\
StringFormat.cc StringFormat.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 if ENABLE_MESSAGE_DIGEST
SRCS += IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ SRCS += IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\

View File

@ -39,7 +39,8 @@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
target_triplet = @target@ target_triplet = @target@
bin_PROGRAMS = aria2c$(EXEEXT) 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@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.cc ChecksumCheckIntegrityEntry.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@ Checksum.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ ChunkChecksum.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@ Data.cc Data.h\
@ENABLE_BITTORRENT_TRUE@ Dictionary.cc Dictionary.h\ @ENABLE_BITTORRENT_TRUE@ Dictionary.cc Dictionary.h\
@ENABLE_BITTORRENT_TRUE@ List.cc List.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@ BtLeecherStateChoke.cc BtLeecherStateChoke.h\
@ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.cc BtSeederStateChoke.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@ MetalinkEntry.cc MetalinkEntry.h\
@ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\
@ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\
@ -253,17 +254,17 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\
@ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h @ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h
@ENABLE_LIBXML2_TRUE@am__append_4 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h @ENABLE_LIBXML2_TRUE@am__append_5 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h
@ENABLE_LIBEXPAT_TRUE@am__append_5 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h @ENABLE_LIBEXPAT_TRUE@am__append_6 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h
@HAVE_BASENAME_FALSE@am__append_6 = libgen.c libgen.h @HAVE_BASENAME_FALSE@am__append_7 = libgen.c libgen.h
@HAVE_GETADDRINFO_FALSE@am__append_7 = getaddrinfo.c getaddrinfo.h @HAVE_GETADDRINFO_FALSE@am__append_8 = getaddrinfo.c getaddrinfo.h
@HAVE_GAI_STRERROR_FALSE@am__append_8 = gai_strerror.c gai_strerror.h @HAVE_GAI_STRERROR_FALSE@am__append_9 = gai_strerror.c gai_strerror.h
@HAVE_GETTIMEOFDAY_FALSE@am__append_9 = gettimeofday.c gettimeofday.h \ @HAVE_GETTIMEOFDAY_FALSE@am__append_10 = gettimeofday.c gettimeofday.h \
@HAVE_GETTIMEOFDAY_FALSE@ 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_INET_ATON_FALSE@am__append_11 = inet_aton.c inet_aton.h
@HAVE_LOCALTIME_R_FALSE@am__append_11 = localtime_r.c localtime_r.h @HAVE_LOCALTIME_R_FALSE@am__append_12 = localtime_r.c localtime_r.h
@HAVE_STRPTIME_FALSE@am__append_12 = strptime.c strptime.h @HAVE_STRPTIME_FALSE@am__append_13 = strptime.c strptime.h
@HAVE_TIMEGM_FALSE@am__append_13 = timegm.c timegm.h @HAVE_TIMEGM_FALSE@am__append_14 = timegm.c timegm.h
subdir = src subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 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 \ usage_text.h ProtocolDetector.cc ProtocolDetector.h \
NullStatCalc.h StringFormat.cc StringFormat.h \ NullStatCalc.h StringFormat.cc StringFormat.h \
HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \ HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \
InitiateConnectionCommand.cc InitiateConnectionCommand.h \
AsyncNameResolver.cc AsyncNameResolver.h \
IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.cc \
IteratableChunkChecksumValidator.h \ IteratableChunkChecksumValidator.h \
IteratableChecksumValidator.cc IteratableChecksumValidator.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 \ getaddrinfo.h gai_strerror.c gai_strerror.h gettimeofday.c \
gettimeofday.h inet_aton.c inet_aton.h localtime_r.c \ gettimeofday.h inet_aton.c inet_aton.h localtime_r.c \
localtime_r.h strptime.c strptime.h timegm.c timegm.h 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@ IteratableChecksumValidator.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(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@ Dictionary.$(OBJEXT) List.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BencodeVisitor.$(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@ MSEHandshake.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.$(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@ MetalinkEntry.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkProcessorFactory.$(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@ Metalink2RequestGroup.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT) @ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT)
@ENABLE_LIBXML2_TRUE@am__objects_4 = \ @ENABLE_LIBXML2_TRUE@am__objects_5 = \
@ENABLE_LIBXML2_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT) @ENABLE_LIBXML2_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT)
@ENABLE_LIBEXPAT_TRUE@am__objects_5 = \ @ENABLE_LIBEXPAT_TRUE@am__objects_6 = \
@ENABLE_LIBEXPAT_TRUE@ ExpatMetalinkProcessor.$(OBJEXT) @ENABLE_LIBEXPAT_TRUE@ ExpatMetalinkProcessor.$(OBJEXT)
@HAVE_BASENAME_FALSE@am__objects_6 = libgen.$(OBJEXT) @HAVE_BASENAME_FALSE@am__objects_7 = libgen.$(OBJEXT)
@HAVE_GETADDRINFO_FALSE@am__objects_7 = getaddrinfo.$(OBJEXT) @HAVE_GETADDRINFO_FALSE@am__objects_8 = getaddrinfo.$(OBJEXT)
@HAVE_GAI_STRERROR_FALSE@am__objects_8 = gai_strerror.$(OBJEXT) @HAVE_GAI_STRERROR_FALSE@am__objects_9 = gai_strerror.$(OBJEXT)
@HAVE_GETTIMEOFDAY_FALSE@am__objects_9 = gettimeofday.$(OBJEXT) \ @HAVE_GETTIMEOFDAY_FALSE@am__objects_10 = gettimeofday.$(OBJEXT) \
@HAVE_GETTIMEOFDAY_FALSE@ gettimeofday.$(OBJEXT) @HAVE_GETTIMEOFDAY_FALSE@ gettimeofday.$(OBJEXT)
@HAVE_INET_ATON_FALSE@am__objects_10 = inet_aton.$(OBJEXT) @HAVE_INET_ATON_FALSE@am__objects_11 = inet_aton.$(OBJEXT)
@HAVE_LOCALTIME_R_FALSE@am__objects_11 = localtime_r.$(OBJEXT) @HAVE_LOCALTIME_R_FALSE@am__objects_12 = localtime_r.$(OBJEXT)
@HAVE_STRPTIME_FALSE@am__objects_12 = strptime.$(OBJEXT) @HAVE_STRPTIME_FALSE@am__objects_13 = strptime.$(OBJEXT)
@HAVE_TIMEGM_FALSE@am__objects_13 = timegm.$(OBJEXT) @HAVE_TIMEGM_FALSE@am__objects_14 = timegm.$(OBJEXT)
am__objects_14 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ am__objects_15 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
AbstractCommand.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \
InitiateConnectionCommandFactory.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \
DownloadCommand.$(OBJEXT) \ DownloadCommand.$(OBJEXT) \
@ -783,12 +787,13 @@ am__objects_14 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
HelpItemFactory.$(OBJEXT) SingleFileDownloadContext.$(OBJEXT) \ HelpItemFactory.$(OBJEXT) SingleFileDownloadContext.$(OBJEXT) \
TimedHaltCommand.$(OBJEXT) ProtocolDetector.$(OBJEXT) \ TimedHaltCommand.$(OBJEXT) ProtocolDetector.$(OBJEXT) \
StringFormat.$(OBJEXT) HttpNullDownloadCommand.$(OBJEXT) \ StringFormat.$(OBJEXT) HttpNullDownloadCommand.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3) \ InitiateConnectionCommand.$(OBJEXT) $(am__objects_1) \
$(am__objects_4) $(am__objects_5) $(am__objects_6) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \
$(am__objects_7) $(am__objects_8) $(am__objects_9) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \
$(am__objects_10) $(am__objects_11) $(am__objects_12) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \
$(am__objects_13) $(am__objects_11) $(am__objects_12) $(am__objects_13) \
am_libaria2c_a_OBJECTS = $(am__objects_14) $(am__objects_14)
am_libaria2c_a_OBJECTS = $(am__objects_15)
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
am__installdirs = "$(DESTDIR)$(bindir)" am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) 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 \ usage_text.h ProtocolDetector.cc ProtocolDetector.h \
NullStatCalc.h StringFormat.cc StringFormat.h \ NullStatCalc.h StringFormat.cc StringFormat.h \
HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \ HttpNullDownloadCommand.cc HttpNullDownloadCommand.h \
InitiateConnectionCommand.cc InitiateConnectionCommand.h \
$(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_4) $(am__append_5) $(am__append_6) \
$(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_7) $(am__append_8) $(am__append_9) \
$(am__append_10) $(am__append_11) $(am__append_12) \ $(am__append_10) $(am__append_11) $(am__append_12) \
$(am__append_13) $(am__append_13) $(am__append_14)
noinst_LIBRARIES = libaria2c.a noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS) libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ 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)/AbstractSingleDiskAdaptor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActivePeerConnectionCommand.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)/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)/AuthConfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactory.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@ @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)/HttpResponse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseCommand.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)/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)/InitiateConnectionCommandFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiatorMSEHandshakeCommand.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidator.Po@am__quote@

View File

@ -36,98 +36,43 @@
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "message.h" #include "message.h"
#include "StringFormat.h" #include "StringFormat.h"
#include "Util.h"
#include <cstring> #include <cstring>
namespace aria2 { namespace aria2 {
#ifdef ENABLE_ASYNC_DNS NameResolver::NameResolver():_socktype(0) {}
#ifdef HAVE_LIBCARES1_5 std::deque<std::string> NameResolver::resolve(const std::string& hostname)
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
{ {
NameResolver* resolverPtr = (NameResolver*)arg; struct addrinfo hints;
#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* res; struct addrinfo* res;
int ec; memset(&hints, 0, sizeof(hints));
if((ec = getaddrinfo(hostname.c_str(), 0, &ai, &res)) != 0) { 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, 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); 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 } // namespace aria2

View File

@ -36,115 +36,23 @@
#define _D_NAME_RESOLVER_H_ #define _D_NAME_RESOLVER_H_
#include "common.h" #include "common.h"
#include "SharedHandle.h"
#include "a2netcompat.h"
#include <string> #include <string>
#include <deque>
#ifdef ENABLE_ASYNC_DNS
#ifdef __cplusplus
extern "C" {
#endif
#include <ares.h>
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif // ENABLE_ASYNC_DNS
namespace aria2 { 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 { class NameResolver {
private: private:
struct in_addr _addr; int _socktype;
public: public:
void resolve(const std::string& hostname); NameResolver();
std::string getAddrString() const; std::deque<std::string> resolve(const std::string& hostname);
void setAddr(const std::string& addrString); // specify SOCK_STREAM or SOCK_DGRAM
void setSocktype(int socktype);
void reset();
}; };
#endif // ENABLE_ASYNC_DNS
typedef SharedHandle<NameResolver> NameResolverHandle;
} // namespace aria2 } // namespace aria2
#endif // _D_NAME_RESOLVER_H_ #endif // _D_NAME_RESOLVER_H_

View File

@ -128,6 +128,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
handlers.push_back(SH(new BooleanOptionHandler(PREF_BT_REQUIRE_CRYPTO))); handlers.push_back(SH(new BooleanOptionHandler(PREF_BT_REQUIRE_CRYPTO)));
handlers.push_back(SH(new CumulativeOptionHandler(PREF_HEADER, "\n"))); handlers.push_back(SH(new CumulativeOptionHandler(PREF_HEADER, "\n")));
handlers.push_back(SH(new BooleanOptionHandler(PREF_QUIET))); 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; return handlers;
} }

View File

@ -38,6 +38,7 @@
#include "DlRetryEx.h" #include "DlRetryEx.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "StringFormat.h" #include "StringFormat.h"
#include "Util.h"
#include <unistd.h> #include <unistd.h>
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
@ -169,20 +170,6 @@ SocketCore* SocketCore::acceptConnection() const
return new SocketCore(fd, _sockType); 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 void SocketCore::getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const
{ {
struct sockaddr_storage sockaddr; 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) { if(getsockname(sockfd, addrp, &len) == -1) {
throw DlAbortEx(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); 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 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) { if(getpeername(sockfd, addrp, &len) == -1) {
throw DlAbortEx(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); 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) 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) { if(r == -1) {
throw DlAbortEx(StringFormat(EX_SOCKET_RECV, errorMsg()).str()); throw DlAbortEx(StringFormat(EX_SOCKET_RECV, errorMsg()).str());
} }
sender = SocketCore::getNameInfoInNumeric(addrp, sockaddrlen); sender = Util::getNumericNameInfo(addrp, sockaddrlen);
return r; return r;
} }

View File

@ -87,9 +87,6 @@ private:
static int error(); static int error();
static const char *errorMsg(); static const char *errorMsg();
static const char *errorMsg(const int err); static const char *errorMsg(const int err);
static std::pair<std::string, uint16_t>
getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len);
public: public:
SocketCore(int sockType = SOCK_STREAM); SocketCore(int sockType = SOCK_STREAM);
~SocketCore(); ~SocketCore();

View File

@ -858,4 +858,18 @@ void* Util::allocateAlignedMemory(size_t alignment, size_t size)
} }
#endif // HAVE_POSIX_MEMALIGN #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 } // namespace aria2

View File

@ -39,6 +39,7 @@
#include "SharedHandle.h" #include "SharedHandle.h"
#include "IntSequence.h" #include "IntSequence.h"
#include "a2time.h" #include "a2time.h"
#include "a2netcompat.h"
#include <sys/time.h> #include <sys/time.h>
#include <string> #include <string>
#include <utility> #include <utility>
@ -236,6 +237,9 @@ public:
#ifdef HAVE_POSIX_MEMALIGN #ifdef HAVE_POSIX_MEMALIGN
static void* allocateAlignedMemory(size_t alignment, size_t size); static void* allocateAlignedMemory(size_t alignment, size_t size);
#endif // HAVE_POSIX_MEMALIGN #endif // HAVE_POSIX_MEMALIGN
static std::pair<std::string, uint16_t>
getNumericNameInfo(const struct sockaddr* sockaddr, socklen_t len);
}; };
} // namespace aria2 } // namespace aria2

View File

@ -144,6 +144,11 @@ Option* createDefaultOption()
op->put(PREF_BT_REQUIRE_CRYPTO, V_FALSE); op->put(PREF_BT_REQUIRE_CRYPTO, V_FALSE);
op->put(PREF_QUIET, V_FALSE); op->put(PREF_QUIET, V_FALSE);
op->put(PREF_STOP, "0"); 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; return op;
} }
@ -215,6 +220,9 @@ Option* option_processing(int argc, char* const argv[])
{ PREF_STOP, required_argument, &lopt, 214 }, { PREF_STOP, required_argument, &lopt, 214 },
{ PREF_HEADER, required_argument, &lopt, 215 }, { PREF_HEADER, required_argument, &lopt, 215 },
{ PREF_QUIET, optional_argument, 0, 'q' }, { 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 #if defined ENABLE_BITTORRENT || ENABLE_METALINK
{ PREF_SHOW_FILES, no_argument, NULL, 'S' }, { PREF_SHOW_FILES, no_argument, NULL, 'S' },
{ PREF_SELECT_FILE, required_argument, &lopt, 21 }, { PREF_SELECT_FILE, required_argument, &lopt, 21 },
@ -416,6 +424,11 @@ Option* option_processing(int argc, char* const argv[])
case 215: case 215:
cmdstream << PREF_HEADER << "=" << optarg << "\n"; cmdstream << PREF_HEADER << "=" << optarg << "\n";
break; break;
#ifdef ENABLE_ASYNC_DNS
case 216:
cmdstream << PREF_ASYNC_DNS << "=" << toBoolArg(optarg) << "\n";
break;
#endif // ENABLE_ASYNC_DNS
} }
break; break;
} }

View File

@ -128,6 +128,8 @@
#define PREF_STOP "stop" #define PREF_STOP "stop"
// value: true | false // value: true | false
#define PREF_QUIET "quiet" #define PREF_QUIET "quiet"
// value: true | false
#define PREF_ASYNC_DNS "async-dns"
/** /**
* FTP related preferences * FTP related preferences

View File

@ -336,3 +336,5 @@ _(" --header=HEADER Append HEADER to HTTP request header. You can u
" http://host/file") " http://host/file")
#define TEXT_QUIET \ #define TEXT_QUIET \
_(" -q, --quiet[=true|false] Make aria2 quite (no console output).") _(" -q, --quiet[=true|false] Make aria2 quite (no console output).")
#define TEXT_ASYNC_DNS \
_(" --async-dns[=true|false] Enable asynchronous DNS.")