1 /***************************************************************************
2                           ctransfer.h  -  description
3                              -------------------
4     begin                : Fri Feb 22 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 CTRANSFER_H
19 #define CTRANSFER_H
20 
21 /**
22   *@author Mathias Küster
23   *
24   * This class handles a file transfer, reading or writing to the file,
25   * possibly doing zlib compression or decompression.
26   *
27   * Perhaps the worst thing missing from this class, and dclib overall, is
28   * that there is no verification of the data received using the TTH leaf data.
29   *
30   * The TTH leaf data should basically be a list of TTHs, for sections of the
31   * file, you can check the leaf data matches the root (by hashing it), and
32   * then hash the data as it is received.
33   *
34   * This class is an awful mess mainly for all the obsolete protocol command
35   * support, but also due to compressed transfers (most things are not even
36   * compressible anyway).
37   */
38 
39 #include <dclib/dcos.h>
40 #include <dclib/core/cstring.h>
41 #include <dclib/core/ccallback.h>
42 #include <dclib/core/cfile.h>
43 #include <dclib/core/czlib.h>
44 #include <dclib/cdcproto.h>
45 #include <dclib/dcobject.h>
46 
47 #ifndef WIN32
48 #include <sys/time.h>
49 #endif
50 
51 class CByteArray;
52 
53 enum eTransferState {
54 	etsNONE,
55 	etsREADY,
56 	etsIDLE
57 };
58 
59 /*
60  * Warning: these are not in order the types of slot are allocated.
61  * Changes for 0.3.22:
62  * - total upload rate dependant extra normal slots added (O: in DC++ tag)
63  * - if a user is granted a slot, the user may still get a normal slot,
64  *   and this still uses up the granted slot
65  * - operator slots were fixed, and now may actually be allocated after special slots
66  *
67  * Previously operator slots were broken (never given), which is lucky
68  * because they would have prevented operators getting small files when
69  * normal users could. Also slots granted to users caused that
70  * user to not use a normal slot. I think the idea of slots granted to
71  * users is to allow friends to get files when normal slots are used, not to
72  * allow normal users to get files while your friends are busy downloading.
73  *
74  * SETTINGS, RATE_EXTRA and USER are all normal slots allowing all uploads,
75  * but SPECIAL is limited and OPERATOR more limited. So 3 types of slot
76  * but 5 ways for some kind of slot to be given (3,1,1 for normal,mini,op).
77  */
78 enum eTransferType {
79 	ettNONE,	/* unknown */
80 	ettSETTINGS,	/* normal slot from settings slot limit */
81 	ettOPERATOR,	/* 1 of 4 slots for operators to get the filelist */
82 	ettUSER,	/* normal slot granted to a user */
83 	ettSPECIAL,	/* 1 of 4 slots for small files,filelist,leaves */
84 	ettRATE_EXTRA	/* normal slot allocated because total upload rate was below minimum */
85 };
86 
87 typedef struct sAverageTransferRate {
88 	struct timeval tv[10];
89 	ulonglong transfered[10];
90 	int index;
91 } sAverageTransferRate;
92 
93 class CTransfer : public CDCProto {
94 public:
95 	/** */
96 	CTransfer( bool listener = false );
97 	/** */
98 	virtual ~CTransfer();
99 
100 	/** callback function */
DC_CallBack(CDCMessage *)101 	virtual int DC_CallBack( CDCMessage * ) { return -1; };
102 	/** */
103 	virtual void DataAvailable( const char * buffer, int len );
104 	/** */
105 	virtual void DataSend();
106 	/** */
107 	virtual void DataTimeout();
108 	/** */
109 	virtual void ConnectionState( eConnectionState state );
110 	/** */
111 	virtual void Notify();
112 
113 	/** */
114 	void SetCallBackFunction( _CCallback2<CTransfer, CDCMessage*> * callback );
115 
116 	/** */
117 	int StartDownload( CString dstfile, ulonglong startposition, ulonglong endposition, ulonglong size, ulonglong chunksize, CString srcfile, CString adcTTH = CString() );
118 	/** */
119 	int StartUpload( CString dstfile, ulonglong length, ulonglong pos, ulonglong chunksize, CString srcfile, bool uget = false, bool adcget = false, CString adcTTH = CString(), bool compress = false );
120 
121 	/** */
122 	int CallBack_SendObject( CDCMessage * DCMessage );
123 	/** */
124 	int CallBack_SendError( CString msg );
125 
126 	/** */
127 	ulonglong GetTransferrate();
128 	/** */
129 	ulonglong GetBytesForTransferrate( ulonglong rate );
130 	/** */
131 	void AddTraffic( long n );
132 	/** */
133 	ulonglong GetTraffic();
134 
135 	/** */
136 	int HandleMessage( char * c, int len );
137 
138 	/** */
CloseFile()139 	void CloseFile() { m_File.Close(); };
140 	/** */
141 	ulonglong GetTransferID() const;
142 	/** */
143 	void SetTransferID( ulonglong transferid );
144 	/** */
145 	CString GetDstFilename() const;
146 	/** */
147 	void SetDstFilename( CString filename );
148 	/** */
149 	CString GetSrcFilename() const;
150 	/** */
151 	void SetSrcFilename( CString filename );
152 	/** */
153 	CString GetDstNick() const;
154 	/** */
155 	CString GetHubHost() const;
156 	/** */
157 	void SetHubHost( CString hubhost );
158 	/** */
159 	CString GetHubName() const;
160 	/** */
161 	void SetHubName( CString hubname );
162 	/** */
163 	eltMedium GetMedium() const;
164 	/** */
165 	void SetMedium( eltMedium medium );
166 	/** */
167 	long GetBuffer( CByteArray *ba );
168 	/** */
169 	bool SaveBufferToFile( const CString & filename );
170 	/** */
171 	void SetBuffer( CByteArray *ba );
172 	/**
173 	 * This is to avoid creating an intermediate CByteArray for ADCGET list transfers.
174 	 */
175 	void ClearAndAppendBuffer( const unsigned char * data, const unsigned long length );
176 
177 	/** */
178 	eDirection GetSrcDirection() const;
179 	/** */
180 	void SetSrcDirection( eDirection direction );
181 	/** */
182 	eDirection GetDstDirection() const;
183 	/** */
184 	void SetDstDirection( eDirection direction );
185 
186 	/** */
187 	int GetSrcLevel() const;
188 	/** */
189 	int GetDstLevel() const;
190 	/** */
191 	eConnectionState GetMode() const;
192 	/** */
193 	void SetMode( eConnectionState mode );
194 	/** */
195 	ulonglong GetStartPosition() const;
196 	/** */
197 	void SetStartPosition( ulonglong pos );
198 	/** */
199 	ulonglong GetEndPosition() const;
200 	/** */
201 	void SetEndPosition( ulonglong pos );
202 	/** */
203 	ulonglong GetLength() const;
204 	/** */
205 	void SetLength( ulonglong length );
206 	/** */
207 	ulonglong GetTransfered() const;
208 	/** */
SetTransfered(ulonglong n)209 	void SetTransfered( ulonglong n ) { m_nTransfered = n; };
210 	/** */
GetChunkSize()211 	ulonglong GetChunkSize() const { return m_nChunkSize; };
212 	/** */
SetChunkSize(ulonglong n)213 	void SetChunkSize( ulonglong n ) { m_nChunkSize = n; };
214 	/** */
215 	void InitTime();
216 	/** */
217 	void SetNick( CString nick );
218 	/** */
219 	CString GetNick();
220 	/** */
221 	void SetRate( ulonglong rate );
222 	/** */
223 	ulonglong GetRate() const;
224 	/** */
225 	bool IsIdle() const;
226 
227 	/** */
228 	void SetDone( eTransferState e );
229 	/** */
230 	eTransferState GetDone() const;
231 	/** */
232 	time_t GetStartTime() const;
233 	/** */
234 	void SetStartTime( time_t t );
235 
236 	/** */
237 	eTransferType GetTransferType() const;
238 	/** */
239 	void SetTransferType( eTransferType type );
240 
241 	/** */
GetSupport()242 	CMessageSupports GetSupport() { return m_MessageSupports; }
243 	/** */
244 	bool GetEncrypted();
245 	/** */
246 	bool SupportsChunks() const;
247 
248 	/** */
249 	CString GetTTH() const;
250 	/** */
251 	void SetTTH( const CString & newtth );
252 
253 	/** */
IsListener()254 	bool IsListener() const { return m_bListener; };
255 
256 private:
257 	/** */
258 	bool DoInitDownload();
259 	/** */
260 	void DoInitUpload();
261 	/** */
262 	int HandleFileTransfer( const char * buffer, int len );
263 	/** */
264 	int HandleBufferTransfer( const char * buffer, int len );
265 	/** */
266 	int HandleControlTransfer( const char * buffer, int len );
267 	/** Send SSL messages to GUI */
268 	void SendSSLInfo();
269 
270 	/** */
271 	int m_nDataType;
272 	/** */
273 	ulonglong m_nTransferID;
274 	/** */
275 	CString sNick;
276 	/** */
277 	CString sBuffer;
278 	/** remote filesize */
279 	ulonglong m_nFileSize;
280 	/** start transfer from this fileposition */
281 	ulonglong m_nStartPosition;
282 	/** */
283 	ulonglong m_nEndPosition;
284 	/** bytes transfered */
285 	ulonglong m_nTransfered;
286 	/** wanted bytes */
287 	ulonglong m_nChunkSize;
288 	/** */
289 	bool m_bListener;
290 	/** */
291 	long m_nFileBufferPos;
292 	/** */
293 	long m_nFileBufferSize;
294 	/** */
295 	ulonglong m_nTransferRate;
296 	/** */
297 	eConnectionState eMode;
298 	/** */
299 	eltMedium eMedium;
300 	/** */
301 	bool m_bIdle;
302 	/** */
303 	CFile m_File;
304 	/** */
305 	CByteArray * pByteArray;
306 	/** local filename */
307 	CString sSrcFilename;
308 	/** remote filename */
309 	CString sDstFilename;
310 	/** local direction */
311 	eDirection eSrcDirection;
312 	/** remote direction */
313 	eDirection eDstDirection;
314 	/** remote nick */
315 	CString sDstNick;
316 	/** local level */
317 	int m_nSrcLevel;
318 	/** local level */
319 	int m_nDstLevel;
320 	/** identifier hubname */
321 	CString sHubName;
322 	/** identifier hubhost:hubport */
323 	CString sHubHost;
324 	/** */
325 	struct timeval starttime;
326 	/** */
327 	ulonglong m_nPendingSendBytes;
328 	/** */
329 	CMutex TransferMutex;
330 	/** callback function */
331 	_CCallback2<CTransfer, CDCMessage*> * pCallback;
332 	/** */
333 	eTransferState m_eTransferState;
334 	/** */
335 	eTransferType m_eTransferType;
336 	/** */
337 	CMessageSupports m_MessageSupports;
338 	/** Disable XML filelists for DC++ >= 0.307 and <= 0.403 */
339 	bool m_bDisableXML;
340 	/** */
341 	struct sAverageTransferRate m_AverageTransferRate;
342 	/** */
343 	CZLib m_ZLib;
344 	/** used to compress uploads */
345 	CDeflater m_Deflater;
346 	/** size of read buffer */
347 	long m_nReadFileBufferSize;
348 	/** last return value from czlib/cdeflater */
349 	int m_nZlibStatus;
350 	/** file TTH */
351 	CString m_sTTH;
352 };
353 
354 /** */
GetDstFilename()355 inline CString CTransfer::GetDstFilename() const
356 { return sDstFilename; }
357 /** */
SetDstFilename(CString filename)358 inline void CTransfer::SetDstFilename( CString filename )
359 { TransferMutex.Lock(); sDstFilename=filename; TransferMutex.UnLock(); }
360 /** */
GetSrcFilename()361 inline CString CTransfer::GetSrcFilename() const
362 { return sSrcFilename; }
363 /** */
SetSrcFilename(CString filename)364 inline void CTransfer::SetSrcFilename( CString filename )
365 { TransferMutex.Lock(); sSrcFilename=filename; TransferMutex.UnLock(); }
366 /** */
GetDstNick()367 inline CString CTransfer::GetDstNick() const
368 { return sDstNick; }
369 /** */
GetHubHost()370 inline CString CTransfer::GetHubHost() const
371 { return sHubHost; }
372 /** */
SetHubHost(CString hubhost)373 inline void CTransfer::SetHubHost( CString hubhost )
374 { TransferMutex.Lock(); sHubHost=hubhost; TransferMutex.UnLock(); }
375 /** */
GetHubName()376 inline CString CTransfer::GetHubName() const
377 { return sHubName; }
378 /** */
SetHubName(CString hubname)379 inline void CTransfer::SetHubName( CString hubname )
380 { TransferMutex.Lock(); sHubName=hubname; TransferMutex.UnLock(); }
381 /** */
SetMedium(eltMedium medium)382 inline void CTransfer::SetMedium( eltMedium medium )
383 { TransferMutex.Lock(); eMedium=medium; TransferMutex.UnLock(); }
384 /** */
GetMedium()385 inline eltMedium CTransfer::GetMedium() const
386 { return eMedium; }
387 /** */
GetSrcDirection()388 inline eDirection CTransfer::GetSrcDirection() const
389 { return eSrcDirection; }
390 /** */
SetSrcDirection(eDirection direction)391 inline void CTransfer::SetSrcDirection( eDirection direction )
392 { TransferMutex.Lock(); eSrcDirection = direction; TransferMutex.UnLock(); }
393 /** */
GetDstDirection()394 inline eDirection CTransfer::GetDstDirection() const
395 { return eDstDirection; }
396 /** */
SetDstDirection(eDirection direction)397 inline void CTransfer::SetDstDirection( eDirection direction )
398 { TransferMutex.Lock(); eDstDirection = direction; TransferMutex.UnLock(); }
399 /** */
GetSrcLevel()400 inline int CTransfer::GetSrcLevel() const
401 { return m_nSrcLevel; }
402 /** */
GetDstLevel()403 inline int CTransfer::GetDstLevel() const
404 { return m_nDstLevel; }
405 /** */
GetMode()406 inline eConnectionState CTransfer::GetMode() const
407 { return eMode; }
408 /** */
SetMode(eConnectionState mode)409 inline void CTransfer::SetMode( eConnectionState mode )
410 { TransferMutex.Lock(); eMode = mode; TransferMutex.UnLock(); }
411 /** */
GetStartPosition()412 inline ulonglong CTransfer::GetStartPosition() const
413 { return m_nStartPosition; }
414 /** */
SetStartPosition(ulonglong pos)415 inline void CTransfer::SetStartPosition( ulonglong pos )
416 { TransferMutex.Lock(); m_nStartPosition=pos; TransferMutex.UnLock(); }
417 /** */
GetEndPosition()418 inline ulonglong CTransfer::GetEndPosition() const
419 { return m_nEndPosition; }
420 /** */
SetEndPosition(ulonglong pos)421 inline void CTransfer::SetEndPosition( ulonglong pos )
422 { TransferMutex.Lock(); m_nEndPosition=pos; TransferMutex.UnLock(); }
423 /** */
GetLength()424 inline ulonglong CTransfer::GetLength() const
425 { return m_nFileSize; }
426 /** */
SetLength(ulonglong length)427 inline void CTransfer::SetLength( ulonglong length )
428 { TransferMutex.Lock(); m_nFileSize = length; TransferMutex.UnLock(); }
429 /** */
GetTransfered()430 inline ulonglong CTransfer::GetTransfered() const
431 { return m_nTransfered; }
432 /** */
SetNick(CString nick)433 inline void CTransfer::SetNick(CString nick)
434 { TransferMutex.Lock(); sNick=nick; TransferMutex.UnLock(); }
435 /** */
GetNick()436 inline CString CTransfer::GetNick()
437 { return sNick; }
438 /** */
SetRate(ulonglong rate)439 inline void CTransfer::SetRate( ulonglong rate )
440 { TransferMutex.Lock(); m_nTransferRate=rate; TransferMutex.UnLock(); }
441 /** */
GetRate()442 inline ulonglong CTransfer::GetRate() const
443 { return m_nTransferRate; }
444 /** */
IsIdle()445 inline bool CTransfer::IsIdle() const
446 { return m_bIdle; }
447 /** */
SetCallBackFunction(_CCallback2<CTransfer,CDCMessage * > * callback)448 inline void CTransfer::SetCallBackFunction( _CCallback2<CTransfer, CDCMessage*> * callback )
449 { TransferMutex.Lock(); delete pCallback; pCallback = callback; TransferMutex.UnLock(); }
450 /** */
SetDone(eTransferState e)451 inline void CTransfer::SetDone( eTransferState e )
452 { TransferMutex.Lock(); m_eTransferState = e; TransferMutex.UnLock(); }
453 /** */
GetDone()454 inline eTransferState CTransfer::GetDone() const
455 { return m_eTransferState; }
456 /** */
GetStartTime()457 inline time_t CTransfer::GetStartTime() const
458 { return starttime.tv_sec; }
459 /** */
SetStartTime(time_t t)460 inline void CTransfer::SetStartTime( time_t t )
461 { TransferMutex.Lock(); starttime.tv_sec = t; TransferMutex.UnLock(); }
462 /** */
GetTransferID()463 inline ulonglong CTransfer::GetTransferID() const
464 { return m_nTransferID; }
465 /** */
SetTransferID(ulonglong transferid)466 inline void CTransfer::SetTransferID( ulonglong transferid )
467 { TransferMutex.Lock(); m_nTransferID = transferid; TransferMutex.UnLock(); }
468 /** */
GetTransferType()469 inline eTransferType CTransfer::GetTransferType() const
470 { return m_eTransferType; }
471 /** */
SetTransferType(eTransferType type)472 inline void CTransfer::SetTransferType( eTransferType type )
473 { TransferMutex.Lock(); m_eTransferType = type; TransferMutex.UnLock(); }
474 /** */
GetTTH()475 inline CString CTransfer::GetTTH() const
476 { return m_sTTH; }
477 /** */
SetTTH(const CString & newtth)478 inline void CTransfer::SetTTH( const CString & newtth )
479 { TransferMutex.Lock(); m_sTTH = newtth; TransferMutex.UnLock(); }
480 
481 #endif
482