1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
//
// This file is part of the aMule Project.
//
// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
// Any parts of this program derived from the xMule, lMule or eMule project,
// or contributed by third-party developers are copyrighted by their
// respective authors.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
//

#ifndef UPDOWNCLIENT_H
#define UPDOWNCLIENT_H

#include "Constants.h"		// Needed for ESourceFrom
#include "GetTickCount.h"	// Needed for GetTickCount
#include "MD4Hash.h"
#include <common/StringFunctions.h>
#include <common/Macros.h>
#include "NetworkFunctions.h"
#include "OtherStructs.h"
#include "ClientCredits.h"	// Needed for EIdentState
#include <ec/cpp/ECID.h>	// Needed for CECID
#include "BitVector.h"		// Needed for BitVector
#include "ClientRef.h"		// Needed for debug defines

#include <map>


class CPartFile;
class CClientTCPSocket;
class CPacket;
class CFriend;
class CKnownFile;
class CMemFile;
class CAICHHash;


enum EChatCaptchaState {
	CA_NONE				= 0,
	CA_CHALLENGESENT,
	CA_CAPTCHASOLVED,
	CA_ACCEPTING,
	CA_CAPTCHARECV,
	CA_SOLUTIONSENT
};

enum ESecureIdentState {
	IS_UNAVAILABLE		= 0,
	IS_ALLREQUESTSSEND	= 0,
	IS_SIGNATURENEEDED	= 1,
	IS_KEYANDSIGNEEDED	= 2
};

enum EInfoPacketState {
	IP_NONE			= 0,
	IP_EDONKEYPROTPACK	= 1,
	IP_EMULEPROTPACK	= 2,
	IP_BOTH			= 3
};

enum EKadState {
	KS_NONE,
	KS_QUEUED_FWCHECK,
	KS_CONNECTING_FWCHECK,
	KS_CONNECTED_FWCHECK,
	KS_QUEUED_BUDDY,
	KS_INCOMING_BUDDY,
	KS_CONNECTING_BUDDY,
	KS_CONNECTED_BUDDY,
	KS_QUEUED_FWCHECK_UDP,
	KS_FWCHECK_UDP,
	KS_CONNECTING_FWCHECK_UDP
};

//! Used to keep track of the state of the client
enum ClientState
{
	//! New is for clients that have just been created.
	CS_NEW = 0,
	//! Listed is for clients that are on the clientlist
	CS_LISTED,
	//! Dying signifies clients that have been queued for deletion
	CS_DYING
};

// This is fixed on ed2k v1, but can be any number on ED2Kv2
#define STANDARD_BLOCKS_REQUEST 3

class CUpDownClient : public CECID
{
	friend class CClientList;
	friend class CClientRef;
private:
	/**
	 * Please note that only the ClientList is allowed to delete the clients.
	 * To schedule a client for deletion, call the CClientList::AddToDeleteQueue
	 * function, which will safely remove dead clients once every second.
	 */
	~CUpDownClient();

	/**
	 * Reference count which is increased whenever client is linked to a clientref.
	 * Clients are to be stored only by ClientRefs, CUpDownClient * are for temporary
	 * use only.
	 * Linking is done only by CClientRef which is friend, so methods are private.
	 */
	uint16 m_linked;
#ifdef DEBUG_ZOMBIE_CLIENTS
	bool	m_linkedDebug;
	std::multiset<wxString> m_linkedFrom;
	void	Link(const wxString& from)		{ m_linked++; m_linkedFrom.insert(from); }
	void	Unlink(const wxString& from);
	wxString GetLinkedFrom() {
		wxString ret;
		for (std::multiset<wxString>::iterator it = m_linkedFrom.begin(); it != m_linkedFrom.end(); ++it) {
			ret += *it + wxT(", ");
		}
		return ret;
	}
#else
	void	Link()		{ m_linked++; }
	void	Unlink();
#endif

public:
	//base
	CUpDownClient(CClientTCPSocket* sender = 0);
	CUpDownClient(uint16 in_port, uint32 in_userid, uint32 in_serverup, uint16 in_serverport,CPartFile* in_reqfile, bool ed2kID, bool checkfriend);

	/**
	 * This function is to be called when the client object is to be deleted.
	 * It'll close the socket of the client and remove it from various lists
	 * that can own it.
	 *
	 * The client will really be deleted only after thelast reference to it
	 * is unlinked;
	 */
	void		Safe_Delete();

	/**
	 * Specifies if the client has been queued for deletion.
	 *
	 * @return True if Safe_Delete has been called, false otherwise.
	 */
	bool		HasBeenDeleted()		{ return m_clientState == CS_DYING; }

	ClientState	GetClientState()		{ return m_clientState; }

	bool		Disconnected(const wxString& strReason, bool bFromSocket = false);
	bool		TryToConnect(bool bIgnoreMaxCon = false);
	bool		Connect();
	void		ConnectionEstablished();
	const wxString&	GetUserName() const		{ return m_Username; }
	//Only use this when you know the real IP or when your clearing it.
	void		SetIP( uint32 val );
	uint32		GetIP() const			{ return m_dwUserIP; }
	bool		HasLowID() const		{ return IsLowID(m_nUserIDHybrid); }
	wxString	GetFullIP() const		{ return Uint32toStringIP(m_FullUserIP); }
	uint32		GetConnectIP() const		{ return m_nConnectIP; }
	uint32		GetUserIDHybrid() const		{ return m_nUserIDHybrid; }
	void		SetUserIDHybrid(uint32 val);
	uint16_t	GetUserPort() const		{ return m_nUserPort; }
	void		SetUserPort(uint16_t port)	{ m_nUserPort = port; }
	uint64		GetTransferredDown() const	{ return m_nTransferredDown; }
	uint32		GetServerIP() const		{ return m_dwServerIP; }
	void		SetServerIP(uint32 nIP)		{ m_dwServerIP = nIP; }
	uint16		GetServerPort()	const		{ return m_nServerPort; }
	void		SetServerPort(uint16 nPort)	{ m_nServerPort = nPort; }
	const CMD4Hash&	GetUserHash() const		{ return m_UserHash; }
	void		SetUserHash(const CMD4Hash& userhash);
	void		ValidateHash()			{ m_HasValidHash = !m_UserHash.IsEmpty(); }
	bool		HasValidHash() const		{ return m_HasValidHash; }
	uint32		GetVersion() const		{ return m_nClientVersion;}
	uint8		GetMuleVersion() const		{ return m_byEmuleVersion;}
	bool		ExtProtocolAvailable() const	{ return m_bEmuleProtocol;}
	bool		IsEmuleClient()	const		{ return (m_byEmuleVersion > 0);}
	bool		IsBanned() const;
	const wxString&	GetClientFilename() const	{ return m_clientFilename; }
	uint16		GetUDPPort() const		{ return m_nUDPPort; }
	void		SetUDPPort(uint16 nPort)	{ m_nUDPPort = nPort; }
	uint8		GetUDPVersion() const		{ return m_byUDPVer; }
	uint8		GetExtendedRequestsVersion() const { return m_byExtendedRequestsVer; }
	bool		IsFriend() const		{ return m_Friend != NULL; }
	bool		IsML() const			{ return m_bIsML; }
	bool		IsHybrid() const		{ return m_bIsHybrid; }
	uint32		GetCompatibleClient() const	{ return m_byCompatibleClient; }

	void		ClearDownloadBlockRequests();
	void		RequestSharedFileList();
	void		ProcessSharedFileList(const uint8_t* pachPacket, uint32 nSize, wxString& pszDirectory);
	void		SendSharedDirectories();
	void		SendSharedFilesOfDirectory(const wxString& strReqDir);

	wxString	GetUploadFileInfo();

	void		SetUserName(const wxString& NewName) { m_Username = NewName; }

	uint8		GetClientSoft() const		{ return m_clientSoft; }
	void		ReGetClientSoft();
	bool		ProcessHelloAnswer(const uint8_t* pachPacket, uint32 nSize);
	bool		ProcessHelloPacket(const uint8_t* pachPacket, uint32 nSize);
	void		SendHelloAnswer();
	bool		SendHelloPacket();
	void		SendMuleInfoPacket(bool bAnswer, bool OSInfo = false);
	bool		ProcessMuleInfoPacket(const uint8_t* pachPacket, uint32 nSize);
	void		ProcessMuleCommentPacket(const uint8_t* pachPacket, uint32 nSize);
	bool		Compare(const CUpDownClient* tocomp, bool bIgnoreUserhash = false) const;
	void		SetLastSrcReqTime()		{ m_dwLastSourceRequest = ::GetTickCount(); }
	void		SetLastSrcAnswerTime()		{ m_dwLastSourceAnswer = ::GetTickCount(); }
	void		SetLastAskedForSources()	{ m_dwLastAskedForSources = ::GetTickCount(); }
	uint32		GetLastSrcReqTime() const	{ return m_dwLastSourceRequest; }
	uint32		GetLastSrcAnswerTime() const	{ return m_dwLastSourceAnswer; }
	uint32		GetLastAskedForSources() const	{ return m_dwLastAskedForSources; }
	bool		GetFriendSlot() const		{ return m_bFriendSlot; }
	void		SetFriendSlot(bool bNV)		{ m_bFriendSlot = bNV; }
	void		SetCommentDirty(bool bDirty = true)	{ m_bCommentDirty = bDirty; }
	uint8		GetSourceExchange1Version() const	{ return m_bySourceExchange1Ver; }
	bool		SupportsSourceExchange2() const		{ return m_fSupportsSourceEx2; }

	bool		SafeSendPacket(CPacket* packet);

	void		ProcessRequestPartsPacket(const uint8_t* pachPacket, uint32 nSize, bool largeblocks);
	void		ProcessRequestPartsPacketv2(const CMemFile& data);

	void		SendPublicKeyPacket();
	void		SendSignaturePacket();
	void		ProcessPublicKeyPacket(const uint8_t* pachPacket, uint32 nSize);
	void		ProcessSignaturePacket(const uint8_t* pachPacket, uint32 nSize);
	uint8		GetSecureIdentState();

	void		SendSecIdentStatePacket();
	void		ProcessSecIdentStatePacket(const uint8_t* pachPacket, uint32 nSize);

	uint8		GetInfoPacketsReceived() const	{ return m_byInfopacketsReceived; }
	void		InfoPacketsReceived();

	//upload
	uint8		GetUploadState() const		{ return m_nUploadState; }
	void		SetUploadState(uint8 news);
	uint64		GetTransferredUp() const	{ return m_nTransferredUp; }
	uint64		GetSessionUp() const		{ return m_nTransferredUp - m_nCurSessionUp; }
	void		ResetSessionUp();
	uint32		GetUploadDatarate() const	{ return m_nUpDatarate; }

	//uint32		GetWaitTime() const		{ return m_dwUploadTime - GetWaitStartTime(); }
	uint32		GetUpStartTimeDelay() const	{ return ::GetTickCount() - m_dwUploadTime; }
	uint32		GetWaitStartTime() const;

	bool		IsDownloading()	const		{ return (m_nUploadState == US_UPLOADING); }

	uint32		GetScore() const	{ return m_score; }
	uint32		CalculateScore()	{ m_score = CalculateScoreInternal(); return m_score; }
	void		ClearScore()		{ m_score = 0; }
	uint16		GetUploadQueueWaitingPosition() const	{ return m_waitingPosition; }
	void		SetUploadQueueWaitingPosition(uint16 pos)	{ m_waitingPosition = pos; }
	uint8		GetObfuscationStatus() const;
	uint16		GetNextRequestedPart() const;

	void		AddReqBlock(Requested_Block_Struct* reqblock);
	void		CreateNextBlockPackage();
	void		SetUpStartTime()		{ m_dwUploadTime = ::GetTickCount(); }
	void		SetWaitStartTime();
	void		ClearWaitStartTime();
	void		SendHashsetPacket(const CMD4Hash& forfileid);
	bool		SupportMultiPacket() const	{ return m_bMultiPacket; }
	bool		SupportExtMultiPacket() const	{ return m_fExtMultiPacket; }

	void		SetUploadFileID(CKnownFile *newreqfile);

	/**
	 *Gets the file actually on upload
	 *
	 */
	const CKnownFile* GetUploadFile() const		{ return m_uploadingfile; }

	void		SendOutOfPartReqsAndAddToWaitingQueue();
	void		ProcessExtendedInfo(const CMemFile *data, CKnownFile *tempreqfile);
	void		ProcessFileInfo(const CMemFile* data, const CPartFile* file);
	void		ProcessFileStatus(bool bUdpPacket, const CMemFile* data, const CPartFile* file);

	const CMD4Hash&	GetUploadFileID() const		{ return m_requpfileid; }
	void		SetUploadFileID(const CMD4Hash& new_id);
	void		ClearUploadFileID()		{ m_requpfileid.Clear(); m_uploadingfile = NULL;}
	uint32		SendBlockData();
	void		ClearUploadBlockRequests();
	void		SendRankingInfo();
	void		SendCommentInfo(CKnownFile *file);
	bool		IsDifferentPartBlock() const;
	void		UnBan();
	void		Ban();
	bool		m_bAddNextConnect;      // VQB Fix for LowID slots only on connection
	uint32		GetAskedCount() const		{ return m_cAsked; }
	void		AddAskedCount()			{ m_cAsked++; }
	void		ClearAskedCount()		{ m_cAsked = 1; }	// 1, because it's cleared *after* the first request...
	void		FlushSendBlocks();	// call this when you stop upload,
						// or the socket might be not able to send
	void		SetLastUpRequest()		{ m_dwLastUpRequest = ::GetTickCount(); }
	uint32		GetLastUpRequest() const	{ return m_dwLastUpRequest; }
	size_t		GetUpPartCount() const		{ return m_upPartStatus.size(); }


	//download
	void		SetRequestFile(CPartFile* reqfile);
	CPartFile*	GetRequestFile() const		{ return m_reqfile; }

	uint8		GetDownloadState() const	{ return m_nDownloadState; }
	void		SetDownloadState(uint8 byNewState);
	uint32		GetLastAskedTime() const	{ return m_dwLastAskedTime; }
	void		ResetLastAskedTime()		{ m_dwLastAskedTime = 0; }

	bool		IsPartAvailable(uint16 iPart) const
					{ return ( iPart < m_downPartStatus.size() ) ? m_downPartStatus.get(iPart) : 0; }
	bool		IsUpPartAvailable(uint16 iPart) const
					{ return ( iPart < m_upPartStatus.size() ) ? m_upPartStatus.get(iPart) : 0;}

	const BitVector& GetPartStatus() const		{ return m_downPartStatus; }
	const BitVector& GetUpPartStatus() const	{ return m_upPartStatus; }
	float		GetKBpsDown() const				{ return kBpsDown; }
	float		CalculateKBpsDown();
	uint16		GetRemoteQueueRank() const	{ return m_nRemoteQueueRank; }
	uint16		GetOldRemoteQueueRank() const	{ return m_nOldRemoteQueueRank; }
	void		SetRemoteQueueFull(bool flag)	{ m_bRemoteQueueFull = flag; }
	bool		IsRemoteQueueFull() const	{ return m_bRemoteQueueFull; }
	void		SetRemoteQueueRank(uint16 nr);
	bool		AskForDownload();
	void		SendStartupLoadReq();
	void		SendFileRequest();
	void		ProcessHashSet(const uint8_t* packet, uint32 size);
	bool		AddRequestForAnotherFile(CPartFile* file);
	bool		DeleteFileRequest(CPartFile* file);
	void		DeleteAllFileRequests();
	void		SendBlockRequests();
	void		ProcessBlockPacket(const uint8_t* packet, uint32 size, bool packed, bool largeblocks);
	uint16		GetAvailablePartCount() const;

	bool		SwapToAnotherFile(bool bIgnoreNoNeeded, bool ignoreSuspensions, bool bRemoveCompletely, CPartFile* toFile = NULL);
	void		UDPReaskACK(uint16 nNewQR);
	void		UDPReaskFNF();
	void		UDPReaskForDownload();
	bool		IsSourceRequestAllowed();
	uint16		GetUpCompleteSourcesCount() const	{ return m_nUpCompleteSourcesCount; }
	void		SetUpCompleteSourcesCount(uint16 n)	{ m_nUpCompleteSourcesCount = n; }

	//chat
	uint8		GetChatState()			{ return m_byChatstate; }
	void		SetChatState(uint8 nNewS)	{ m_byChatstate = nNewS; }
	EChatCaptchaState GetChatCaptchaState() const	{ return (EChatCaptchaState)m_nChatCaptchaState; }
	void		ProcessCaptchaRequest(CMemFile* data);
	void		ProcessCaptchaReqRes(uint8 nStatus);
	void		ProcessChatMessage(wxString message);
	// message filtering
	uint8		GetMessagesReceived() const	{ return m_cMessagesReceived; }
	void		IncMessagesReceived()		{ m_cMessagesReceived < 255 ? ++m_cMessagesReceived : 255; }
	uint8		GetMessagesSent() const		{ return m_cMessagesSent; }
	void		IncMessagesSent()		{ m_cMessagesSent < 255 ? ++m_cMessagesSent : 255; }
	bool		IsSpammer() const		{ return m_fIsSpammer; }
	void		SetSpammer(bool bVal);
	bool		IsMessageFiltered(const wxString& message);

	//File Comment
	const wxString&	GetFileComment() const		{ return m_strComment; }
	uint8		GetFileRating() const		{ return m_iRating; }

	const wxString&	GetSoftStr() const		{ return m_clientSoftString; }
	const wxString&	GetSoftVerStr() const		{ return m_clientVerString; }
	const wxString GetServerName() const;

	uint16		GetKadPort() const		{ return m_nKadPort; }
	void		SetKadPort(uint16 nPort)	{ m_nKadPort = nPort; }

	// Kry - AICH import
	void		SetReqFileAICHHash(CAICHHash* val);
	CAICHHash*	GetReqFileAICHHash() const	{return m_pReqFileAICHHash;}
	bool		IsSupportingAICH() const	{return m_fSupportsAICH & 0x01;}
	void		SendAICHRequest(CPartFile* pForFile, uint16 nPart);
	bool		IsAICHReqPending() const	{return m_fAICHRequested; }
	void		ProcessAICHAnswer(const uint8_t* packet, uint32 size);
	void		ProcessAICHRequest(const uint8_t* packet, uint32 size);
	void		ProcessAICHFileHash(CMemFile* data, const CPartFile* file);

	EUtf8Str	GetUnicodeSupport() const;

	// Barry - Process zip file as it arrives, don't need to wait until end of block
	int		unzip(Pending_Block_Struct *block, uint8_t *zipped, uint32 lenZipped, uint8_t **unzipped, uint32 *lenUnzipped, int iRecursion = 0);
	void		UpdateDisplayedInfo(bool force = false);
	int		GetFileListRequested() const	{ return m_iFileListRequested; }
	void		SetFileListRequested(int iFileListRequested) { m_iFileListRequested = iFileListRequested; }

	void		ResetFileStatusInfo();

	bool		CheckHandshakeFinished() const;

	bool		GetSentCancelTransfer() const	{ return m_fSentCancelTransfer; }
	void		SetSentCancelTransfer(bool bVal)	{ m_fSentCancelTransfer = bVal; }

	DEBUG_ONLY( wxString	GetClientFullInfo(); )<--- There is an unknown macro here somewhere. Configuration is required. If DEBUG_ONLY is a macro then please configure it.
	wxString	GetClientShortInfo();

	const wxString& GetClientOSInfo() const		{ return m_sClientOSInfo; }

	void		ProcessPublicIPAnswer(const uint8_t* pbyData, uint32 uSize);
	void		SendPublicIPRequest();

	/**
	 * Sets the current socket of the client.
	 *
	 * @param socket The pointer to the new socket, can be NULL.
	 *
	 * Please note that this function DOES NOT delete the old socket.
	 */
	void		SetSocket(CClientTCPSocket* socket);

	/**
	 * Function for accessing the socket owned by a client.
	 *
	 * @return The pointer (can be NULL) to the socket used by this client.
	 *
	 * Please note that the socket object is quite volatile and can be removed
	 * from one function call to the next, therefore, you should normally use
	 * the safer functions below, which all check if the socket is valid before
	 * deferring it.
	 */
	CClientTCPSocket* GetSocket() const		{ return m_socket; }

	/**
	 * Safe function for checking if the socket is connected.
	 *
	 * @return True if the socket exists and is connected, false otherwise.
	 */
	bool		IsConnected() const;

	/**
	 * Safe function for sending packets.
	 *
	 * @return True if the socket exists and the packet was sent, false otherwise.
	 */
	bool		SendPacket(CPacket* packet, bool delpacket = true, bool controlpacket = true);

	/**
	 * Safe function for setting the download limit of the socket.
	 *
	 * @return Current download speed of the client.
	 */
	float		SetDownloadLimit(uint32 reducedownload);

	/**
	 * Sends a message to a client
	 *
	 * @return True if sent, false if connecting
	 */
	bool		SendChatMessage(const wxString& message);

	bool		HasBlocks() const		{ return !m_BlockRequests_queue.empty(); }

	/* Source comes from? */
	ESourceFrom		GetSourceFrom() const	{ return m_nSourceFrom; }
	void			SetSourceFrom(ESourceFrom val)	{ m_nSourceFrom = val; }

	/* Kad buddy support */
	// ID
	const uint8_t*	GetBuddyID() const	{ return m_achBuddyID; }
	void		SetBuddyID(const uint8_t* m_achTempBuddyID);
	bool		HasValidBuddyID() const		{ return m_bBuddyIDValid; }
	/* IP */
	void		SetBuddyIP( uint32 val )	{ m_nBuddyIP = val; }
	uint32		GetBuddyIP() const		{ return m_nBuddyIP; }
	/* Port */
	void		SetBuddyPort( uint16 val )	{ m_nBuddyPort = val; }
	uint16		GetBuddyPort() const		{ return m_nBuddyPort; }

	//KadIPCheck
	bool		SendBuddyPingPong()		{ return m_dwLastBuddyPingPongTime < ::GetTickCount(); }
	bool		AllowIncomeingBuddyPingPong()	{ return m_dwLastBuddyPingPongTime < (::GetTickCount()-(3*60*1000)); }
	void		SetLastBuddyPingPongTime()	{ m_dwLastBuddyPingPongTime = (::GetTickCount()+(10*60*1000)); }
	EKadState	GetKadState() const		{ return m_nKadState; }
	void		SetKadState(EKadState nNewS)	{ m_nKadState = nNewS; }
	uint8		GetKadVersion()			{ return m_byKadVersion; }
	void		ProcessFirewallCheckUDPRequest(CMemFile *data);
	// Kad added by me
	bool		SendBuddyPing();

	/* Returns the client hash type (SO_EMULE, mldonkey, etc) */
	int		GetHashType() const;

	/**
	 * Checks that a client isn't aggressively re-asking for files.
	 *
	 * Call this when a file is requested. If the time since the last request is
	 * less than MIN_REQUESTTIME, 3 is added to the m_Aggressiveness variable.
	 * If the time since the last request is >= MIN_REQUESTTIME, the variable is
	 * decremented by 1. The client is banned if the variable reaches 10 or above.
	 *
	 * To check if a client is aggressive use the IsClientAggressive() function.
	 *
	 * Currently this function is called when the following packets are received:
	 *  - OP_STARTUPLOADREQ
	 *  - OP_REASKFILEPING
	 */
	void		CheckForAggressive();

	const wxString&	GetClientModString() const	{ return m_strModVersion; }

	const wxString&	GetClientVerString() const	{ return m_fullClientVerString; }

	const wxString&	GetVersionString() const	{ return m_clientVersionString; }

	void		UpdateStats();

	/* Returns a pointer to the credits, only for hash purposes */
	void*		GetCreditsHash() const { return (void*)credits; }

	uint16		GetLastDownloadingPart() const { return m_lastDownloadingPart; }

	bool		GetOSInfoSupport() const { return m_fOsInfoSupport; }

	bool		GetVBTTags() const { return m_fValueBasedTypeTags; }

	uint16		GetLastPartAsked() const { return m_lastPartAsked; }

	void		SetLastPartAsked(uint16 nPart) { m_lastPartAsked = nPart; }

	CFriend*	GetFriend() const { return m_Friend; }

	void		SetFriend(CFriend* newfriend) { m_Friend = newfriend; }

	bool		IsIdentified() const;

	bool		IsBadGuy() const;

	bool		SUIFailed() const;

	bool		SUINeeded() const;

	bool		SUINotSupported() const;

	uint64		GetDownloadedTotal() const;

	uint64		GetUploadedTotal() const;

	double		GetScoreRatio() const;

	uint32		GetCreationTime() const { return m_nCreationTime; }

	bool		SupportsLargeFiles() const { return m_fSupportsLargeFiles; }

	EIdentState	GetCurrentIdentState() const { return credits ? credits->GetCurrentIdentState(GetIP()) : IS_NOTAVAILABLE; }

#ifdef __DEBUG__
	/* Kry - Debug. See connection_reason definition comment below */
	void		SetConnectionReason(const wxString& reason) { connection_reason = reason; }
#endif

	// Encryption / Obfuscation / ConnectOptions
	bool		SupportsCryptLayer() const			{ return m_fSupportsCryptLayer; }
	bool		RequestsCryptLayer() const			{ return SupportsCryptLayer() && m_fRequestsCryptLayer; }
	bool		RequiresCryptLayer() const			{ return RequestsCryptLayer() && m_fRequiresCryptLayer; }
	bool		SupportsDirectUDPCallback() const		{ return m_fDirectUDPCallback != 0 && HasValidHash() && GetKadPort() != 0; }
	uint32_t	GetDirectCallbackTimeout() const		{ return m_dwDirectCallbackTimeout; }
	bool		HasObfuscatedConnectionBeenEstablished() const	{ return m_hasbeenobfuscatinglately; }

	void		SetCryptLayerSupport(bool bVal)			{ m_fSupportsCryptLayer = bVal ? 1 : 0; }
	void		SetCryptLayerRequest(bool bVal)			{ m_fRequestsCryptLayer = bVal ? 1 : 0; }
	void		SetCryptLayerRequires(bool bVal)		{ m_fRequiresCryptLayer = bVal ? 1 : 0; }
	void		SetDirectUDPCallbackSupport(bool bVal)		{ m_fDirectUDPCallback = bVal ? 1 : 0; }
	void		SetConnectOptions(uint8_t options, bool encryption = true, bool callback = true); // shortcut, sets crypt, callback, etc from the tagvalue we receive
	bool		ShouldReceiveCryptUDPPackets() const;

	bool		HasDisabledSharedFiles() const { return m_fNoViewSharedFiles; }

private:

	CClientCredits	*credits;
	CFriend		*m_Friend;

	uint64		m_nTransferredUp;
	sint64		m_nCurQueueSessionPayloadUp;
	sint64		m_addedPayloadQueueSession;

	struct TransferredData {
		uint32	datalen;
		uint32	timestamp;
	};

	//////////////////////////////////////////////////////////
	// Upload data rate computation
	//
	uint32		m_nUpDatarate;
	uint32		m_nSumForAvgUpDataRate;
	std::list<TransferredData> m_AvarageUDR_list;


	/**
	 * This struct is used to keep track of CPartFiles which this source shares.
	 */
	struct A4AFStamp {
		//! Signifies if this sources has needed parts for this file.
		bool NeededParts;
		//! This is set when we wish to avoid swapping to this file for a while.
		uint32 timestamp;
	};

	//! I typedef in the name of readability!
	typedef std::map<CPartFile*, A4AFStamp> A4AFList;
	//! This list contains all PartFiles which this client can be used as a source for.
	A4AFList m_A4AF_list;

	/**
	 * Helper function used by SwapToAnotherFile().
	 *
	 * @param it The iterator of the PartFile to be examined.
	 * @param ignorenoneeded Do not check for the status NoNeededParts when checking the file.
	 * @param ignoresuspended Do not check the timestamp when checking the file.
	 * @return True if the file is a viable target, false otherwise.
	 *
	 * This function is used to perform checks to see if we should consider
	 * this file a viable target for A4AF swapping. Unless ignoresuspended is
	 * true, it will examine the timestamp of the file and reset it if needed.
	 */
	bool		IsValidSwapTarget( A4AFList::iterator it, bool ignorenoneeded = false, bool ignoresuspended = false );

	CPartFile*	m_reqfile;

	// base
	void		Init();
	bool		ProcessHelloTypePacket(const CMemFile& data);
	void		SendHelloTypePacket(CMemFile* data);
	void		SendFirewallCheckUDPRequest();
	void		ClearHelloProperties(); // eMule 0.42

	uint32		m_dwUserIP;
	uint32		m_nConnectIP;		// holds the supposed IP or (after we had a connection) the real IP
	uint32		m_dwServerIP;
	uint32		m_nUserIDHybrid;
	uint16_t	m_nUserPort;
	int16		m_nServerPort;
	uint32		m_nClientVersion;
	uint32		m_cSendblock;
	uint8		m_byEmuleVersion;
	uint8		m_byDataCompVer;
	bool		m_bEmuleProtocol;
	wxString	m_Username;
	uint32		m_FullUserIP;
	CMD4Hash	m_UserHash;
	bool		m_HasValidHash;
	uint16		m_nUDPPort;
	uint8		m_byUDPVer;
	uint8		m_bySourceExchange1Ver;
	uint8		m_byAcceptCommentVer;
	uint8		m_byExtendedRequestsVer;
	uint8		m_clientSoft;
	uint32		m_dwLastSourceRequest;
	uint32		m_dwLastSourceAnswer;
	uint32		m_dwLastAskedForSources;
	int		m_iFileListRequested;
	bool		m_bFriendSlot;
	bool		m_bCommentDirty;
	bool		m_bIsHybrid;
	bool		m_bIsML;
	bool		m_bSupportsPreview;
	bool		m_bUnicodeSupport;
	uint16		m_nKadPort;
	bool		m_bMultiPacket;
	ClientState	m_clientState;
	CClientTCPSocket*	m_socket;
	bool		m_fNeedOurPublicIP; // we requested our IP from this client

	// Kry - Secure User Ident import
	ESecureIdentState	m_SecureIdentState;
	uint8		m_byInfopacketsReceived;		// have we received the edonkeyprot and emuleprot packet already (see InfoPacketsReceived() )
	uint32		m_dwLastSignatureIP;
	uint8		m_bySupportSecIdent;

	uint32		m_byCompatibleClient;
	std::list<CPacket*>	m_WaitingPackets_list;
	uint32		m_lastRefreshedDLDisplay;

	//upload
	void CreateStandardPackets(const unsigned char* data,uint32 togo, Requested_Block_Struct* currentblock);
	void CreatePackedPackets(const unsigned char* data,uint32 togo, Requested_Block_Struct* currentblock);
	uint32 CalculateScoreInternal();

	uint8		m_nUploadState;
	uint32		m_dwUploadTime;
	uint32		m_cAsked;
	uint32		m_dwLastUpRequest;
	uint32		m_nCurSessionUp;
	uint16		m_nUpPartCount;
	CMD4Hash	m_requpfileid;
	uint16		m_nUpCompleteSourcesCount;
	uint32		m_score;
	uint16		m_waitingPosition;

	//! This vector contains the availability of parts for the file that the user
	//! is requesting. When changing it, be sure to call CKnownFile::UpdatePartsFrequency
	//! so that the files know the actual availability of parts.
	BitVector	m_upPartStatus;
	uint16		m_lastPartAsked;
	wxString	m_strModVersion;

	std::list<Requested_Block_Struct*>	m_BlockRequests_queue;
	std::list<Requested_Block_Struct*>	m_DoneBlocks_list;

	//download
	bool		m_bRemoteQueueFull;
	uint8		m_nDownloadState;
	uint16		m_nPartCount;
	uint32		m_dwLastAskedTime;
	wxString	m_clientFilename;
	uint64		m_nTransferredDown;
	uint16		m_lastDownloadingPart;   // last Part that was downloading
	uint16		m_cShowDR;
	uint32		m_dwLastBlockReceived;
	uint16		m_nRemoteQueueRank;
	uint16		m_nOldRemoteQueueRank;
	bool		m_bCompleteSource;
	bool		m_bReaskPending;
	bool		m_bUDPPending;
	bool		m_bHashsetRequested;

	std::list<Pending_Block_Struct*>	m_PendingBlocks_list;
	std::list<Requested_Block_Struct*>	m_DownloadBlocks_list;

	// download speed calculation
	float		kBpsDown;
	uint32		msReceivedPrev;
	uint32		bytesReceivedCycle;
	// chat
	wxString	m_strComment;
	uint8		m_byChatstate;
	uint8		m_nChatCaptchaState;
	uint8		m_cCaptchasSent;
	int8		m_iRating;
	uint8		m_cMessagesReceived;		// count of chatmessages he sent to me
	uint8		m_cMessagesSent;			// count of chatmessages I sent to him
	wxString	m_strCaptchaChallenge;
	wxString	m_strCaptchaPendingMsg;

	unsigned int
		m_fHashsetRequesting : 1, // we have sent a hashset request to this client
		m_fNoViewSharedFiles : 1, // client has disabled the 'View Shared Files' feature,
					  // if this flag is not set, we just know that we don't know
					  // for sure if it is enabled
		m_fSupportsPreview   : 1,
		m_fIsSpammer	     : 1,
		m_fSentCancelTransfer: 1, // we have sent an OP_CANCELTRANSFER in the current connection
		m_fSharedDirectories : 1, // client supports OP_ASKSHAREDIRS opcodes
		m_fSupportsAICH      : 3,
		m_fAICHRequested     : 1,
		m_fSupportsLargeFiles: 1,
		m_fSentOutOfPartReqs : 1,
		m_fExtMultiPacket    : 1,
		m_fRequestsCryptLayer: 1,
		m_fSupportsCryptLayer: 1,
		m_fRequiresCryptLayer: 1,
		m_fSupportsSourceEx2 : 1,
		m_fSupportsCaptcha   : 1,
		m_fDirectUDPCallback : 1;

	unsigned int
		m_fOsInfoSupport : 1,
		m_fValueBasedTypeTags : 1;

	/* Razor 1a - Modif by MikaelB */

	bool		m_bHelloAnswerPending;

	//! This vector contains the availability of parts for the file we requested
	//! from this user. When changing it, be sure to call CPartFile::UpdatePartsFrequency
	//! so that the files know the actual availability of parts.
	BitVector	m_downPartStatus;

	CAICHHash*	m_pReqFileAICHHash;

	ESourceFrom	m_nSourceFrom;

	/* Kad Stuff */
	uint8_t		m_achBuddyID[16];
	bool		m_bBuddyIDValid;
	uint32		m_nBuddyIP;
	uint16		m_nBuddyPort;

	EKadState	m_nKadState;

	uint8		m_byKadVersion;
	uint32		m_dwLastBuddyPingPongTime;
	uint32_t	m_dwDirectCallbackTimeout;

	//! This keeps track of aggressive requests for files.
	uint16		m_Aggressiveness;
	//! This tracks the time of the last time since a file was requested
	uint32		m_LastFileRequest;

	bool		m_OSInfo_sent;

	wxString	m_clientSoftString;	/* software name */
	wxString	m_clientVerString;	/* version + optional mod name */
	wxString	m_clientVersionString;	/* version string */
	wxString	m_fullClientVerString;	/* full info string */
	wxString	m_sClientOSInfo;
	wxString	m_pendingMessage;

	int		SecIdentSupRec;

	CKnownFile*	m_uploadingfile;

	uint8		m_MaxBlockRequests;

	// needed for stats
	uint32		m_lastClientSoft;
	uint32		m_lastClientVersion;
	wxString	m_lastOSInfo;

	/* For buddies timeout */
	uint32		m_nCreationTime;

	/* Calculation of last average speed */
	uint32		m_lastaverage;
	uint32		m_last_block_start;

	/* Save the encryption status for display when disconnected */
	bool		m_hasbeenobfuscatinglately;

	/* Kry - Debug thing. Clients created just to check their data
	   have this string set to the reason we want to check them.
	   Obviously, once checked, we disconnect them. Take that, sucker.
	   This debug code is just for me I'm afraid. */
#ifdef __DEBUG__
	wxString	connection_reason;
#endif
};


#define	MAKE_CLIENT_VERSION(mjr, min, upd) \
	((uint32)(mjr)*100U*10U*100U + (uint32)(min)*100U*10U + (uint32)(upd)*100U)


#endif // UPDOWNCLIENT_H
// File_checked_for_headers