/* */ #include "DownloadEngineFactory.h" #include #include "Option.h" #include "RequestGroup.h" #include "DownloadEngine.h" #include "RequestGroupMan.h" #include "FileAllocationMan.h" #include "CheckIntegrityMan.h" #include "CheckIntegrityEntry.h" #include "CheckIntegrityDispatcherCommand.h" #include "prefs.h" #include "FillRequestGroupCommand.h" #include "FileAllocationDispatcherCommand.h" #include "AutoSaveCommand.h" #include "SaveSessionCommand.h" #include "HaveEraseCommand.h" #include "TimedHaltCommand.h" #include "WatchProcessCommand.h" #include "DownloadResult.h" #include "ServerStatMan.h" #include "a2io.h" #include "DownloadContext.h" #include "array_fun.h" #include "EvictSocketPoolCommand.h" #ifdef HAVE_LIBUV #include "LibuvEventPoll.h" #endif // HAVE_LIBUV #ifdef HAVE_EPOLL #include "EpollEventPoll.h" #endif // HAVE_EPOLL #ifdef HAVE_PORT_ASSOCIATE #include "PortEventPoll.h" #endif // HAVE_PORT_ASSOCIATE #ifdef HAVE_KQUEUE #include "KqueueEventPoll.h" #endif // HAVE_KQUEUE #ifdef HAVE_POLL #include "PollEventPoll.h" #endif // HAVE_POLL #include "SelectEventPoll.h" #include "DlAbortEx.h" #include "FileAllocationEntry.h" #include "HttpListenCommand.h" #include "LogFactory.h" namespace aria2 { DownloadEngineFactory::DownloadEngineFactory() = default; namespace { std::unique_ptr createEventPoll(Option* op) { const std::string& pollMethod = op->get(PREF_EVENT_POLL); #ifdef HAVE_LIBUV if (pollMethod == V_LIBUV) { auto ep = make_unique(); if (!ep->good()) { throw DL_ABORT_EX("Initializing LibuvEventPoll failed." " Try --event-poll=select"); } return std::move(ep); } else #endif // HAVE_LIBUV #ifdef HAVE_EPOLL if (pollMethod == V_EPOLL) { auto ep = make_unique(); if (!ep->good()) { throw DL_ABORT_EX("Initializing EpollEventPoll failed." " Try --event-poll=select"); } return std::move(ep); } else #endif // HAVE_EPLL #ifdef HAVE_KQUEUE if (pollMethod == V_KQUEUE) { auto kp = make_unique(); if (!kp->good()) { throw DL_ABORT_EX("Initializing KqueueEventPoll failed." " Try --event-poll=select"); } return std::move(kp); } else #endif // HAVE_KQUEUE #ifdef HAVE_PORT_ASSOCIATE if (pollMethod == V_PORT) { auto pp = make_unique(); if (!pp->good()) { throw DL_ABORT_EX("Initializing PortEventPoll failed." " Try --event-poll=select"); } return std::move(pp); } else #endif // HAVE_PORT_ASSOCIATE #ifdef HAVE_POLL if (pollMethod == V_POLL) { return make_unique(); } else #endif // HAVE_POLL if (pollMethod == V_SELECT) { return make_unique(); } assert(0); return nullptr; } } // namespace std::unique_ptr DownloadEngineFactory::newDownloadEngine( Option* op, std::vector> requestGroups) { const size_t MAX_CONCURRENT_DOWNLOADS = op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS); auto e = make_unique(createEventPoll(op)); e->setOption(op); { auto requestGroupMan = make_unique( std::move(requestGroups), MAX_CONCURRENT_DOWNLOADS, op); requestGroupMan->initWrDiskCache(); e->setRequestGroupMan(std::move(requestGroupMan)); } e->setFileAllocationMan(make_unique()); e->setCheckIntegrityMan(make_unique()); e->addRoutineCommand( make_unique(e->newCUID(), e.get())); e->addRoutineCommand(make_unique( e->newCUID(), e->getFileAllocationMan().get(), e.get())); e->addRoutineCommand(make_unique( e->newCUID(), e->getCheckIntegrityMan().get(), e.get())); e->addRoutineCommand( make_unique(e->newCUID(), e.get(), 30_s)); if (op->getAsInt(PREF_AUTO_SAVE_INTERVAL) > 0) { e->addRoutineCommand(make_unique( e->newCUID(), e.get(), std::chrono::seconds(op->getAsInt(PREF_AUTO_SAVE_INTERVAL)))); } if (op->getAsInt(PREF_SAVE_SESSION_INTERVAL) > 0) { e->addRoutineCommand(make_unique( e->newCUID(), e.get(), std::chrono::seconds(op->getAsInt(PREF_SAVE_SESSION_INTERVAL)))); } e->addRoutineCommand( make_unique(e->newCUID(), e.get(), 10_s)); { auto stopSec = op->getAsInt(PREF_STOP); if (stopSec > 0) { e->addRoutineCommand(make_unique( e->newCUID(), e.get(), std::chrono::seconds(stopSec))); } } if (op->defined(PREF_STOP_WITH_PROCESS)) { unsigned int pid = op->getAsInt(PREF_STOP_WITH_PROCESS); e->addRoutineCommand( make_unique(e->newCUID(), e.get(), pid)); } if (op->getAsBool(PREF_ENABLE_RPC)) { if (op->get(PREF_RPC_SECRET).empty() && op->get(PREF_RPC_USER).empty()) { A2_LOG_WARN("Neither --rpc-secret nor a combination of --rpc-user and " "--rpc-passwd is set. This is insecure. It is extremely " "recommended to specify --rpc-secret with the adequate " "secrecy or now deprecated --rpc-user and --rpc-passwd."); } bool ok = false; bool secure = op->getAsBool(PREF_RPC_SECURE); if (secure) { A2_LOG_NOTICE("RPC transport will be encrypted."); } static int families[] = {AF_INET, AF_INET6}; size_t familiesLength = op->getAsBool(PREF_DISABLE_IPV6) ? 1 : 2; for (size_t i = 0; i < familiesLength; ++i) { auto httpListenCommand = make_unique( e->newCUID(), e.get(), families[i], secure); if (httpListenCommand->bindPort(op->getAsInt(PREF_RPC_LISTEN_PORT))) { e->addCommand(std::move(httpListenCommand)); ok = true; } } if (!ok) { throw DL_ABORT_EX("Failed to setup RPC server."); } } return e; } } // namespace aria2