/* */ #ifndef _D_DOWNLOAD_ENGINE_H_ #define _D_DOWNLOAD_ENGINE_H_ #include "common.h" #ifdef HAVE_EPOLL_CREATE # include #endif // HAVE_EPOLL_CREATE #include #include #include #include "SharedHandle.h" #include "Command.h" #include "a2netcompat.h" #include "TimeA2.h" #include "a2io.h" #ifdef ENABLE_ASYNC_DNS # include "AsyncNameResolver.h" #endif // ENABLE_ASYNC_DNS #include "CUIDCounter.h" namespace aria2 { class Logger; class Option; class RequestGroupMan; class FileAllocationMan; class StatCalc; class CheckIntegrityMan; class SocketCore; class CookieStorage; class BtRegistry; class DNSCache; class AuthConfigFactory; class Request; class CommandEvent { private: Command* _command; int _events; public: CommandEvent(Command* command, int events); Command* getCommand() const; int getEvents() const; void addEvents(int events); void removeEvents(int events); bool eventsEmpty() const; void processEvents(int events); bool operator==(const CommandEvent& event) const; }; #if defined HAVE_EPOLL && defined ENABLE_ASYNC_DNS class ADNSEvent { private: SharedHandle _resolver; Command* _command; sock_t _socket; int _events; public: ADNSEvent(const SharedHandle& resolver, Command* command, sock_t socket, int events); void processEvents(int events); bool operator==(const ADNSEvent& event) const; int getEvents() const; }; #endif // HAVE_EPOLL && ENABLE_ASYNC_DNS class SocketEntry { private: sock_t _socket; std::deque _commandEvents; #if defined HAVE_EPOLL && defined ENABLE_ASYNC_DNS std::deque _adnsEvents; #endif // HAVE_EPOLL && ENABLE_ASYNC_DNS #ifdef HAVE_EPOLL struct epoll_event _epEvent; #endif // HAVE_EPOLL public: #ifdef HAVE_EPOLL enum EventType { EVENT_READ = EPOLLIN, EVENT_WRITE = EPOLLOUT, EVENT_ERROR = EPOLLERR, EVENT_HUP = EPOLLHUP, }; #else // !HAVE_EPOLL enum EventType { EVENT_READ = 1, EVENT_WRITE = 1 << 1, EVENT_ERROR = 1 << 2, EVENT_HUP = 1 << 3, }; #endif // !HAVE_EPOLL SocketEntry(sock_t socket); bool operator==(const SocketEntry& entry) const; bool operator<(const SocketEntry& entry) const; void addCommandEvent(Command* command, int events); void removeCommandEvent(Command* command, int events); #if defined HAVE_EPOLL && defined ENABLE_ASYNC_DNS void addADNSEvent(const SharedHandle& resolver, Command* command, int events); void removeADNSEvent(const SharedHandle& resolver, Command* command); #endif // HAVE_EPOLL && ENABLE_ASYNC_DNS #ifdef HAVE_EPOLL struct epoll_event& getEpEvent(); #else // !HAVE_EPOLL int getEvents(); #endif // !HAVE_EPOLL sock_t getSocket() const; bool eventEmpty() const; void processEvents(int events); }; #ifdef ENABLE_ASYNC_DNS class DownloadEngine; class AsyncNameResolverEntry { private: SharedHandle _nameResolver; Command* _command; #ifdef HAVE_EPOLL // HAVE_EPOLL assumes c-ares size_t _socketsSize; sock_t _sockets[ARES_GETSOCK_MAXNUM]; #endif // HAVE_EPOLL public: AsyncNameResolverEntry(const SharedHandle& nameResolver, Command* command); bool operator==(const AsyncNameResolverEntry& entry); #ifdef HAVE_EPOLL void addSocketEvents(DownloadEngine* e); void removeSocketEvents(DownloadEngine* e); #else // !HAVE_EPOLL int getFds(fd_set* rfdsPtr, fd_set* wfdsPtr); void process(fd_set* rfdsPtr, fd_set* wfdsPtr); #endif // !HAVE_EPOLL }; #endif // ENABLE_ASYNC_DNS class DownloadEngine { private: void waitData(); std::deque > socketEntries; #ifdef ENABLE_ASYNC_DNS std::deque > nameResolverEntries; #endif // ENABLE_ASYNC_DNS #ifdef HAVE_EPOLL int _epfd; struct epoll_event* _epEvents; static const size_t EPOLL_EVENTS_MAX = 1024; #else // !HAVE_EPOLL // If epoll is not available, then use select system call. fd_set rfdset; fd_set wfdset; int fdmax; #endif // !HAVE_EPOLL Logger* logger; SharedHandle _statCalc; bool _haltRequested; class SocketPoolEntry { private: SharedHandle _socket; std::map _options; time_t _timeout; Time _registeredTime; public: SocketPoolEntry(const SharedHandle& socket, const std::map& option, time_t timeout); ~SocketPoolEntry(); bool isTimeout() const; SharedHandle getSocket() const; const std::map& getOptions() const; }; // key = IP address:port, value = SocketPoolEntry std::multimap _socketPool; Time _lastSocketPoolScan; bool _noWait; std::deque _routineCommands; SharedHandle _cookieStorage; SharedHandle _btRegistry; CUIDCounter _cuidCounter; SharedHandle _dnsCache; SharedHandle _authConfigFactory; void shortSleep() const; /** * Delegates to StatCalc */ void calculateStatistics(); void onEndOfRun(); void afterEachIteration(); void poolSocket(const std::string& ipaddr, uint16_t port, const SocketPoolEntry& entry); std::multimap::iterator findSocketPoolEntry(const std::string& ipaddr, uint16_t port); public: std::deque commands; SharedHandle _requestGroupMan; SharedHandle _fileAllocationMan; SharedHandle _checkIntegrityMan; const Option* option; DownloadEngine(); virtual ~DownloadEngine(); void run(); void cleanQueue(); #ifndef HAVE_EPOLL void updateFdSet(); #endif // !HAVE_EPOLL bool addSocketForReadCheck(const SharedHandle& socket, Command* command); bool deleteSocketForReadCheck(const SharedHandle& socket, Command* command); bool addSocketForWriteCheck(const SharedHandle& socket, Command* command); bool deleteSocketForWriteCheck(const SharedHandle& socket, Command* command); bool addSocketEvents(sock_t socket, Command* command, int events #if defined HAVE_EPOLL && defined ENABLE_ASYNC_DNS ,const SharedHandle& rs = SharedHandle() #endif // HAVE_EPOLL && ENABLE_ASYNC_DNS ); bool deleteSocketEvents(sock_t socket, Command* command, int events #if defined HAVE_EPOLL && defined ENABLE_ASYNC_DNS ,const SharedHandle& rs = SharedHandle() #endif // HAVE_EPOLL && ENABLE_ASYNC_DNS ); #ifdef ENABLE_ASYNC_DNS bool addNameResolverCheck(const SharedHandle& resolver, Command* command); bool deleteNameResolverCheck(const SharedHandle& resolver, Command* command); #endif // ENABLE_ASYNC_DNS void addCommand(const Commands& commands); void fillCommand(); void setStatCalc(const SharedHandle& statCalc); bool isHaltRequested() const { return _haltRequested; } void requestHalt(); void setNoWait(bool b); void addRoutineCommand(Command* command); void poolSocket(const std::string& ipaddr, uint16_t port, const SharedHandle& sock, const std::map& options, time_t timeout = 15); void poolSocket(const std::string& ipaddr, uint16_t port, const SharedHandle& sock, time_t timeout = 15); SharedHandle popPooledSocket(const std::string& ipaddr, uint16_t port); SharedHandle popPooledSocket (std::map& options, const std::string& ipaddr, uint16_t port); SharedHandle popPooledSocket(const std::deque& ipaddrs, uint16_t port); SharedHandle popPooledSocket (std::map& options, const std::deque& ipaddrs, uint16_t port); SharedHandle getCookieStorage() const; SharedHandle getBtRegistry() const; CUID newCUID(); const std::string& findCachedIPAddress(const std::string& hostname) const; void cacheIPAddress(const std::string& hostname, const std::string& ipaddr); void setAuthConfigFactory(const SharedHandle& factory); SharedHandle getAuthConfigFactory() const; }; typedef SharedHandle DownloadEngineHandle; } // namespace aria2 #endif // _D_DOWNLOAD_ENGINE_H_