1 /* <!-- copyright */
2 /*
3  * aria2 - The high speed download utility
4  *
5  * Copyright (C) 2006 Tatsuhiro Tsujikawa
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * In addition, as a special exception, the copyright holders give
22  * permission to link the code of portions of this program with the
23  * OpenSSL library under certain conditions as described in each
24  * individual source file, and distribute linked combinations
25  * including the two.
26  * You must obey the GNU General Public License in all respects
27  * for all of the code used other than OpenSSL.  If you modify
28  * file(s) with this exception, you may extend this exception to your
29  * version of the file(s), but you are not obligated to do so.  If you
30  * do not wish to do so, delete this exception statement from your
31  * version.  If you delete this exception statement from all source
32  * files in the program, then also delete it here.
33  */
34 /* copyright --> */
35 #ifndef D_DOWNLOAD_ENGINE_H
36 #define D_DOWNLOAD_ENGINE_H
37 
38 #include "common.h"
39 
40 #include <string>
41 #include <deque>
42 #include <map>
43 #include <vector>
44 #include <memory>
45 
46 #include "a2netcompat.h"
47 #include "TimerA2.h"
48 #include "a2io.h"
49 #include "CUIDCounter.h"
50 #include "FileAllocationMan.h"
51 #include "CheckIntegrityMan.h"
52 #include "DNSCache.h"
53 #ifdef ENABLE_ASYNC_DNS
54 #  include "AsyncNameResolver.h"
55 #endif // ENABLE_ASYNC_DNS
56 
57 namespace aria2 {
58 
59 class Option;
60 class RequestGroupMan;
61 class StatCalc;
62 class SocketCore;
63 class CookieStorage;
64 class AuthConfigFactory;
65 class Request;
66 class EventPoll;
67 class Command;
68 #ifdef ENABLE_BITTORRENT
69 class BtRegistry;
70 #endif // ENABLE_BITTORRENT
71 #ifdef ENABLE_WEBSOCKET
72 namespace rpc {
73 class WebSocketSessionMan;
74 } // namespace rpc
75 #endif // ENABLE_WEBSOCKET
76 
77 namespace util {
78 namespace security {
79 class HMAC;
80 class HMACResult;
81 } // namespace security
82 } // namespace util
83 
84 class DownloadEngine {
85 private:
86   void waitData();
87 
88   std::string sessionId_;
89 
90   std::unique_ptr<EventPoll> eventPoll_;
91 
92   std::unique_ptr<StatCalc> statCalc_;
93 
94   int haltRequested_;
95 
96   class SocketPoolEntry {
97   private:
98     std::shared_ptr<SocketCore> socket_;
99     // protocol specific option string
100     std::string options_;
101 
102     std::chrono::seconds timeout_;
103 
104     Timer registeredTime_;
105 
106   public:
107     SocketPoolEntry(const std::shared_ptr<SocketCore>& socket,
108                     const std::string& option, std::chrono::seconds timeout);
109 
110     SocketPoolEntry(const std::shared_ptr<SocketCore>& socket,
111                     std::chrono::seconds timeout);
112 
113     ~SocketPoolEntry();
114 
115     bool isTimeout() const;
116 
getSocket()117     const std::shared_ptr<SocketCore>& getSocket() const { return socket_; }
118 
getOptions()119     const std::string& getOptions() const { return options_; }
120   };
121 
122   // key = IP address:port, value = SocketPoolEntry
123   std::multimap<std::string, SocketPoolEntry> socketPool_;
124 
125   Timer lastSocketPoolScan_;
126 
127   bool noWait_;
128 
129   std::chrono::milliseconds refreshInterval_;
130   Timer lastRefresh_;
131 
132   std::unique_ptr<CookieStorage> cookieStorage_;
133 
134 #ifdef ENABLE_BITTORRENT
135   std::unique_ptr<BtRegistry> btRegistry_;
136 #endif // ENABLE_BITTORRENT
137 
138   CUIDCounter cuidCounter_;
139 
140 #ifdef HAVE_ARES_ADDR_NODE
141   ares_addr_node* asyncDNSServers_;
142 #endif // HAVE_ARES_ADDR_NODE
143 
144   std::unique_ptr<DNSCache> dnsCache_;
145 
146   std::unique_ptr<AuthConfigFactory> authConfigFactory_;
147 
148 #ifdef ENABLE_WEBSOCKET
149   std::unique_ptr<rpc::WebSocketSessionMan> webSocketSessionMan_;
150 #endif // ENABLE_WEBSOCKET
151 
152   /**
153    * Delegates to StatCalc
154    */
155   void calculateStatistics();
156 
157   void onEndOfRun();
158 
159   void afterEachIteration();
160 
161   void poolSocket(const std::string& key, const SocketPoolEntry& entry);
162 
163   std::multimap<std::string, SocketPoolEntry>::iterator
164   findSocketPoolEntry(const std::string& key);
165 
166   std::unique_ptr<RequestGroupMan> requestGroupMan_;
167   std::unique_ptr<FileAllocationMan> fileAllocationMan_;
168   std::unique_ptr<CheckIntegrityMan> checkIntegrityMan_;
169   Option* option_;
170   // Ensure that Commands are cleaned up before requestGroupMan_ is
171   // deleted.
172   std::deque<std::unique_ptr<Command>> routineCommands_;
173   std::deque<std::unique_ptr<Command>> commands_;
174 
175   std::unique_ptr<util::security::HMAC> tokenHMAC_;
176   std::unique_ptr<util::security::HMACResult> tokenExpected_;
177 
178 public:
179   DownloadEngine(std::unique_ptr<EventPoll> eventPoll);
180 
181   ~DownloadEngine();
182 
183   // If oneshot is true, this function returns after one event polling
184   // and performing action for them. This function returns 1 when
185   // oneshot is true and there are still downloads to be
186   // processed. Otherwise, returns 0.
187   int run(bool oneshot = false);
188 
189   bool addSocketForReadCheck(const std::shared_ptr<SocketCore>& socket,
190                              Command* command);
191   bool deleteSocketForReadCheck(const std::shared_ptr<SocketCore>& socket,
192                                 Command* command);
193   bool addSocketForWriteCheck(const std::shared_ptr<SocketCore>& socket,
194                               Command* command);
195   bool deleteSocketForWriteCheck(const std::shared_ptr<SocketCore>& socket,
196                                  Command* command);
197 
198 #ifdef ENABLE_ASYNC_DNS
199 
200   bool addNameResolverCheck(const std::shared_ptr<AsyncNameResolver>& resolver,
201                             Command* command);
202   bool
203   deleteNameResolverCheck(const std::shared_ptr<AsyncNameResolver>& resolver,
204                           Command* command);
205 #endif // ENABLE_ASYNC_DNS
206 
207   void addCommand(std::vector<std::unique_ptr<Command>> commands);
208 
209   void addCommand(std::unique_ptr<Command> command);
210 
getRequestGroupMan()211   const std::unique_ptr<RequestGroupMan>& getRequestGroupMan() const
212   {
213     return requestGroupMan_;
214   }
215 
216   void setRequestGroupMan(std::unique_ptr<RequestGroupMan> rgman);
217 
getFileAllocationMan()218   const std::unique_ptr<FileAllocationMan>& getFileAllocationMan() const
219   {
220     return fileAllocationMan_;
221   }
222 
223   void setFileAllocationMan(std::unique_ptr<FileAllocationMan> faman);
224 
getCheckIntegrityMan()225   const std::unique_ptr<CheckIntegrityMan>& getCheckIntegrityMan() const
226   {
227     return checkIntegrityMan_;
228   }
229 
230   void setCheckIntegrityMan(std::unique_ptr<CheckIntegrityMan> ciman);
231 
getOption()232   Option* getOption() const { return option_; }
233 
setOption(Option * op)234   void setOption(Option* op) { option_ = op; }
235 
236   void setStatCalc(std::unique_ptr<StatCalc> statCalc);
237 
isHaltRequested()238   bool isHaltRequested() const { return haltRequested_; }
239 
isForceHaltRequested()240   bool isForceHaltRequested() const { return haltRequested_ >= 2; }
241 
242   void requestHalt();
243 
244   void requestForceHalt();
245 
246   void setNoWait(bool b);
247 
248   void addRoutineCommand(std::unique_ptr<Command> command);
249 
250   void poolSocket(const std::string& ipaddr, uint16_t port,
251                   const std::string& username, const std::string& proxyhost,
252                   uint16_t proxyport, const std::shared_ptr<SocketCore>& sock,
253                   const std::string& options,
254                   std::chrono::seconds timeout = 15_s);
255 
256   void poolSocket(const std::shared_ptr<Request>& request,
257                   const std::string& username,
258                   const std::shared_ptr<Request>& proxyRequest,
259                   const std::shared_ptr<SocketCore>& socket,
260                   const std::string& options,
261                   std::chrono::seconds timeout = 15_s);
262 
263   void poolSocket(const std::string& ipaddr, uint16_t port,
264                   const std::string& proxyhost, uint16_t proxyport,
265                   const std::shared_ptr<SocketCore>& sock,
266                   std::chrono::seconds timeout = 15_s);
267 
268   void poolSocket(const std::shared_ptr<Request>& request,
269                   const std::shared_ptr<Request>& proxyRequest,
270                   const std::shared_ptr<SocketCore>& socket,
271                   std::chrono::seconds timeout = 15_s);
272 
273   std::shared_ptr<SocketCore> popPooledSocket(const std::string& ipaddr,
274                                               uint16_t port,
275                                               const std::string& proxyhost,
276                                               uint16_t proxyport);
277 
278   std::shared_ptr<SocketCore>
279   popPooledSocket(std::string& options, const std::string& ipaddr,
280                   uint16_t port, const std::string& username,
281                   const std::string& proxyhost, uint16_t proxyport);
282 
283   std::shared_ptr<SocketCore>
284   popPooledSocket(const std::vector<std::string>& ipaddrs, uint16_t port);
285 
286   std::shared_ptr<SocketCore>
287   popPooledSocket(std::string& options, const std::vector<std::string>& ipaddrs,
288                   uint16_t port, const std::string& username);
289 
290   void evictSocketPool();
291 
292   const std::unique_ptr<CookieStorage>& getCookieStorage() const;
293 
294 #ifdef ENABLE_BITTORRENT
getBtRegistry()295   const std::unique_ptr<BtRegistry>& getBtRegistry() const
296   {
297     return btRegistry_;
298   }
299 #endif // ENABLE_BITTORRENT
300 
301   cuid_t newCUID();
302 
303   const std::string& findCachedIPAddress(const std::string& hostname,
304                                          uint16_t port) const;
305 
306   template <typename OutputIterator>
findAllCachedIPAddresses(OutputIterator out,const std::string & hostname,uint16_t port)307   void findAllCachedIPAddresses(OutputIterator out, const std::string& hostname,
308                                 uint16_t port) const
309   {
310     dnsCache_->findAll(out, hostname, port);
311   }
312 
313   void cacheIPAddress(const std::string& hostname, const std::string& ipaddr,
314                       uint16_t port);
315 
316   void markBadIPAddress(const std::string& hostname, const std::string& ipaddr,
317                         uint16_t port);
318 
319   void removeCachedIPAddress(const std::string& hostname, uint16_t port);
320 
321   void setAuthConfigFactory(std::unique_ptr<AuthConfigFactory> factory);
322 
323   const std::unique_ptr<AuthConfigFactory>& getAuthConfigFactory() const;
324 
325   void setRefreshInterval(std::chrono::milliseconds interval);
326 
getSessionId()327   const std::string getSessionId() const { return sessionId_; }
328 
329 #ifdef HAVE_ARES_ADDR_NODE
330   void setAsyncDNSServers(ares_addr_node* asyncDNSServers);
331 
getAsyncDNSServers()332   ares_addr_node* getAsyncDNSServers() const { return asyncDNSServers_; }
333 #endif // HAVE_ARES_ADDR_NODE
334 
335 #ifdef ENABLE_WEBSOCKET
336   void setWebSocketSessionMan(std::unique_ptr<rpc::WebSocketSessionMan> wsman);
337   const std::unique_ptr<rpc::WebSocketSessionMan>&
getWebSocketSessionMan()338   getWebSocketSessionMan() const
339   {
340     return webSocketSessionMan_;
341   }
342 #endif // ENABLE_WEBSOCKET
343 
344   bool validateToken(const std::string& token);
345 };
346 
347 } // namespace aria2
348 
349 #endif // D_DOWNLOAD_ENGINE_H
350