/* */ #include "NameResolveCommand.h" #include "DownloadEngine.h" #include "NameResolver.h" #include "prefs.h" #include "message.h" #include "util.h" #include "Option.h" #include "RequestGroupMan.h" #include "Logger.h" #include "LogFactory.h" #include "fmt.h" #include "UDPTrackerRequest.h" #include "UDPTrackerClient.h" #include "BtRegistry.h" #ifdef ENABLE_ASYNC_DNS #include "AsyncNameResolver.h" #endif // ENABLE_ASYNC_DNS namespace aria2 { NameResolveCommand::NameResolveCommand (cuid_t cuid, DownloadEngine* e, const SharedHandle& req) : Command(cuid), e_(e), req_(req) { setStatus(Command::STATUS_ONESHOT_REALTIME); } NameResolveCommand::~NameResolveCommand() { #ifdef ENABLE_ASYNC_DNS disableNameResolverCheck(resolver_); #endif // ENABLE_ASYNC_DNS } bool NameResolveCommand::execute() { // This is UDP tracker specific, but we need to keep this command // alive until force shutdown is // commencing. RequestGroupMan::downloadFinished() is useless here // at the moment. if(e_->isForceHaltRequested()) { onShutdown(); return true; } #ifdef ENABLE_ASYNC_DNS if(!resolver_) { int family = AF_INET; resolver_.reset(new AsyncNameResolver(family #ifdef HAVE_ARES_ADDR_NODE , e_->getAsyncDNSServers() #endif // HAVE_ARES_ADDR_NODE )); } #endif // ENABLE_ASYNC_DNS std::string hostname = req_->remoteAddr; std::vector res; if(util::isNumericHost(hostname)) { res.push_back(hostname); } else { #ifdef ENABLE_ASYNC_DNS if(e_->getOption()->getAsBool(PREF_ASYNC_DNS)) { try { if(resolveHostname(hostname, resolver_)) { res = resolver_->getResolvedAddresses(); } else { e_->addCommand(this); return false; } } catch(RecoverableException& e) { A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e); } } else #endif // ENABLE_ASYNC_DNS { NameResolver resolver; resolver.setSocktype(SOCK_DGRAM); try { resolver.resolve(res, hostname); } catch(RecoverableException& e) { A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e); } } } if(res.empty()) { onFailure(); } else { onSuccess(res, e_); } return true; } void NameResolveCommand::onShutdown() { req_->state = UDPT_STA_COMPLETE; req_->error = UDPT_ERR_SHUTDOWN; } void NameResolveCommand::onFailure() { req_->state = UDPT_STA_COMPLETE; req_->error = UDPT_ERR_NETWORK; } void NameResolveCommand::onSuccess (const std::vector& addrs, DownloadEngine* e) { req_->remoteAddr = addrs[0]; e->getBtRegistry()->getUDPTrackerClient()->addRequest(req_); } #ifdef ENABLE_ASYNC_DNS bool NameResolveCommand::resolveHostname (const std::string& hostname, const SharedHandle& resolver) { switch(resolver->getStatus()) { case AsyncNameResolver::STATUS_READY: A2_LOG_INFO(fmt(MSG_RESOLVING_HOSTNAME, getCuid(), hostname.c_str())); resolver->resolve(hostname); setNameResolverCheck(resolver); return false; case AsyncNameResolver::STATUS_SUCCESS: A2_LOG_INFO(fmt(MSG_NAME_RESOLUTION_COMPLETE, getCuid(), resolver->getHostname().c_str(), resolver->getResolvedAddresses().front().c_str())); return true; break; case AsyncNameResolver::STATUS_ERROR: throw DL_ABORT_EX (fmt(MSG_NAME_RESOLUTION_FAILED, getCuid(), hostname.c_str(), resolver->getError().c_str())); default: return false; } } void NameResolveCommand::setNameResolverCheck (const SharedHandle& resolver) { e_->addNameResolverCheck(resolver, this); } void NameResolveCommand::disableNameResolverCheck (const SharedHandle& resolver) { e_->deleteNameResolverCheck(resolver, this); } #endif // ENABLE_ASYNC_DNS } // namespace aria2