1 /***************************************************************************
2                           cdownloadmanager.h  -  description
3                              -------------------
4     begin                : Don Mai 16 2002
5     copyright            : (C) 2002-2004 by Mathias Küster
6     email                : mathen@users.berlios.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef CDOWNLOADMANAGER_H
19 #define CDOWNLOADMANAGER_H
20 
21 /**
22   *@author Mathias Küster
23   *
24   * This handles the queue of files and sources, the list of running
25   * transfers, and starting auto searches.
26   *
27   * The download manager is lacking multi threading, also segment size
28   * is fixed, and the number of download slots is not normally limited.
29   *
30   * Upload bandwith limiting is present, although not present in
31   * mainline DC++ at the time of writing this.
32   *
33   * Calculating the MD5 checksum of the first 10KiB is mostly
34   * useless and completely obsolete, but basically very little
35   * was ever done to dclib's downloading ability between 0.3.7 and 0.3.22.
36   */
37 
38 #include <dclib/dcos.h>
39 #include <dclib/core/cmutex.h>
40 #include <dclib/core/csingleton.h>
41 #include <dclib/ctransfer.h>
42 
43 /*
44  * eCloseType has moved to here so
45  * that cconfig.h does not need to include cdownloadmanager.h
46  */
47 #include <dclib/core/types.h>
48 
49 #include <dclib/core/cstringlist.h>
50 
51 #define MAX_FILE_PRIORITY 5
52 
53 enum eShutdownState {
54 	essNONE,
55 	essSHUTDOWN,
56 	essSHUTDOWNREADY
57 };
58 
59 class CUserFileInfo {
60 public:
61 	/** */
CUserFileInfo()62 	CUserFileInfo()
63 	{
64 		bMulti = false;
65 	};
66 	/** */
~CUserFileInfo()67 	~CUserFileInfo() {};
68 	/** */
69 	eTransferWaitState eWaitState;
70 	/** */
71 	eTransferFileState eFileState;
72 	/** */
73 	CString sLocalFile;
74 	/** */
75 	bool bMulti;
76 };
77 
78 class CExtraUserSlot {
79 public:
80 	/** */
CExtraUserSlot()81 	CExtraUserSlot()
82 	{
83 		iSlots = 1;
84 		bPermanent = false;
85 	};
86 	/** */
~CExtraUserSlot()87 	~CExtraUserSlot() {};
88 	/** */
89 	CString sNick;
90 	/** */
91 	CString sHubName;
92 	/** */
93 	int iSlots;
94 	/** */
95 	bool bPermanent;
96 };
97 
98 class DCTransferBanObject {
99 public:
100 	/** */
DCTransferBanObject()101 	DCTransferBanObject() {
102 		m_nRequestCount = 0;
103 		m_tTime         = 0;
104 	};
105 	/** */
~DCTransferBanObject()106 	~DCTransferBanObject() {};
107 	/** */
108 	CString m_sIP;
109 	/** */
110 	unsigned int m_nRequestCount;
111 	/** */
112 	time_t m_tTime;
113 };
114 
115 class CDownloadManagerInfo : public CDCMessage {
116 public:
117 	/** */
CDownloadManagerInfo()118 	CDownloadManagerInfo() : CDCMessage(DC_MESSAGE_DM_INFO) {
119 		rate_ul_settings = 0;
120 		rate_ul_operator = 0;
121 		rate_ul_user     = 0;
122 		rate_ul_special  = 0;
123 		rate_ul_rate_extra = 0;
124 		rate_dl  = 0;
125 		slot_max = 0;
126 		slot_use_settings = 0;
127 		slot_use_operator = 0;
128 		slot_use_user     = 0;
129 		slot_use_special  = 0;
130 		slot_use_rate_extra = 0;
131 	};
132 	/** */
~CDownloadManagerInfo()133 	virtual ~CDownloadManagerInfo() {};
134 	/** */
Rate()135 	ulonglong Rate() {
136 		return rate_ul_settings + rate_ul_operator + rate_ul_user + rate_ul_special + rate_ul_rate_extra;
137 	}
138 	/** */
139 	ulonglong rate_ul_settings;
140 	/** */
141 	ulonglong rate_ul_operator;
142 	/** */
143 	ulonglong rate_ul_user;
144 	/** */
145 	ulonglong rate_ul_special;
146 	/** */
147 	ulonglong rate_ul_rate_extra;
148 	/** */
149 	ulonglong rate_dl;
150 	/** */
151 	int slot_max;
152 	/** the number of normal slots from main config settings used */
153 	int slot_use_settings;
154 	/** slot usage for operators (after all other slots used up) */
155 	int slot_use_operator;
156 	/** slot usage for users (extra normal slots granted to users, only used if normal slots used up) */
157 	int slot_use_user;
158 	/** slot usage for special transfers e.g. minimum filelength (after all normal used up) */
159 	int slot_use_special;
160 	/** the number of extra slots that have been given because total upload rate is below a limit */
161 	int slot_use_rate_extra;
162 
163 	CDownloadManagerInfo & operator = (const CDownloadManagerInfo & s)
164 	{
165 		rate_ul_settings = s.rate_ul_settings;
166 		rate_ul_operator = s.rate_ul_operator;
167 		rate_ul_user     = s.rate_ul_user;
168 		rate_ul_special  = s.rate_ul_special;
169 		rate_ul_rate_extra = s.rate_ul_rate_extra;
170 
171 		rate_dl  = s.rate_dl;
172 		slot_max = s.slot_max;
173 
174 		slot_use_settings = s.slot_use_settings;
175 		slot_use_operator = s.slot_use_operator;
176 		slot_use_user     = s.slot_use_user;
177 		slot_use_special  = s.slot_use_special;
178 		slot_use_rate_extra = s.slot_use_rate_extra;
179 
180 		return *this;
181 	};
182 };
183 
184 enum eFileManagerStatus {
185 	efmsNONE=0,
186 	efmsIDLE,
187 	efmsCREATESHARELIST,
188 	efmsCREATESEARCHINDEX,
189 	efmsCREATEHASHLIST,
190 	efmsREBUILDLISTS,
191 	efmsVALIDATELEAVES
192 };
193 
194 class CFileManagerInfo : public CDCMessage {
195 public:
196 	/** */
CFileManagerInfo()197 	CFileManagerInfo() : CDCMessage(DC_MESSAGE_FM_INFO) {
198 		m_eFileManagerStatus = efmsNONE;
199 		m_nProgress = 0;
200 	};
201 	/** */
~CFileManagerInfo()202 	virtual ~CFileManagerInfo() {};
203 	/** */
204 	enum eFileManagerStatus m_eFileManagerStatus;
205 	/** */
206 	double m_nProgress;
207 
208 	CFileManagerInfo & operator = (const CFileManagerInfo & s)
209 	{
210 		m_eFileManagerStatus = s.m_eFileManagerStatus;
211 		m_nProgress          = s.m_nProgress;
212 		return *this;
213 	};
214 };
215 
216 class CDCMessage;
217 class CListen;
218 class CDownloadQueue;
219 class DCFileChunkObject;
220 class DCTransferQueueObject;
221 class DCTransferFileObject;
222 class DCTransferWait;
223 class _CCallback0;
224 
225 class CTransferObject {
226 public:
227 	/** */
CTransferObject()228 	CTransferObject() {
229 		m_pTransfer = 0;
230 		m_UserDisconnectTimeout = time(0);
231 	}
232 	/** */
~CTransferObject()233 	~CTransferObject() {
234 		delete m_pTransfer;
235 		m_pTransfer = 0;
236 	}
237 
238 	/** */
239 	CTransfer * m_pTransfer;
240 	/** */
241 	time_t m_UserDisconnectTimeout;
242 };
243 
244 class CDownloadManager : public CSingleton<CDownloadManager> {
245 public:
246 	/** */
247 	CDownloadManager();
248 	/** */
249 	virtual ~CDownloadManager();
250 
251 	/** load the queue */
252 	int DLM_LoadQueue();
253 	/** save the queue */
254 	int DLM_SaveQueue();
255 	/** disconnect all transfers for a clean shutdown */
256 	void DLM_Shutdown();
257 	/** return the current shutdownstate */
DLM_ShutdownState()258 	eShutdownState DLM_ShutdownState() const { return m_eShutdownState; }
259 	/** add a extra slot to the user */
260 	void DLM_AddUserSlot( CString nick, CString hubname, int slot, bool permanent = false );
261 	/** return current used upload slots */
DLM_UsedSlots()262 	int DLM_UsedSlots() const { return DownloadManagerInfo.slot_use_settings; }
263 	/** */
264 	bool DLM_TransferConnect( CString nick, CString hubname );
265 	/** */
266 	bool DLM_TransferClose( ulonglong transferid );
267 	/** */
268 	bool DLM_TransferSetRate( ulonglong transferid, ulonglong rate );
269 	/** */
270 	bool DLM_TransferGetRate( ulonglong transferid, ulonglong & rate );
271 	/** */
272 	CList<CMessageDMTransferObject> * DLM_TransferGetList();
273 
274 	/** */
275 	eDirection DLM_TransferDirection( ulonglong transferid );
276 
277 	/**
278 	 * For filelists, localpath is abused to set the file/folder to
279 	 * open the list at (when downloaded from search) and localrootpath
280 	 * is abused to download a directory.
281 	 */
282 	void DLM_QueueAdd( CString nick, CString hubname, CString hubhost,
283 				CString remotename, CString localname,
284 				CString localpath, CString localrootpath,
285 				eltMedium medium, ulonglong size,
286 				ulonglong startposition,
287 				ulonglong endposition,
288 				CString hash,
289 				bool multi = false );
290 	/** */
291 	int DLM_QueueCheck( CString nick, CString hubname, CString hubhost,
292 				CString remotename, CString localname,
293 				CString localpath, CString localrootpath,
294 				eltMedium medium, ulonglong size, CString tth );
295 	/** change the src-nick/hubname to dst-nick/hubname in the queue */
296 	bool DLM_QueueEdit( CString srcnick, CString srchubname, CString dstnick, CString dsthubname, CString dsthubhost );
297 	/** */
298 	bool DLM_QueuePause( CString nick, CString hubname, CString remotefile, bool pause );
299 	/** */
300 	bool DLM_QueueRemove( CString nick, CString hubname, CString remotefile );
301 	/** */
302 	bool DLM_QueueRemove( CString localfile );
303 	/**
304 	 * 0 = directory removed
305 	 * 1 = user/hub not found
306 	 * 2 = no directories queued
307 	 * 3 = that directory not queued
308 	 */
309 	int DLM_QueueRemoveDirectory( CString nick, CString hubname, CString directory );
310 	/** */
311 	bool DLM_QueueSetFilePriority( CString nick, CString hubname, CString remotefile, int priority );
312 	/** */
313 	bool DLM_QueueGetFileInfo( CString nick, CString hubname, CString hubhost, CString file, CUserFileInfo * UserFileInfo );
314 	/** */
315 	DCFileChunkObject * DLM_QueueGetFileChunk( CString file );
316 	/** */
317 	bool DLM_QueueUpdateHub( CString nick, CString hubname );
318 	/** */
319 	void DLM_QueueGetHub( CString nick, CString hubname, CList<DCHubObject> * list );
320 
321 	/** */
322 	bool DLM_AddTransferRequest( CString nick, CString userhost, CString hubname, CString hubhost );
323 	/** */
324 	void DLM_AddTransferRequest( CString host, int port, bool crypto, CString hubname, CString hubhost );
325 
326 	/** */
327 	bool DLM_GetDownloadManagerInfo( CDownloadManagerInfo * pinfo );
328 	/** handle search */
329 	bool DLM_HandleSearch( CMessageSearchResult * MessageSearchResult );
330 
331 	/** callback function - Called by CManager */
332 	int Callback();
333 	/** callback function */
DC_DownloadManagerCallBack(CDCMessage *)334 	virtual int DC_DownloadManagerCallBack( CDCMessage * ) { return -1; };
335 
336 	/**
337 	 * It's not given to a CCallback it's just directly called by the
338 	 * listen managers so it can take whatever parameters are necessary.
339 	 */
340 	int ListenCallbackHandler( int fd, bool crypto );
341 
342 protected:
343 	/** */
344 	int DM_TransferCallBack( CTransfer * Transfer, CDCMessage * DCMessage );
345 
346 	/** */
347 	void SendFileManagerInfo( CFileManagerInfo * info );
348 
349 private:
350 	/** */
351 	friend class CFileManager;
352 
353 	/** */
354 	void SendFileInfo( DCTransferQueueObject * TransferObject, DCTransferFileObject * TransferFileItem = 0, bool bRemoveFile = false );
355 	/** */
356 	void SendTransferInfo( CTransfer * Transfer, bool remove = false );
357 	/** */
358 	void SendSlotInfo( CExtraUserSlot * Object );
359 	/** */
360 	void SendLogInfo( CString message, CTransfer * Transfer = 0 );
361 	/** */
362 	void SendDownloadManagerInfo( CDownloadManagerInfo * dminfo );
363 	/** */
364 	void SendTrafficInfo();
365 
366 	/** create a messagedmtransferobject from a transfer */
367 	CMessageDMTransferObject * CreateDMTransferObject( CTransfer * Transfer );
368 	/** */
369 	void FileListDone( CTransfer * Transfer, DCTransferFileObject * TransferFileObject );
370 
371 	/** */
372 	bool CheckUserSlot( CString nick, CString hubname );
373 	/** */
374 	void OptimizeChunks( DCFileChunkObject * FileChunkObject );
375 	/** */
376 	bool GetNextChunk( CString file, ulonglong * lstart, ulonglong * lend );
377 	/** */
378 	int UpdateChunk( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent );
379 	/** */
380 	bool GetNewChunkEnd( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent, ulonglong * lnstart, ulonglong *lnend );
381 
382 	/** */
383 	void UpdateQueueList( time_t ttimeout );
384 	/** */
385 	void UpdateTransferList( time_t ttimeout );
386 	/** */
387 	void UpdateBanList( time_t ttimeout );
388 
389 	/** */
390 	eDirection CheckWaitTransfer( CTransfer * Transfer );
391 	/** */
392 	bool UpdateWaitTransfer( CTransfer * Transfer, bool rem = false );
393 	/** */
394 	bool ChangeDirection( CTransfer * Transfer );
395 	/** */
396 	bool SetNextFile( CTransfer * Transfer );
397 	/** */
398 	bool SetDirection( CTransfer * Transfer );
399 	/** */
400 	bool SetFile( CTransfer * Transfer );
401 	/** */
402 	void UpdateFileState( CTransfer * Transfer, eTransferFileState eState );
403 	/** */
404 	bool CheckHash( CTransfer * Transfer );
405 
406 	/** */
407 	bool RemoveQueueFile( CString nick, CString hubname, CString remotefile );
408 	/** */
409 	bool RemoveQueueFile( CString localfile );
410 
411 	/** */
412 	bool InitSearch( time_t ttimeout );
413 
414 	/** */
415 	ulonglong GetNewID();
416 
417 	/** */
418 	eShutdownState m_eShutdownState;
419 
420 	/** mutex for extra slots list */
421 	CMutex * m_pExtraSlotsMutex;
422 	/** */
423 	CList<CExtraUserSlot> * m_pExtraUserSlotList;
424 
425 	/** */
426 	_CCallback0 * m_pCallback;
427 
428 	/** */
429 	CDownloadManagerInfo DownloadManagerInfo;
430 	/** */
431 	CMutex TransferCallBackMutex;
432 	/** */
433 	CMutex LogMutex;
434 	/** */
435 	ulonglong m_nID;
436 
437 	/** */
438 	time_t m_tDownloadQueueTimeout;
439 	/** */
440 	time_t m_tUpdateTransferTimeout;
441 	/** timeout for a new hubsearch */
442 	time_t m_tHubSearchTimeout;
443 	/** timeout for a single search */
444 	time_t m_tSearchTimeout;
445 	/**
446 	 * The last time an additional upload slot was given because
447 	 * total upload rate was below a limit. This is needed so that
448 	 * these slots are only given max 1 per minute so that there
449 	 * is enough time for the new transfer to be included in
450 	 * the total upload rate.
451 	 */
452 	time_t m_tLastRateExtra;
453 	/**
454 	 * The time old entries were removed from m_pTransferWaitList.
455 	 */
456 	time_t m_tWaitListCleaned;
457 
458 	/** */
459 	CDownloadQueue * m_pDownloadQueue;
460 	/** mutex for transfers list */
461 	CMutex * m_pTransfersMutex;
462 	/** */
463 	CStringList<CTransferObject> * m_pTransferList;
464 	/** mutex for transfer wait list */
465 	CMutex * m_pWaitListMutex;
466 	/** */
467 	CList<DCTransferWait> * m_pTransferWaitList;
468 	/** mutex for transfer ban list */
469 	CMutex * m_pBanListMutex;
470 	/** */
471 	CStringList<DCTransferBanObject> * m_pTransferBanList;
472 	/**
473 	 * The search result list was never locked/unlocked.
474 	 */
475 	CList<CMessageSearchResult> * m_pSearchList;
476 	/** */
477 	CList<CDCMessage> * m_pSearchQueryList;
478 };
479 
480 #endif
481