1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )//
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
23 //
24 
25 #include "ClientTCPSocket.h"	// Interface declarations
26 
27 #include <protocol/Protocols.h>
28 #include <protocol/ed2k/Client2Client/TCP.h>
29 #include <protocol/ed2k/Client2Client/UDP.h> // Sometimes we reply with UDP packets.
30 #include <protocol/ed2k/ClientSoftware.h>
31 #include <protocol/kad2/Client2Client/TCP.h>
32 #include <common/EventIDs.h>
33 
34 #include "Preferences.h"	// Needed for thePrefs
35 #include "Packet.h"		// Needed for CPacket
36 #include "Statistics.h"		// Needed for theStats
37 #include "Logger.h"		// Neeed for logRemoteClient
38 #include "updownclient.h"	// Needed for CUpDownClient
39 #include <common/Format.h>	// Needed for CFormat
40 #include "amule.h"		// Needed for theApp
41 #include "SharedFileList.h"	// Needed for CSharedFileList
42 #include "ClientList.h"		// Needed for CClientList
43 #include "UploadQueue.h"	// Needed for CUploadQueue
44 #include "ClientUDPSocket.h"	// Needed for CClientUDPSocket
45 #include "PartFile.h"		// Needed for CPartFile
46 #include "MemFile.h"		// Needed for CMemFile
47 #include "kademlia/kademlia/Kademlia.h" // Needed for CKademlia::Kademlia
48 #include "kademlia/kademlia/Prefs.h"	// Needed for CKademlia::CPrefs
49 #include "DownloadQueue.h"	// Needed for CDownloadQueue
50 #include "Server.h"		// Needed for CServer
51 #include "ServerList.h"		// Needed for CServerList
52 #include "IPFilter.h"		// Needed for CIPFilter
53 #include "ListenSocket.h"	// Needed for CListenSocket
54 #include "GuiEvents.h"		// Needed for Notify_*
55 
56 
57 //#define __PACKET_RECV_DUMP__
58 
59 #ifndef ASIO_SOCKETS
60 
61 //------------------------------------------------------------------------------
62 // CClientTCPSocketHandler
63 //------------------------------------------------------------------------------
64 
65 class CClientTCPSocketHandler: public wxEvtHandler
66 {
67 public:
CClientTCPSocketHandler()68 	CClientTCPSocketHandler() {};
69 
70 private:
71 	void ClientTCPSocketHandler(wxSocketEvent& event);
72 	DECLARE_EVENT_TABLE()
73 };
74 
BEGIN_EVENT_TABLE(CClientTCPSocketHandler,wxEvtHandler)75 BEGIN_EVENT_TABLE(CClientTCPSocketHandler, wxEvtHandler)
76 	EVT_SOCKET(ID_CLIENTTCPSOCKET_EVENT, CClientTCPSocketHandler::ClientTCPSocketHandler)
77 END_EVENT_TABLE()
78 
79 void CClientTCPSocketHandler::ClientTCPSocketHandler(wxSocketEvent& event)
80 {
81 	wxSocketBase* baseSocket = event.GetSocket();
82 //	wxASSERT(baseSocket);	// Rather want a log message right now. Enough other wx problems. >:(
83 	if (!baseSocket) {		// WTF?
84 		AddDebugLogLineN(logClient, wxT("received bad wxSocketEvent"));
85 		return;
86 	}
87 
88 	CClientTCPSocket *socket = dynamic_cast<CClientTCPSocket *>(baseSocket);
89 	wxASSERT(socket);
90 	if (!socket) {
91 		return;
92 	}
93 
94 	if (socket->IsDestroying()) {
95 		return;
96 	}
97 
98 	switch(event.GetSocketEvent()) {
99 		case wxSOCKET_LOST:
100 			socket->OnError(0xFEFF /* SOCKET_LOST is not an error */);
101 			break;
102 		case wxSOCKET_INPUT:
103 			socket->OnReceive(0);
104 			break;
105 		case wxSOCKET_OUTPUT:
106 			socket->OnSend(0);
107 			break;
108 		case wxSOCKET_CONNECTION:
109 			// connection stablished, nothing to do about it?
110 			socket->OnConnect(socket->LastError());
111 			break;
112 		default:
113 			// Nothing should arrive here...
114 			wxFAIL;
115 			break;
116 	}
117 }
118 
119 //
120 // There can be only one. :)
121 //
122 static CClientTCPSocketHandler g_clientReqSocketHandler;
123 
124 #endif /* !ASIO_SOCKETS */
125 
126 
127 //------------------------------------------------------------------------------
128 // CClientTCPSocket
129 //------------------------------------------------------------------------------
130 
CClientTCPSocket(CUpDownClient * in_client,const CProxyData * ProxyData)131 CClientTCPSocket::CClientTCPSocket(CUpDownClient* in_client, const CProxyData *ProxyData)
132 	: CEMSocket(ProxyData)
133 {
134 	SetClient(in_client);
135 	if (in_client) {
136 		m_remoteip = wxUINT32_SWAP_ALWAYS(in_client->GetUserIDHybrid());
137 	} else {
138 		m_remoteip = 0;
139 	}
140 
141 	ResetTimeOutTimer();
142 
143 #ifndef ASIO_SOCKETS
144 	SetEventHandler(g_clientReqSocketHandler, ID_CLIENTTCPSOCKET_EVENT);
145 	SetNotify(
146 		wxSOCKET_CONNECTION_FLAG |
147 		wxSOCKET_INPUT_FLAG |
148 		wxSOCKET_OUTPUT_FLAG |
149 		wxSOCKET_LOST_FLAG);
150 #endif
151 	Notify(true);
152 
153 	theApp->listensocket->AddSocket(this);
154 	theApp->listensocket->AddConnection();
155 }
156 
~CClientTCPSocket()157 CClientTCPSocket::~CClientTCPSocket()
158 {
159 #ifndef ASIO_SOCKETS
160 	// remove event handler
161 	SetNotify(0);
162 	Notify(false);
163 #endif
164 
165 	if (m_client) {
166 		m_client->SetSocket( NULL );
167 	}
168 	m_client = NULL;
169 
170 	if (theApp->listensocket && !theApp->listensocket->OnShutdown()) {
171 		theApp->listensocket->RemoveSocket(this);
172 	}
173 }
174 
InitNetworkData()175 bool CClientTCPSocket::InitNetworkData()
176 {
177 	wxASSERT(!m_remoteip);
178 	wxASSERT(!m_client);
179 	m_remoteip = GetPeerInt();
180 
181 	MULE_CHECK(m_remoteip, false);
182 
183 	if (theApp->ipfilter->IsFiltered(m_remoteip)) {
184 		AddDebugLogLineN(logClient, wxT("Denied connection from ") + GetPeer() + wxT("(Filtered IP)"));
185 		return false;
186 	} else if (theApp->clientlist->IsBannedClient(m_remoteip)) {
187 		AddDebugLogLineN(logClient, wxT("Denied connection from ") + GetPeer() + wxT("(Banned IP)"));
188 		return false;
189 	} else {
190 		AddDebugLogLineN(logClient, wxT("Accepted connection from ") + GetPeer());
191 		return true;
192 	}
193 }
194 
ResetTimeOutTimer()195 void CClientTCPSocket::ResetTimeOutTimer()
196 {
197 	timeout_timer = ::GetTickCount();
198 }
199 
200 
CheckTimeOut()201 bool CClientTCPSocket::CheckTimeOut()
202 {
203 	// 0.42x
204 	uint32 uTimeout = GetTimeOut();
205 	if (m_client) {
206 
207 		if (m_client->GetKadState() == KS_CONNECTED_BUDDY) {
208 			//We originally ignored the timeout here for buddies.
209 			//This was a stupid idea on my part. There is now a ping/pong system
210 			//for buddies. This ping/pong system now prevents timeouts.
211 			//This release will allow lowID clients with KadVersion 0 to remain connected.
212 			//But a soon future version needs to allow these older clients to time out to prevent dead connections from continuing.
213 			//JOHNTODO: Don't forget to remove backward support in a future release.
214 			if ( m_client->GetKadVersion() == 0 ) {
215 				return false;
216 			}
217 
218 			uTimeout += MIN2MS(15);
219 		}
220 
221 		if (m_client->GetChatState() != MS_NONE) {
222 			uTimeout += CONNECTION_TIMEOUT;
223 		}
224 	}
225 
226 	if (::GetTickCount() - timeout_timer > uTimeout){
227 		timeout_timer = ::GetTickCount();
228 		Disconnect(wxT("Timeout"));
229 		return true;
230 	}
231 
232 	return false;
233 }
234 
235 
SetClient(CUpDownClient * pClient)236 void CClientTCPSocket::SetClient(CUpDownClient* pClient)
237 {
238 	m_client = pClient;
239 	if (m_client) {
240 		m_client->SetSocket( this );
241 	}
242 }
243 
244 
OnClose(int nErrorCode)245 void CClientTCPSocket::OnClose(int nErrorCode)
246 {
247 	// 0.42x
248 	wxASSERT(theApp->listensocket->IsValidSocket(this));
249 	CEMSocket::OnClose(nErrorCode);
250 	if (nErrorCode) {
251 		Disconnect(CFormat(wxT("Closed: %u")) % nErrorCode);
252 	} else {
253 		Disconnect(wxT("Close"));
254 	}
255 }
256 
257 
Disconnect(const wxString & strReason)258 void CClientTCPSocket::Disconnect(const wxString& strReason)
259 {
260 	byConnected = ES_DISCONNECTED;
261 	if (m_client) {
262 		if (m_client->Disconnected(strReason, true)) {
263 			// Somehow, Safe_Delete() is beeing called by Disconnected(),
264 			// or any other function that sets m_client to NULL,
265 			// so we must check m_client first.
266 			if (m_client) {
267 				m_client->SetSocket( NULL );
268 				m_client->Safe_Delete();
269 			}
270 		}
271 		m_client = NULL;
272 	}
273 
274 	Safe_Delete();
275 }
276 
277 
Safe_Delete()278 void CClientTCPSocket::Safe_Delete()
279 {
280 	// More paranoia - make sure client is unlinked in any case
281 	if (m_client) {
282 		m_client->SetSocket( NULL );
283 		m_client = NULL;
284 	}
285 
286 	// Destroy may be called several times
287 	byConnected = ES_DISCONNECTED;
288 	Destroy();
289 }
290 
291 
Safe_Delete_Client()292 void CClientTCPSocket::Safe_Delete_Client()
293 {
294 	if (m_client) {
295 		m_client->Safe_Delete();
296 		m_client = NULL;
297 	}
298 }
299 
300 
ProcessPacket(const byte * buffer,uint32 size,uint8 opcode)301 bool CClientTCPSocket::ProcessPacket(const byte* buffer, uint32 size, uint8 opcode)
302 {
303 	#ifdef __PACKET_RECV_DUMP__
304 	//printf("Rec: OPCODE %x \n",opcode);
305 	DumpMem(buffer, size);
306 	#endif
307 	if (!m_client && opcode != OP_HELLO) {
308 		throw wxString(wxT("Asks for something without saying hello"));
309 	} else if (m_client && opcode != OP_HELLO && opcode != OP_HELLOANSWER) {
310 		m_client->CheckHandshakeFinished();
311 	}
312 
313 	switch(opcode) {
314 		case OP_HELLOANSWER: {	// 0.43b
315 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_HELLOANSWER from ") + m_client->GetFullIP());
316 			theStats::AddDownOverheadOther(size);
317 			m_client->ProcessHelloAnswer(buffer, size);
318 
319 			// start secure identification, if
320 			//  - we have received OP_EMULEINFO and OP_HELLOANSWER (old eMule)
321 			//	- we have received eMule-OP_HELLOANSWER (new eMule)
322 			if (m_client->GetInfoPacketsReceived() == IP_BOTH) {
323 				m_client->InfoPacketsReceived();
324 			}
325 
326 			// Socket might die because of sending in InfoPacketsReceived, so check
327 			if (m_client) {
328 				m_client->ConnectionEstablished();
329 			}
330 
331 			// Socket might die on ConnectionEstablished somehow. Check it.
332 			if (m_client) {
333 				Notify_SharedCtrlRefreshClient( m_client->ECID() , AVAILABLE_SOURCE);
334 			}
335 
336 			break;
337 		}
338 		case OP_HELLO: {	// 0.43b
339 
340 			theStats::AddDownOverheadOther(size);
341 			bool bNewClient = !m_client;
342 			if (bNewClient) {
343 				// create new client to save standart informations
344 				m_client = new CUpDownClient(this);
345 			}
346 
347 			// Do not move up!
348 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_HELLO from ") + m_client->GetFullIP() );
349 
350 			bool bIsMuleHello = false;
351 
352 			try{
353 				bIsMuleHello = m_client->ProcessHelloPacket(buffer, size);
354 			} catch(...) {
355 				if (bNewClient && m_client) {
356 					// Don't let CUpDownClient::Disconnected be processed for a client which is not in the list of clients.
357 					m_client->Safe_Delete();
358 					m_client = NULL;
359 				}
360 				throw;
361 			}
362 
363 			if (thePrefs::ParanoidFilter() && !IsLowID(m_client->GetUserIDHybrid()) && (GetRemoteIP() != wxUINT32_SWAP_ALWAYS(m_client->GetUserIDHybrid()))) {
364 				wxString reason = wxT("Client claims a different IP from the one we received the hello packet from: ");
365 				reason += Uint32toStringIP(wxUINT32_SWAP_ALWAYS(m_client->GetUserIDHybrid())) + wxT(" / ") + Uint32toStringIP(GetRemoteIP());
366 				AddDebugLogLineN(logClient, reason);
367 				if (bNewClient) {
368 					m_client->Safe_Delete();
369 					m_client = NULL;
370 				}
371 				Disconnect(wxT("Paranoid disconecting: ") + reason);
372 				return false;
373 			}
374 
375 			// if IP is filtered, dont reply but disconnect...
376 			if (theApp->ipfilter->IsFiltered(m_client->GetIP())) {
377 				if (bNewClient) {
378 					m_client->Safe_Delete();
379 					m_client = NULL;
380 				}
381 				Disconnect(wxT("IPFilter"));
382 				return false;
383 			}
384 
385 			wxASSERT(m_client);
386 
387 			// now we check if we know this client already. if yes this socket will
388 			// be attached to the known client, the new client will be deleted
389 			// and the var. "client" will point to the known client.
390 			// if not we keep our new-constructed client ;)
391 			if (theApp->clientlist->AttachToAlreadyKnown(&m_client,this)) {
392 				// update the old client informations
393 				bIsMuleHello = m_client->ProcessHelloPacket(buffer, size);
394 			} else {
395 				theApp->clientlist->AddClient(m_client);
396 				m_client->SetCommentDirty();
397 			}
398 			Notify_SharedCtrlRefreshClient( m_client->ECID(), AVAILABLE_SOURCE );
399 			// send a response packet with standart informations
400 			if ((m_client->GetHashType() == SO_EMULE) && !bIsMuleHello) {
401 				m_client->SendMuleInfoPacket(false);
402 			}
403 
404 			// Client might die from Sending in SendMuleInfoPacket, so check
405 			if ( m_client ) {
406 				m_client->SendHelloAnswer();
407 			}
408 
409 			// Kry - If the other side supports it, send OS_INFO
410 			// Client might die from Sending in SendHelloAnswer, so check
411 			if (m_client && m_client->GetOSInfoSupport()) {
412 				m_client->SendMuleInfoPacket(false,true); // Send the OS Info tag on the recycled Mule Info
413 			}
414 
415 			// Client might die from Sending in SendMuleInfoPacket, so check
416 			if ( m_client ) {
417 				m_client->ConnectionEstablished();
418 			}
419 
420 			// start secure identification, if
421 			//	- we have received eMule-OP_HELLO (new eMule)
422 			if (m_client && m_client->GetInfoPacketsReceived() == IP_BOTH) {
423 					m_client->InfoPacketsReceived();
424 			}
425 
426 			break;
427 		}
428 		case OP_REQUESTFILENAME: {	// 0.43b
429 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQUESTFILENAME from ") + m_client->GetFullIP() );
430 
431 			theStats::AddDownOverheadFileRequest(size);
432 			// IP banned, no answer for this request
433 			if (m_client->IsBanned()) {
434 				break;
435 			}
436 			if (size >= 16) {
437 				if (!m_client->GetWaitStartTime()) {
438 					m_client->SetWaitStartTime();
439 				}
440 				CMemFile data_in(buffer, size);
441 				CMD4Hash reqfilehash = data_in.ReadHash();
442 				CKnownFile *reqfile = theApp->sharedfiles->GetFileByID(reqfilehash);
443 				if ( reqfile == NULL ) {
444 					reqfile = theApp->downloadqueue->GetFileByID(reqfilehash);
445 					if ( !( reqfile != NULL && reqfile->GetFileSize() > PARTSIZE ) ) {
446 						break;
447 					}
448 				}
449 				// if we are downloading this file, this could be a new source
450 				// no passive adding of files with only one part
451 				if (reqfile->IsPartFile() && reqfile->GetFileSize() > PARTSIZE) {
452 					if (thePrefs::GetMaxSourcePerFile() > static_cast<CPartFile*>(reqfile)->GetSourceCount()) {
453 						theApp->downloadqueue->CheckAndAddKnownSource(static_cast<CPartFile*>(reqfile), m_client);
454 					}
455 				}
456 
457 				// check to see if this is a new file they are asking for
458 				if (m_client->GetUploadFileID() != reqfilehash) {
459 						m_client->SetCommentDirty();
460 				}
461 
462 				m_client->SetUploadFileID(reqfile);
463 				m_client->ProcessExtendedInfo(&data_in, reqfile);
464 
465 				// send filename etc
466 				CMemFile data_out(128);
467 				data_out.WriteHash(reqfile->GetFileHash());
468 
469 				// Since it's for somebody else to see, we need to send the prettified
470 				// filename, rather than the (possibly) mangled actual filename.
471 				data_out.WriteString(reqfile->GetFileName().GetPrintable(), m_client->GetUnicodeSupport());
472 
473 				CPacket* packet = new CPacket(data_out, OP_EDONKEYPROT, OP_REQFILENAMEANSWER);
474 				theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
475 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_REQFILENAMEANSWER to ") + m_client->GetFullIP() );
476 				SendPacket(packet,true);
477 
478 				// SendPacket might kill the socket, so check
479 				if (m_client)
480 					m_client->SendCommentInfo(reqfile);
481 
482 				break;
483 			}
484 			throw wxString(wxT("Invalid OP_REQUESTFILENAME packet size"));
485 			break;
486 		}
487 		case OP_SETREQFILEID: {	// 0.43b EXCEPT track of bad clients
488 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_SETREQFILEID from ") + m_client->GetFullIP() );
489 
490 			theStats::AddDownOverheadFileRequest(size);
491 
492 			if (m_client->IsBanned()) {
493 				break;
494 			}
495 
496 			// DbT:FileRequest
497 			if (size == 16) {
498 				if (!m_client->GetWaitStartTime()) {
499 					m_client->SetWaitStartTime();
500 				}
501 
502 				const CMD4Hash fileID(buffer);
503 				CKnownFile *reqfile = theApp->sharedfiles->GetFileByID(fileID);
504 				if ( reqfile == NULL ) {
505 					reqfile = theApp->downloadqueue->GetFileByID(fileID);
506 					if ( !( reqfile  != NULL && reqfile->GetFileSize() > PARTSIZE ) ) {
507 						CPacket* replypacket = new CPacket(OP_FILEREQANSNOFIL, 16, OP_EDONKEYPROT);
508 						replypacket->Copy16ToDataBuffer(fileID.GetHash());
509 						theStats::AddUpOverheadFileRequest(replypacket->GetPacketSize());
510 						AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_FILERE to ") + m_client->GetFullIP() );
511 						SendPacket(replypacket, true);
512 						break;
513 					}
514 				}
515 
516 				// check to see if this is a new file they are asking for
517 				if (m_client->GetUploadFileID() != fileID) {
518 					m_client->SetCommentDirty();
519 				}
520 
521 				m_client->SetUploadFileID(reqfile);
522 				// send filestatus
523 				CMemFile data(16+16);
524 				data.WriteHash(reqfile->GetFileHash());
525 				if (reqfile->IsPartFile()) {
526 					static_cast<CPartFile*>(reqfile)->WritePartStatus(&data);
527 				} else {
528 					data.WriteUInt16(0);
529 				}
530 				CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_FILESTATUS);
531 				theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
532 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_FILESTATUS to ") + m_client->GetFullIP() );
533 				SendPacket(packet, true);
534 				break;
535 			}
536 			throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
537 			break;
538 			// DbT:End
539 		}
540 
541 		case OP_FILEREQANSNOFIL: {	// 0.43b protocol, lacks ZZ's download manager on swap
542 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_FILEREQANSNOFIL from ") + m_client->GetFullIP() );
543 
544 			theStats::AddDownOverheadFileRequest(size);
545 			if (size == 16) {
546 				// if that client does not have my file maybe has another different
547 				CPartFile* reqfile = theApp->downloadqueue->GetFileByID(CMD4Hash(buffer));
548 				if ( reqfile) {
549 					reqfile->AddDeadSource( m_client );
550 				} else {
551 					break;
552 				}
553 
554 				// we try to swap to another file ignoring no needed parts files
555 				switch (m_client->GetDownloadState()) {
556 					case DS_CONNECTED:
557 					case DS_ONQUEUE:
558 					case DS_NONEEDEDPARTS:
559 					if (!m_client->SwapToAnotherFile(true, true, true, NULL)) {
560 						theApp->downloadqueue->RemoveSource(m_client);
561 					}
562 					break;
563 				}
564 				break;
565 			}
566 			throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
567 			break;
568 		}
569 
570 		case OP_REQFILENAMEANSWER: {	// 0.43b except check for bad clients
571 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQFILENAMEANSWER from ") + m_client->GetFullIP() );
572 
573 			theStats::AddDownOverheadFileRequest(size);
574 			CMemFile data(buffer, size);
575 			CMD4Hash hash = data.ReadHash();
576 			const CPartFile* file = theApp->downloadqueue->GetFileByID(hash);
577 			m_client->ProcessFileInfo(&data, file);
578 			break;
579 		}
580 
581 		case OP_FILESTATUS: {		// 0.43b except check for bad clients
582 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_FILESTATUS from ") + m_client->GetFullIP() );
583 
584 			theStats::AddDownOverheadFileRequest(size);
585 			CMemFile data(buffer, size);
586 			CMD4Hash hash = data.ReadHash();
587 			const CPartFile* file = theApp->downloadqueue->GetFileByID(hash);
588 			m_client->ProcessFileStatus(false, &data, file);
589 			break;
590 		}
591 
592 		case OP_STARTUPLOADREQ: {
593 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_STARTUPLOADREQ from ") + m_client->GetFullIP() );
594 
595 			theStats::AddDownOverheadFileRequest(size);
596 
597 			if (!m_client->CheckHandshakeFinished()) {
598 				break;
599 			}
600 
601 			m_client->CheckForAggressive();
602 			if ( m_client->IsBanned() ) {
603 				break;
604 			}
605 
606 			if (size == 16) {
607 				const CMD4Hash fileID(buffer);
608 				CKnownFile* reqfile = theApp->sharedfiles->GetFileByID(fileID);
609 				if (reqfile) {
610 					if (m_client->GetUploadFileID() != fileID) {
611 						m_client->SetCommentDirty();
612 					}
613 					m_client->SetUploadFileID(reqfile);
614 					m_client->SendCommentInfo(reqfile);
615 
616 					// Socket might die because of SendCommentInfo, so check
617 					if (m_client)
618 						theApp->uploadqueue->AddClientToQueue(m_client);
619 				}
620 			}
621 			break;
622 		}
623 
624 		case OP_QUEUERANK: {	// 0.43b
625 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_QUEUERANK from ") + m_client->GetFullIP() );
626 
627 			theStats::AddDownOverheadFileRequest(size);
628 			CMemFile data(buffer, size);
629 			uint32 rank = data.ReadUInt32();
630 
631 			m_client->SetRemoteQueueRank(rank);
632 			break;
633 		}
634 
635 		case OP_ACCEPTUPLOADREQ: {	// 0.42e (xcept khaos stats)
636 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ACCEPTUPLOADREQ from ") + m_client->GetFullIP() );
637 
638 			theStats::AddDownOverheadFileRequest(size);
639 			if (m_client->GetRequestFile() && !m_client->GetRequestFile()->IsStopped() && (m_client->GetRequestFile()->GetStatus()==PS_READY || m_client->GetRequestFile()->GetStatus()==PS_EMPTY)) {
640 				if (m_client->GetDownloadState() == DS_ONQUEUE ) {
641 					m_client->SetDownloadState(DS_DOWNLOADING);
642 					m_client->SetLastPartAsked(0xffff); // Reset current downloaded Chunk // Maella -Enhanced Chunk Selection- (based on jicxicmic)
643 					m_client->SendBlockRequests();
644 				}
645 			} else {
646 				if (!m_client->GetSentCancelTransfer()) {
647 					CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
648 					theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
649 					AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client->GetFullIP() );
650 					m_client->SendPacket(packet,true,true);
651 
652 					// SendPacket can cause the socket to die, so check
653 					if (m_client)
654 						m_client->SetSentCancelTransfer(1);
655 				}
656 
657 				if (m_client)
658 					m_client->SetDownloadState((m_client->GetRequestFile()==NULL || m_client->GetRequestFile()->IsStopped()) ? DS_NONE : DS_ONQUEUE);
659 			}
660 			break;
661 		}
662 
663 		case OP_REQUESTPARTS: {		// 0.43b
664 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQUESTPARTS from ") + m_client->GetFullIP() );
665 
666 			theStats::AddDownOverheadFileRequest(size);
667 
668 			m_client->ProcessRequestPartsPacket(buffer, size, false);
669 
670 			break;
671 		}
672 
673 		case OP_CANCELTRANSFER: {		// 0.43b
674 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_CANCELTRANSFER from ") + m_client->GetFullIP() );
675 
676 			theStats::AddDownOverheadFileRequest(size);
677 			theApp->uploadqueue->RemoveFromUploadQueue(m_client);
678 			AddDebugLogLineN( logClient, m_client->GetUserName() + wxT(": Upload session ended due canceled transfer."));
679 			break;
680 		}
681 
682 		case OP_END_OF_DOWNLOAD: { // 0.43b except check for bad clients
683 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_END_OF_DOWNLOAD from ") + m_client->GetFullIP() );
684 
685 			theStats::AddDownOverheadFileRequest(size);
686 			if (size>=16 && m_client->GetUploadFileID() == CMD4Hash(buffer)) {
687 				theApp->uploadqueue->RemoveFromUploadQueue(m_client);
688 				AddDebugLogLineN( logClient, m_client->GetUserName() + wxT(": Upload session ended due ended transfer."));
689 			}
690 			break;
691 		}
692 
693 		case OP_HASHSETREQUEST: {		// 0.43b except check for bad clients
694 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_HASHSETREQUEST from ") + m_client->GetFullIP() );
695 
696 
697 			theStats::AddDownOverheadFileRequest(size);
698 			if (size != 16) {
699 				throw wxString(wxT("Invalid OP_HASHSETREQUEST packet size"));
700 			}
701 			m_client->SendHashsetPacket(CMD4Hash(buffer));
702 			break;
703 		}
704 
705 		case OP_HASHSETANSWER: {		// 0.43b
706 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_HASHSETANSWER from ") + m_client->GetFullIP() );
707 
708 			theStats::AddDownOverheadFileRequest(size);
709 			m_client->ProcessHashSet(buffer, size);
710 			break;
711 		}
712 
713 		case OP_SENDINGPART: {		// 0.47a
714 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_SENDINGPART from ") + m_client->GetFullIP() );
715 
716 			if (	 m_client->GetRequestFile() &&
717 				!m_client->GetRequestFile()->IsStopped() &&
718 				(m_client->GetRequestFile()->GetStatus() == PS_READY || m_client->GetRequestFile()->GetStatus()==PS_EMPTY)) {
719 
720 				m_client->ProcessBlockPacket(buffer, size, false, false);
721 
722 				if (	m_client &&
723 					( m_client->GetRequestFile()->IsStopped() ||
724 					  m_client->GetRequestFile()->GetStatus() == PS_PAUSED ||
725 					  m_client->GetRequestFile()->GetStatus() == PS_ERROR) ) {
726 					if (!m_client->GetSentCancelTransfer()) {
727 						CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
728 						theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
729 						AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client->GetFullIP() );
730 						m_client->SendPacket(packet,true,true);
731 
732 						// Socket might die because of SendPacket, so check
733 						if (m_client)
734 							m_client->SetSentCancelTransfer(1);
735 					}
736 
737 					if (m_client)
738 						m_client->SetDownloadState(m_client->GetRequestFile()->IsStopped() ? DS_NONE : DS_ONQUEUE);
739 				}
740 			} else {
741 				if (!m_client->GetSentCancelTransfer()) {
742 					CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
743 					theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
744 					AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client->GetFullIP() );
745 					m_client->SendPacket(packet,true,true);
746 
747 					// Socket might die because of SendPacket, so check
748 					m_client->SetSentCancelTransfer(1);
749 				}
750 				m_client->SetDownloadState((m_client->GetRequestFile()==NULL || m_client->GetRequestFile()->IsStopped()) ? DS_NONE : DS_ONQUEUE);
751 			}
752 			break;
753 		}
754 
755 		case OP_OUTOFPARTREQS: {	// 0.43b
756 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_OUTOFPARTREQS from ") + m_client->GetFullIP() );
757 
758 			theStats::AddDownOverheadFileRequest(size);
759 			if (m_client->GetDownloadState() == DS_DOWNLOADING) {
760 				m_client->SetDownloadState(DS_ONQUEUE);
761 			}
762 			break;
763 		}
764 
765 		case OP_CHANGE_CLIENT_ID: {	// Kad reviewed
766 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_CHANGE_CLIENT_ID from ") + m_client->GetFullIP() );
767 
768 			theStats::AddDownOverheadOther(size);
769 			CMemFile data(buffer, size);
770 			uint32 nNewUserID = data.ReadUInt32();
771 			uint32 nNewServerIP = data.ReadUInt32();
772 
773 			if (IsLowID(nNewUserID)) { // client changed server and gots a LowID
774 				CServer* pNewServer = theApp->serverlist->GetServerByIP(nNewServerIP);
775 				if (pNewServer != NULL){
776 					m_client->SetUserIDHybrid(nNewUserID); // update UserID only if we know the server
777 					m_client->SetServerIP(nNewServerIP);
778 					m_client->SetServerPort(pNewServer->GetPort());
779 				}
780 			} else if (nNewUserID == m_client->GetIP()) { // client changed server and gots a HighID(IP)
781 				m_client->SetUserIDHybrid(wxUINT32_SWAP_ALWAYS(nNewUserID));
782 				CServer* pNewServer = theApp->serverlist->GetServerByIP(nNewServerIP);
783 				if (pNewServer != NULL){
784 					m_client->SetServerIP(nNewServerIP);
785 					m_client->SetServerPort(pNewServer->GetPort());
786 				}
787 			}
788 
789 			break;
790 		}
791 
792 		case OP_CHANGE_SLOT:{	// 0.43b
793 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_CHANGE_SLOT from ") + m_client->GetFullIP() );
794 
795 			// sometimes sent by Hybrid
796 			theStats::AddDownOverheadOther(size);
797 			break;
798 		}
799 
800 		case OP_MESSAGE: {		// 0.43b
801 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MESSAGE from ") + m_client->GetFullIP() );
802 
803 			theStats::AddDownOverheadOther(size);
804 
805 			if (size < 2) {
806 				throw wxString(wxT("invalid message packet"));
807 			}
808 			CMemFile message_file(buffer, size);
809 			uint16 length = message_file.ReadUInt16();
810 			if (length + 2u != size) {
811 				throw wxString(wxT("invalid message packet"));
812 			}
813 
814 			// limit message length
815 			static const uint16 MAX_CLIENT_MSG_LEN = 450;
816 
817 			if (length > MAX_CLIENT_MSG_LEN) {
818 				AddDebugLogLineN(logRemoteClient, CFormat(wxT("Message from '%s' (IP:%s) exceeds limit by %u chars, truncated."))
819 					% m_client->GetUserName() % m_client->GetFullIP() % (length - MAX_CLIENT_MSG_LEN));
820 				length = MAX_CLIENT_MSG_LEN;
821 			}
822 
823 			wxString message = message_file.ReadOnlyString((m_client->GetUnicodeSupport() != utf8strNone), length);
824 			m_client->ProcessChatMessage(message);
825 
826 			break;
827 		}
828 
829 		case OP_ASKSHAREDFILES:	{	// 0.43b (well, er, it does the same, but in our own way)
830 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDFILES from ") + m_client->GetFullIP() );
831 
832 			// client wants to know what we have in share, let's see if we allow him to know that
833 			theStats::AddDownOverheadOther(size);
834 			// IP banned, no answer for this request
835 			if (m_client->IsBanned()) {
836 				break;
837 			}
838 
839 			if (thePrefs::CanSeeShares() == vsfaEverybody || (thePrefs::CanSeeShares() == vsfaFriends && m_client->IsFriend())) {
840 				AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Accepted"))
841 					% m_client->GetUserName()
842 					% m_client->GetUserIDHybrid() );
843 
844 				std::vector<CKnownFile*> list;
845 				theApp->sharedfiles->CopyFileList(list);
846 
847 				CMemFile tempfile(80);
848 				tempfile.WriteUInt32(list.size());
849 				for (unsigned i = 0; i < list.size(); ++i) {
850 					if (!list[i]->IsLargeFile() || m_client->SupportsLargeFiles()) {
851 						list[i]->CreateOfferedFilePacket(&tempfile, NULL, m_client);
852 					}
853 				}
854 
855 				// create a packet and send it
856 				CPacket* replypacket = new CPacket(tempfile, OP_EDONKEYPROT, OP_ASKSHAREDFILESANSWER);
857 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDFILESANSWER to ") + m_client->GetFullIP() );
858 				theStats::AddUpOverheadOther(replypacket->GetPacketSize());
859 				SendPacket(replypacket, true, true);
860 			} else {
861 				AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Denied"))
862 					% m_client->GetUserName()
863 					% m_client->GetUserIDHybrid() );
864 
865 				CPacket* replypacket = new CPacket(OP_ASKSHAREDDENIEDANS, 0, OP_EDONKEYPROT);
866 				theStats::AddUpOverheadOther(replypacket->GetPacketSize());
867 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client->GetFullIP() );
868 				SendPacket(replypacket, true, true);
869 			}
870 
871 			break;
872 		}
873 
874 		case OP_ASKSHAREDFILESANSWER: {	// 0.43b
875 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDFILESANSWER from ") + m_client->GetFullIP() );
876 
877 			theStats::AddDownOverheadOther(size);
878 			wxString EmptyStr;
879 			m_client->ProcessSharedFileList(buffer, size, EmptyStr);
880 			break;
881 		}
882 
883 		case OP_ASKSHAREDDIRS: {		// 0.43b
884 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDDIRS from ") + m_client->GetFullIP() );
885 
886 			theStats::AddDownOverheadOther(size);
887 			wxASSERT( size == 0 );
888 			// IP banned, no answer for this request
889 			if (m_client->IsBanned()) {
890 				break;
891 			}
892 			if ((thePrefs::CanSeeShares()==vsfaEverybody) || ((thePrefs::CanSeeShares()==vsfaFriends) && m_client->IsFriend())) {
893 				AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Accepted") )
894 					% m_client->GetUserName()
895 					% m_client->GetUserIDHybrid() );
896 				// send the list of shared directories
897 				m_client->SendSharedDirectories();
898 			} else {
899 				AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Denied") )
900 					% m_client->GetUserName()
901 					% m_client->GetUserIDHybrid() );
902 
903 				CPacket* replypacket = new CPacket(OP_ASKSHAREDDENIEDANS, 0, OP_EDONKEYPROT);
904 				theStats::AddUpOverheadOther(replypacket->GetPacketSize());
905 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client->GetFullIP() );
906 				SendPacket(replypacket, true, true);
907 			}
908 
909 			break;
910 		}
911 
912 		case OP_ASKSHAREDFILESDIR: {	// 0.43b
913 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDFILESDIR from ") + m_client->GetFullIP() );
914 
915 			theStats::AddDownOverheadOther(size);
916 			// IP banned, no answer for this request
917 			if (m_client->IsBanned()) {
918 				break;
919 			}
920 			CMemFile data(buffer, size);
921 
922 			wxString strReqDir = data.ReadString((m_client->GetUnicodeSupport() != utf8strNone));
923 			if (thePrefs::CanSeeShares()==vsfaEverybody || (thePrefs::CanSeeShares()==vsfaFriends && m_client->IsFriend())) {
924 				AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> accepted")) % m_client->GetUserName() % m_client->GetUserIDHybrid() % strReqDir);
925 				wxASSERT( data.GetPosition() == data.GetLength() );
926 				// send the list of shared files for the requested directory
927 				m_client->SendSharedFilesOfDirectory(strReqDir);
928 			} else {
929 				AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> denied")) % m_client->GetUserName() % m_client->GetUserIDHybrid() % strReqDir);
930 
931 				CPacket* replypacket = new CPacket(OP_ASKSHAREDDENIEDANS, 0, OP_EDONKEYPROT);
932 				theStats::AddUpOverheadOther(replypacket->GetPacketSize());
933 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client->GetFullIP() );
934 				SendPacket(replypacket, true, true);
935 			}
936 			break;
937 		}
938 
939 		case OP_ASKSHAREDDIRSANS:{		// 0.43b
940 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDDIRSANS from ") + m_client->GetFullIP() );
941 
942 			theStats::AddDownOverheadOther(size);
943 			if (m_client->GetFileListRequested() == 1){
944 				CMemFile data(buffer, size);
945 				uint32 uDirs = data.ReadUInt32();
946 				for (uint32 i = 0; i < uDirs; i++){
947 					wxString strDir = data.ReadString((m_client->GetUnicodeSupport() != utf8strNone));
948 					AddLogLineC(CFormat( _("User %s (%u) shares directory '%s'") )
949 						% m_client->GetUserName()
950 						% m_client->GetUserIDHybrid()
951 						% strDir );
952 
953 					CMemFile tempfile(80);
954 					tempfile.WriteString(strDir, m_client->GetUnicodeSupport());
955 					CPacket* replypacket = new CPacket(tempfile, OP_EDONKEYPROT, OP_ASKSHAREDFILESDIR);
956 					theStats::AddUpOverheadOther(replypacket->GetPacketSize());
957 					AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDFILESDIR to ") + m_client->GetFullIP() );
958 					SendPacket(replypacket, true, true);
959 				}
960 				wxASSERT( data.GetPosition() == data.GetLength() );
961 				m_client->SetFileListRequested(uDirs);
962 			} else {
963 				AddLogLineC(CFormat( _("User %s (%u) sent unrequested shared dirs.") )
964 					% m_client->GetUserName()
965 					% m_client->GetUserIDHybrid() );
966 			}
967 			break;
968 		}
969 
970 		case OP_ASKSHAREDFILESDIRANS: {		// 0.43b
971 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDFILESDIRANS from ") + m_client->GetFullIP() );
972 
973 			theStats::AddDownOverheadOther(size);
974 			CMemFile data(buffer, size);
975 			wxString strDir = data.ReadString((m_client->GetUnicodeSupport() != utf8strNone));
976 
977 			if (m_client->GetFileListRequested() > 0){
978 				AddLogLineC(CFormat( _("User %s (%u) sent sharedfiles-list for directory '%s'") )
979 					% m_client->GetUserName()
980 					% m_client->GetUserIDHybrid()
981 					% strDir );
982 
983 				m_client->ProcessSharedFileList(buffer + data.GetPosition(), size - data.GetPosition(), strDir);
984 				if (m_client->GetFileListRequested() == 0) {
985 					AddLogLineC(CFormat( _("User %s (%u) finished sending sharedfiles-list") )
986 						% m_client->GetUserName()
987 						% m_client->GetUserIDHybrid() );
988 				}
989 			} else {
990 				AddLogLineC(CFormat( _("User %s (%u) sent unwanted sharedfiles-list") )
991 					% m_client->GetUserName()
992 					% m_client->GetUserIDHybrid() );
993 			}
994 			break;
995 		}
996 
997 		case OP_ASKSHAREDDENIEDANS:
998 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ASKSHAREDDENIEDANS from ") + m_client->GetFullIP() );
999 
1000 			theStats::AddDownOverheadOther(size);
1001 			wxASSERT( size == 0 );
1002 			AddLogLineC(CFormat( _("User %s (%u) denied access to shared directories/files list") )
1003 				% m_client->GetUserName()
1004 				% m_client->GetUserIDHybrid() );
1005 
1006 			m_client->SetFileListRequested(0);
1007 			break;
1008 
1009 		default:
1010 			theStats::AddDownOverheadOther(size);
1011 			AddDebugLogLineN(logRemoteClient, CFormat(wxT("Edonkey packet: unknown opcode: %i %x from %s")) % opcode % opcode % m_client->GetFullIP());
1012 			return false;
1013 	}
1014 
1015 	return true;
1016 }
1017 
1018 
ProcessExtPacket(const byte * buffer,uint32 size,uint8 opcode)1019 bool CClientTCPSocket::ProcessExtPacket(const byte* buffer, uint32 size, uint8 opcode)
1020 {
1021 	#ifdef __PACKET_RECV_DUMP__
1022 	//printf("Rec: OPCODE %x \n",opcode);
1023 	DumpMem(buffer,size);
1024 	#endif
1025 
1026 	// 0.42e - except the catchs on mem exception and file exception
1027 	if (!m_client) {
1028 		throw wxString(wxT("Unknown clients sends extended protocol packet"));
1029 	}
1030 	/*
1031 	if (!client->CheckHandshakeFinished()) {
1032 		// Here comes an extended packet without finishing the handshake.
1033 		// IMHO, we should disconnect the client.
1034 		throw wxString(wxT("Client send extended packet before finishing handshake"));
1035 	}
1036 	*/
1037 	switch(opcode) {
1038 		case OP_MULTIPACKET_EXT:
1039 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET_EXT from ") + m_client->GetFullIP());
1040 		/* fall through */
1041 		case OP_MULTIPACKET: {
1042 			if (opcode == OP_MULTIPACKET) AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET from ") + m_client->GetFullIP() );
1043 
1044 			theStats::AddDownOverheadFileRequest(size);
1045 
1046 			if (m_client->IsBanned()) {
1047 				break;
1048 			}
1049 
1050 			if (!m_client->CheckHandshakeFinished()) {
1051 				// Here comes an extended packet without finishing the handshake.
1052 				// IMHO, we should disconnect the client.
1053 				throw wxString(wxT("Client send OP_MULTIPACKET before finishing handshake"));
1054 			}
1055 
1056 			CMemFile data_in(buffer, size);
1057 			CMD4Hash reqfilehash = data_in.ReadHash();
1058 			uint64 nSize = (opcode == OP_MULTIPACKET_EXT) ? data_in.ReadUInt64() : 0;
1059 
1060 			bool file_not_found = false;
1061 			CKnownFile* reqfile = theApp->sharedfiles->GetFileByID(reqfilehash);
1062 			if ( reqfile == NULL ){
1063 				reqfile = theApp->downloadqueue->GetFileByID(reqfilehash);
1064 				if ( !( reqfile != NULL && reqfile->GetFileSize() > PARTSIZE ) ) {
1065 					AddDebugLogLineN(logRemoteClient, wxT("Remote client asked for a non-shared file"));
1066 					file_not_found = true;
1067 				}
1068 			}
1069 
1070 			if (!file_not_found && reqfile->IsLargeFile() && !m_client->SupportsLargeFiles()) {
1071 				AddDebugLogLineN(logRemoteClient, wxT("Remote client asked for a large file but doesn't support them"));
1072 				file_not_found = true;
1073 			}
1074 
1075 			if (!file_not_found && nSize && (reqfile->GetFileSize() != nSize)) {
1076 				AddDebugLogLineN(logRemoteClient, wxT("Remote client asked for a file but specified wrong size"));
1077 				file_not_found = true;
1078 			}
1079 
1080 			if (file_not_found) {
1081 				CPacket* replypacket = new CPacket(OP_FILEREQANSNOFIL, 16, OP_EDONKEYPROT);
1082 				replypacket->Copy16ToDataBuffer(reqfilehash.GetHash());
1083 				theStats::AddUpOverheadFileRequest(replypacket->GetPacketSize());
1084 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_FILEREQANSNOFIL to ") + m_client->GetFullIP() );
1085 				SendPacket(replypacket, true);
1086 				break;
1087 			}
1088 
1089 			if (!m_client->GetWaitStartTime()) {
1090 				m_client->SetWaitStartTime();
1091 			}
1092 			// if we are downloading this file, this could be a new source
1093 			// no passive adding of files with only one part
1094 			if (reqfile->IsPartFile() && reqfile->GetFileSize() > PARTSIZE) {
1095 				if (thePrefs::GetMaxSourcePerFile() > static_cast<CPartFile*>(reqfile)->GetSourceCount()) {
1096 					theApp->downloadqueue->CheckAndAddKnownSource(static_cast<CPartFile*>(reqfile), m_client);
1097 				}
1098 			}
1099 			// check to see if this is a new file they are asking for
1100 			if (m_client->GetUploadFileID() != reqfilehash) {
1101 				m_client->SetCommentDirty();
1102 			}
1103 			m_client->SetUploadFileID(reqfile);
1104 			CMemFile data_out(128);
1105 			data_out.WriteHash(reqfile->GetFileHash());
1106 			while(data_in.GetLength()-data_in.GetPosition()) {
1107 				if (!m_client) {
1108 					throw wxString(wxT("Client suddenly disconnected"));
1109 				}
1110 				uint8 opcode_in = data_in.ReadUInt8();
1111 				switch(opcode_in) {
1112 					case OP_REQUESTFILENAME: {
1113 						AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTFILENAME") );
1114 						m_client->ProcessExtendedInfo(&data_in, reqfile);
1115 						data_out.WriteUInt8(OP_REQFILENAMEANSWER);
1116 
1117 						// Since it's for somebody else to see, we need to send the prettified
1118 						// filename, rather than the (possibly) mangled actual filename
1119 						data_out.WriteString(reqfile->GetFileName().GetPrintable(), m_client->GetUnicodeSupport());
1120 						break;
1121 					}
1122 					case OP_AICHFILEHASHREQ: {
1123 						AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET has OP_AICHFILEHASHANS") );
1124 						if (m_client->IsSupportingAICH() && reqfile->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1125 							&& reqfile->GetAICHHashset()->HasValidMasterHash())
1126 						{
1127 							data_out.WriteUInt8(OP_AICHFILEHASHANS);
1128 							reqfile->GetAICHHashset()->GetMasterHash().Write(&data_out);
1129 						}
1130 						break;
1131 					}
1132 					case OP_SETREQFILEID: {
1133 						AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET has OP_SETREQFILEID") );
1134 						data_out.WriteUInt8(OP_FILESTATUS);
1135 						if (reqfile->IsPartFile()) {
1136 							static_cast<CPartFile*>(reqfile)->WritePartStatus(&data_out);
1137 						} else {
1138 							data_out.WriteUInt16(0);
1139 						}
1140 						break;
1141 					}
1142 					//We still send the source packet separately..
1143 					//We could send it within this packet.. If agreeded, I will fix it..
1144 					case OP_REQUESTSOURCES2:
1145 					case OP_REQUESTSOURCES: {
1146 						AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTSOURCES(2)") );
1147 						uint8 byRequestedVersion = 0;
1148 						uint16 byRequestedOptions = 0;
1149 						if (opcode_in == OP_REQUESTSOURCES2){ // SX2 requests contains additional data
1150 							byRequestedVersion = data_in.ReadUInt8();
1151 							byRequestedOptions = data_in.ReadUInt16();
1152 						}
1153 
1154 						//Although this shouldn't happen, it's a just in case to any Mods that mess with version numbers.
1155 
1156 						if (byRequestedVersion > 0 || m_client->GetSourceExchange1Version() > 1) {
1157 							uint32 dwTimePassed = ::GetTickCount() - m_client->GetLastSrcReqTime() + CONNECTION_LATENCY;
1158 							bool bNeverAskedBefore = m_client->GetLastSrcReqTime() == 0;
1159 							if(
1160 									//if not complete and file is rare
1161 									(    reqfile->IsPartFile()
1162 									&& (bNeverAskedBefore || dwTimePassed > SOURCECLIENTREASKS)
1163 									&& static_cast<CPartFile*>(reqfile)->GetSourceCount() <= RARE_FILE
1164 									) ||
1165 									//OR if file is not rare or if file is complete
1166 									( (bNeverAskedBefore || dwTimePassed > SOURCECLIENTREASKS * MINCOMMONPENALTY) )
1167 									)
1168 							{
1169 								m_client->SetLastSrcReqTime();
1170 								CPacket* tosend = reqfile->CreateSrcInfoPacket(m_client, byRequestedVersion, byRequestedOptions);
1171 								if(tosend) {
1172 									theStats::AddUpOverheadSourceExchange(tosend->GetPacketSize());
1173 									AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client->GetFullIP() );
1174 									SendPacket(tosend, true);
1175 								}
1176 							}
1177 						}
1178 						break;
1179 					}
1180 				}
1181 
1182 			}
1183 			if( data_out.GetLength() > 16 ) {
1184 				CPacket* reply = new CPacket(data_out, OP_EMULEPROT, OP_MULTIPACKETANSWER);
1185 				theStats::AddUpOverheadFileRequest(reply->GetPacketSize());
1186 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_MULTIPACKETANSWER to ") + m_client->GetFullIP() );
1187 				SendPacket(reply, true);
1188 			}
1189 			break;
1190 		}
1191 
1192 		case OP_MULTIPACKETANSWER: {	// 0.43b
1193 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_MULTIPACKETANSWER from ") + m_client->GetFullIP() );
1194 
1195 			theStats::AddDownOverheadFileRequest(size);
1196 
1197 			if (m_client->IsBanned()) {
1198 				break;
1199 			}
1200 
1201 			if (m_client->GetKadPort() && m_client->GetKadVersion() > 1) {
1202 				Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(m_client->GetIP()), m_client->GetKadPort());
1203 			}
1204 
1205 			if (!m_client->CheckHandshakeFinished()) {
1206 				// Here comes an extended packet without finishing the handshake.
1207 				// IMHO, we should disconnect the client.
1208 				throw wxString(wxT("Client send OP_MULTIPACKETANSWER before finishing handshake"));
1209 			}
1210 
1211 			CMemFile data_in(buffer, size);
1212 			CMD4Hash reqfilehash = data_in.ReadHash();
1213 			const CPartFile *reqfile = theApp->downloadqueue->GetFileByID(reqfilehash);
1214 			//Make sure we are downloading this file.
1215 			if ( !reqfile ) {
1216 				throw wxString(wxT(" Wrong File ID: (OP_MULTIPACKETANSWER; reqfile==NULL)"));
1217 			}
1218 			if ( !m_client->GetRequestFile() ) {
1219 
1220 				throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; client->reqfile==NULL)"));
1221 			}
1222 			if (reqfile != m_client->GetRequestFile()) {
1223 				throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; reqfile!=client->reqfile)"));
1224 			}
1225 			while (data_in.GetLength()-data_in.GetPosition()) {
1226 				// Some of the cases down there can actually send a packet and lose the client
1227 				if (!m_client) {
1228 					throw wxString(wxT("Client suddenly disconnected"));
1229 				}
1230 				uint8 opcode_in = data_in.ReadUInt8();
1231 				switch(opcode_in) {
1232 					case OP_REQFILENAMEANSWER: {
1233 						if (!m_client) {
1234 							throw wxString(wxT("Client suddenly disconnected"));
1235 						} else {
1236 							m_client->ProcessFileInfo(&data_in, reqfile);
1237 						}
1238 						break;
1239 					}
1240 					case OP_FILESTATUS: {
1241 						if (!m_client) {
1242 							throw wxString(wxT("Client suddenly disconnected"));
1243 						} else {
1244 							m_client->ProcessFileStatus(false, &data_in, reqfile);
1245 						}
1246 						break;
1247 					}
1248 					case OP_AICHFILEHASHANS: {
1249 						if (!m_client) {
1250 							throw wxString(wxT("Client suddenly disconnected"));
1251 						} else {
1252 							m_client->ProcessAICHFileHash(&data_in, reqfile);
1253 						}
1254 						break;
1255 					}
1256 				}
1257 			}
1258 
1259 			break;
1260 		}
1261 
1262 		case OP_EMULEINFO: {	// 0.43b
1263 			theStats::AddDownOverheadOther(size);
1264 
1265 			if (!m_client->ProcessMuleInfoPacket(buffer, size)) {
1266 				AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_EMULEINFO from ") + m_client->GetFullIP() );
1267 
1268 				// If it's not a OS Info packet, is an old client
1269 				// start secure identification, if
1270 				//  - we have received eD2K and eMule info (old eMule)
1271 				if (m_client->GetInfoPacketsReceived() == IP_BOTH) {
1272 					m_client->InfoPacketsReceived();
1273 				}
1274 				m_client->SendMuleInfoPacket(true);
1275 			} else {
1276 				AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_EMULEINFO is an OS_INFO") );
1277 			}
1278 			break;
1279 		}
1280 		case OP_EMULEINFOANSWER: {	// 0.43b
1281 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_EMULEINFOANSWER from ") + m_client->GetFullIP() );
1282 			theStats::AddDownOverheadOther(size);
1283 
1284 			m_client->ProcessMuleInfoPacket(buffer, size);
1285 			// start secure identification, if
1286 			//  - we have received eD2K and eMule info (old eMule)
1287 
1288 			if (m_client->GetInfoPacketsReceived() == IP_BOTH) {
1289 				m_client->InfoPacketsReceived();
1290 			}
1291 
1292 			break;
1293 		}
1294 
1295 		case OP_SECIDENTSTATE:{		// 0.43b
1296 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_SECIDENTSTATE from ") + m_client->GetFullIP() );
1297 
1298 			if (!m_client->CheckHandshakeFinished()) {
1299 				// Here comes an extended packet without finishing the handshake.
1300 				// IMHO, we should disconnect the client.
1301 				throw wxString(wxT("Client send OP_SECIDENTSTATE before finishing handshake"));
1302 			}
1303 			m_client->ProcessSecIdentStatePacket(buffer, size);
1304 			// ProcessSecIdentStatePacket() might cause the socket to die, so check
1305 			if (m_client) {
1306 				int SecureIdentState = m_client->GetSecureIdentState();
1307 				if (SecureIdentState == IS_SIGNATURENEEDED) {
1308 					m_client->SendSignaturePacket();
1309 				} else if (SecureIdentState == IS_KEYANDSIGNEEDED) {
1310 					m_client->SendPublicKeyPacket();
1311 					// SendPublicKeyPacket() might cause the socket to die, so check
1312 					if ( m_client ) {
1313 						m_client->SendSignaturePacket();
1314 					}
1315 				}
1316 			}
1317 			break;
1318 		}
1319 
1320 		case OP_PUBLICKEY: {		// 0.43b
1321 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_PUBLICKEY from ") + m_client->GetFullIP() );
1322 
1323 			if (m_client->IsBanned() ){
1324 				break;
1325 			}
1326 
1327 			if (!m_client->CheckHandshakeFinished()) {
1328 				// Here comes an extended packet without finishing the handshake.
1329 				// IMHO, we should disconnect the client.
1330 				throw wxString(wxT("Client send OP_PUBLICKEY before finishing handshake"));
1331 			}
1332 
1333 			m_client->ProcessPublicKeyPacket(buffer, size);
1334 			break;
1335 		}
1336 		case OP_SIGNATURE:{			// 0.43b
1337 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_SIGNATURE from ") + m_client->GetFullIP() );
1338 
1339 			if (!m_client->CheckHandshakeFinished()) {
1340 				// Here comes an extended packet without finishing the handshake.
1341 				// IMHO, we should disconnect the client.
1342 				throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1343 			}
1344 
1345 			m_client->ProcessSignaturePacket(buffer, size);
1346 			break;
1347 		}
1348 		case OP_SENDINGPART_I64:
1349 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_SENDINGPART_I64 from ") + m_client->GetFullIP() );
1350 		/* fall through */
1351 		case OP_COMPRESSEDPART_I64:
1352 			if (opcode == OP_COMPRESSEDPART_I64) AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_COMPRESSEDPART_I64 from ") + m_client->GetFullIP() );
1353 		/* fall through */
1354 		case OP_COMPRESSEDPART: {	// 0.47a
1355 			if (opcode == OP_COMPRESSEDPART) AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_COMPRESSEDPART from ") + m_client->GetFullIP() );
1356 
1357 			if (!m_client->CheckHandshakeFinished()) {
1358 				// Here comes an extended packet without finishing the handshake.
1359 				// IMHO, we should disconnect the client.
1360 				throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1361 			}
1362 
1363 			if (m_client->GetRequestFile() && !m_client->GetRequestFile()->IsStopped() && (m_client->GetRequestFile()->GetStatus()==PS_READY || m_client->GetRequestFile()->GetStatus()==PS_EMPTY)) {
1364 
1365 				m_client->ProcessBlockPacket(buffer, size, (opcode != OP_SENDINGPART_I64), (opcode == OP_COMPRESSEDPART_I64) || (opcode == OP_SENDINGPART_I64));
1366 
1367 				if (m_client && (
1368 					m_client->GetRequestFile()->IsStopped() ||
1369 					m_client->GetRequestFile()->GetStatus() == PS_PAUSED ||
1370 					m_client->GetRequestFile()->GetStatus() == PS_ERROR)) {
1371 					if (!m_client->GetSentCancelTransfer()) {
1372 						CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
1373 						theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
1374 						AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client->GetFullIP() );
1375 						m_client->SendPacket(packet,true,true);
1376 
1377 						if (m_client) {
1378 							m_client->SetSentCancelTransfer(1);
1379 						}
1380 					}
1381 
1382 					if ( m_client ) {
1383 						m_client->SetDownloadState(m_client->GetRequestFile()->IsStopped() ? DS_NONE : DS_ONQUEUE);
1384 					}
1385 				}
1386 			} else {
1387 				if (!m_client->GetSentCancelTransfer()) {
1388 					CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
1389 					theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
1390 					AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client->GetFullIP() );
1391 					m_client->SendPacket(packet,true,true);
1392 
1393 					if ( m_client ) {
1394 						m_client->SetSentCancelTransfer(1);
1395 					}
1396 				}
1397 
1398 				if ( m_client ) {
1399 					m_client->SetDownloadState((m_client->GetRequestFile()==NULL || m_client->GetRequestFile()->IsStopped()) ? DS_NONE : DS_ONQUEUE);
1400 				}
1401 			}
1402 			break;
1403 		}
1404 		case OP_REQUESTPARTS_I64: {
1405 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQUESTPARTS_I64 from ") + m_client->GetFullIP()  );
1406 
1407 			theStats::AddDownOverheadFileRequest(size);
1408 
1409 			m_client->ProcessRequestPartsPacket(buffer, size, true);
1410 
1411 			break;
1412 		}
1413 		case OP_QUEUERANKING: {		// 0.43b
1414 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_QUEUERANKING from ") + m_client->GetFullIP()  );
1415 
1416 			theStats::AddDownOverheadOther(size);
1417 
1418 			if (!m_client->CheckHandshakeFinished()) {
1419 				// Here comes an extended packet without finishing the handshake.
1420 				// IMHO, we should disconnect the client.
1421 				throw wxString(wxT("Client send OP_QUEUERANKING before finishing handshake"));
1422 			}
1423 
1424 			if (size != 12) {
1425 				throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1426 			}
1427 
1428 			uint16 newrank = PeekUInt16(buffer);
1429 			m_client->SetRemoteQueueFull(false);
1430 			m_client->SetRemoteQueueRank(newrank);
1431 			break;
1432 		}
1433 		case OP_REQUESTSOURCES2:
1434 		case OP_REQUESTSOURCES:{
1435 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQUESTSOURCES from ") + m_client->GetFullIP()  );
1436 
1437 			theStats::AddDownOverheadSourceExchange(size);
1438 
1439 			if (!m_client->CheckHandshakeFinished()) {
1440 				// Here comes an extended packet without finishing the handshake.
1441 				// IMHO, we should disconnect the client.
1442 				throw wxString(wxT("Client send OP_REQUESTSOURCES before finishing handshake"));
1443 			}
1444 
1445 			uint8 byRequestedVersion = 0;
1446 			uint16 byRequestedOptions = 0;
1447 			CMemFile data_in(buffer, size);
1448 			if (opcode == OP_REQUESTSOURCES2){ // SX2 requests contains additional data
1449 				byRequestedVersion = data_in.ReadUInt8();
1450 				byRequestedOptions = data_in.ReadUInt16();
1451 			}
1452 
1453 			if (byRequestedVersion > 0 || m_client->GetSourceExchange1Version() >= 1) {
1454 				if(size != 16) {
1455 					throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1456 				}
1457 				//first check shared file list, then download list
1458 				const CMD4Hash fileID(buffer);
1459 				CKnownFile* file = theApp->sharedfiles->GetFileByID(fileID);
1460 				if(!file) {
1461 					file = theApp->downloadqueue->GetFileByID(fileID);
1462 				}
1463 				if(file) {
1464 					// There are some clients which do not follow the correct protocol procedure of sending
1465 					// the sequence OP_REQUESTFILENAME, OP_SETREQFILEID, OP_REQUESTSOURCES. If those clients
1466 					// are doing this, they will not get the optimal set of sources which we could offer if
1467 					// they would follow the above noted protocol sequence. They better do it the right way
1468 					// or they will get just a random set of sources because we do not know their download
1469 					// part status which may get cleared with the call of 'SetUploadFileID'.
1470 					m_client->SetUploadFileID(file);
1471 
1472 					uint32 dwTimePassed = ::GetTickCount() - m_client->GetLastSrcReqTime() + CONNECTION_LATENCY;
1473 					bool bNeverAskedBefore = m_client->GetLastSrcReqTime() == 0;
1474 					if(
1475 					//if not complete and file is rare, allow once every 40 minutes
1476 					( file->IsPartFile() &&
1477 					static_cast<CPartFile*>(file)->GetSourceCount() <= RARE_FILE &&
1478 					(bNeverAskedBefore || dwTimePassed > SOURCECLIENTREASKS)
1479 					) ||
1480 					//OR if file is not rare or if file is complete, allow every 90 minutes
1481 					( (bNeverAskedBefore || dwTimePassed > SOURCECLIENTREASKS * MINCOMMONPENALTY) )
1482 					)
1483 					{
1484 						m_client->SetLastSrcReqTime();
1485 						CPacket* tosend = file->CreateSrcInfoPacket(m_client, byRequestedVersion, byRequestedOptions);
1486 						if(tosend) {
1487 							theStats::AddUpOverheadSourceExchange(tosend->GetPacketSize());
1488 							AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client->GetFullIP() );
1489 							SendPacket(tosend, true, true);
1490 						}
1491 					}
1492 				}
1493 			}
1494 			break;
1495 		}
1496 		case OP_ANSWERSOURCES: {
1497 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_ANSWERSOURCES from ") + m_client->GetFullIP()  );
1498 
1499 			theStats::AddDownOverheadSourceExchange(size);
1500 
1501 			if (!m_client->CheckHandshakeFinished()) {
1502 				// Here comes an extended packet without finishing the handshake.
1503 				// IMHO, we should disconnect the client.
1504 				throw wxString(wxT("Client send OP_ANSWERSOURCES before finishing handshake"));
1505 			}
1506 
1507 			CMemFile data(buffer, size);
1508 			CMD4Hash hash = data.ReadHash();
1509 			CKnownFile* file = theApp->downloadqueue->GetFileByID(hash);
1510 			if(file){
1511 				if (file->IsPartFile()){
1512 					//set the client's answer time
1513 					m_client->SetLastSrcAnswerTime();
1514 					//and set the file's last answer time
1515 					static_cast<CPartFile*>(file)->SetLastAnsweredTime();
1516 					static_cast<CPartFile*>(file)->AddClientSources(&data, SF_SOURCE_EXCHANGE, m_client->GetSourceExchange1Version(), false, m_client);
1517 				}
1518 			}
1519 			break;
1520 		}
1521 		case OP_ANSWERSOURCES2: {
1522 			//printf("Received OP_ANSWERSOURCES2\n");
1523 			theStats::AddDownOverheadSourceExchange(size);
1524 
1525 			if (!m_client->CheckHandshakeFinished()) {
1526 				// Here comes an extended packet without finishing the handshake.
1527 				// IMHO, we should disconnect the client.
1528 				throw wxString(wxT("Client send OP_ANSWERSOURCES2 before finishing handshake"));
1529 			}
1530 
1531 			CMemFile data(buffer, size);
1532 			uint8 byVersion = data.ReadUInt8();
1533 			CMD4Hash hash = data.ReadHash();
1534 			CKnownFile* file = theApp->downloadqueue->GetFileByID(hash);
1535 			if (file){
1536 				if (file->IsPartFile()){
1537 					//set the client's answer time
1538 					m_client->SetLastSrcAnswerTime();
1539 					//and set the file's last answer time
1540 					static_cast<CPartFile*>(file)->SetLastAnsweredTime();
1541 					static_cast<CPartFile*>(file)->AddClientSources(&data, SF_SOURCE_EXCHANGE, byVersion, true, m_client);
1542 				}
1543 			}
1544 			break;
1545 		}
1546 		case OP_FILEDESC: {		// 0.43b
1547 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_FILEDESC from ") + m_client->GetFullIP()  );
1548 
1549 			theStats::AddDownOverheadFileRequest(size);
1550 
1551 			if (!m_client->CheckHandshakeFinished()) {
1552 				// Here comes an extended packet without finishing the handshake.
1553 				// IMHO, we should disconnect the client.
1554 				throw wxString(wxT("Client send OP_FILEDESC before finishing handshake"));
1555 			}
1556 
1557 			m_client->ProcessMuleCommentPacket(buffer, size);
1558 			break;
1559 		}
1560 
1561 		// Unsupported
1562 		case OP_REQUESTPREVIEW: {
1563 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REQUESTPREVIEW  from ") + m_client->GetFullIP()  );
1564 			break;
1565 		}
1566 		// Unsupported
1567 		case OP_PREVIEWANSWER: {
1568 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_PREVIEWANSWER from ") + m_client->GetFullIP()  );
1569 			break;
1570 		}
1571 
1572 		case OP_PUBLICIP_ANSWER: {
1573 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_PUBLICIP_ANSWER from ") + m_client->GetFullIP()  );
1574 			theStats::AddDownOverheadOther(size);
1575 			m_client->ProcessPublicIPAnswer(buffer, size);
1576 			break;
1577 		}
1578 		case OP_PUBLICIP_REQ: {
1579 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_PUBLICIP_REQ from ") + m_client->GetFullIP()  );
1580 			theStats::AddDownOverheadOther(size);
1581 			CPacket* pPacket = new CPacket(OP_PUBLICIP_ANSWER, 4, OP_EMULEPROT);
1582 			pPacket->CopyUInt32ToDataBuffer(m_client->GetIP());
1583 			theStats::AddUpOverheadOther(pPacket->GetPacketSize());
1584 			AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_PUBLICIP_ANSWER to") + m_client->GetFullIP());
1585 			SendPacket(pPacket);
1586 			break;
1587 		}
1588 		case OP_AICHANSWER: {
1589 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_AICHANSWER from ") + m_client->GetFullIP()  );
1590 			theStats::AddDownOverheadOther(size);
1591 			m_client->ProcessAICHAnswer(buffer, size);
1592 			break;
1593 		}
1594 		case OP_AICHREQUEST: {
1595 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_AICHREQUEST from ") + m_client->GetFullIP()  );
1596 			theStats::AddDownOverheadOther(size);
1597 			m_client->ProcessAICHRequest(buffer, size);
1598 			break;
1599 		}
1600 		case OP_AICHFILEHASHANS: {
1601 			// those should not be received normally, since we should only get those in MULTIPACKET
1602 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_AICHFILEHASHANS from ") + m_client->GetFullIP()  );
1603 			theStats::AddDownOverheadOther(size);
1604 			CMemFile data(buffer, size);
1605 			m_client->ProcessAICHFileHash(&data, NULL);
1606 			break;
1607 		}
1608 		case OP_AICHFILEHASHREQ: {
1609 			// those should not be received normally, since we should only get those in MULTIPACKET
1610 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_AICHFILEHASHREQ from ") + m_client->GetFullIP()  );
1611 			CMemFile data(buffer, size);
1612 			CMD4Hash hash = data.ReadHash();
1613 			CKnownFile* pPartFile = theApp->sharedfiles->GetFileByID(hash);
1614 			if (pPartFile == NULL){
1615 				break;
1616 			}
1617 
1618 			if (m_client->IsSupportingAICH() && pPartFile->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1619 				&& pPartFile->GetAICHHashset()->HasValidMasterHash()) {
1620 				CMemFile data_out;
1621 				data_out.WriteHash(hash);
1622 				pPartFile->GetAICHHashset()->GetMasterHash().Write(&data_out);
1623 				CPacket* packet = new CPacket(data_out, OP_EMULEPROT, OP_AICHFILEHASHANS);
1624 				theStats::AddUpOverheadOther(packet->GetPacketSize());
1625 					AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_AICHFILEHASHANS to") + m_client->GetFullIP());
1626 				SendPacket(packet);
1627 			}
1628 			break;
1629 		}
1630 		case OP_CALLBACK: {
1631 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_CALLBACK from ") + m_client->GetFullIP() );
1632 			theStats::AddDownOverheadFileRequest(size);
1633 			if(!Kademlia::CKademlia::IsRunning()) {
1634 				break;
1635 			}
1636 			CMemFile data(buffer, size);
1637 			CUInt128 check = data.ReadUInt128();
1638 			check ^= Kademlia::CUInt128(true);
1639 			if (check != Kademlia::CKademlia::GetPrefs()->GetKadID()) {
1640 				break;
1641 			}
1642 			CUInt128 fileid = data.ReadUInt128();
1643 			byte fileid2[16];
1644 			fileid.ToByteArray(fileid2);
1645 			const CMD4Hash fileHash(fileid2);
1646 			if (theApp->sharedfiles->GetFileByID(fileHash) == NULL) {
1647 				if (theApp->downloadqueue->GetFileByID(fileHash) == NULL) {
1648 					break;
1649 				}
1650 			}
1651 
1652 			uint32 ip = data.ReadUInt32();
1653 			uint16 tcp = data.ReadUInt16();
1654 			CUpDownClient* callback;
1655 			callback = theApp->clientlist->FindClientByIP(wxUINT32_SWAP_ALWAYS(ip), tcp);
1656 			if( callback == NULL ) {
1657 				//#warning Do we actually have to check friend status here?
1658 				callback = new CUpDownClient(tcp,ip,0,0,NULL,false, false);
1659 				theApp->clientlist->AddClient(callback);
1660 			}
1661 			callback->TryToConnect(true);
1662 			break;
1663 		}
1664 
1665 		case OP_BUDDYPING: {
1666 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_BUDDYPING from ") + m_client->GetFullIP()  );
1667 			theStats::AddDownOverheadKad(size);
1668 
1669 			CUpDownClient* buddy = theApp->clientlist->GetBuddy();
1670 			if( buddy != m_client || m_client->GetKadVersion() == 0 || !m_client->AllowIncomeingBuddyPingPong() ) {
1671 				//This ping was not from our buddy or wrong version or packet sent to fast. Ignore
1672 				break;
1673 			}
1674 
1675 			m_client->SetLastBuddyPingPongTime();
1676 			CPacket* replypacket = new CPacket(OP_BUDDYPONG, 0, OP_EMULEPROT);
1677 			theStats::AddUpOverheadKad(replypacket->GetPacketSize());
1678 			AddDebugLogLineN(logLocalClient,wxT("Local Client: OP_BUDDYPONG to ") + m_client->GetFullIP());
1679 			SendPacket(replypacket);
1680 			break;
1681 		}
1682 		case OP_BUDDYPONG: {
1683 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_BUDDYPONG from ") + m_client->GetFullIP()  );
1684 			theStats::AddDownOverheadKad(size);
1685 
1686 			CUpDownClient* buddy = theApp->clientlist->GetBuddy();
1687 			if( buddy != m_client || m_client->GetKadVersion() == 0 ) {
1688 				//This pong was not from our buddy or wrong version. Ignore
1689 				break;
1690 			}
1691 			m_client->SetLastBuddyPingPongTime();
1692 			//All this is for is to reset our socket timeout.
1693 			break;
1694 		}
1695 		case OP_REASKCALLBACKTCP: {
1696 			theStats::AddDownOverheadFileRequest(size);
1697 			CUpDownClient* buddy = theApp->clientlist->GetBuddy();
1698 			if (buddy != m_client) {
1699 				AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client->GetFullIP() + wxT(" which is not our buddy!") );
1700 				//This callback was not from our buddy.. Ignore.
1701 				break;
1702 			}
1703 			AddDebugLogLineN( logRemoteClient, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client->GetFullIP() );
1704 			CMemFile data_in(buffer, size);
1705 			uint32 destip = data_in.ReadUInt32();
1706 			uint16 destport = data_in.ReadUInt16();
1707 			CMD4Hash hash = data_in.ReadHash();
1708 			CKnownFile* reqfile = theApp->sharedfiles->GetFileByID(hash);
1709 
1710 			bool bSenderMultipleIpUnknown = false;
1711 			CUpDownClient* sender = theApp->uploadqueue->GetWaitingClientByIP_UDP(destip, destport, true, &bSenderMultipleIpUnknown);
1712 			if (!reqfile) {
1713 				AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_FILENOTFOUND to ") + m_client->GetFullIP() );
1714 				CPacket* response = new CPacket(OP_FILENOTFOUND,0,OP_EMULEPROT);
1715 				theStats::AddUpOverheadFileRequest(response->GetPacketSize());
1716 				if (sender) {
1717 					theApp->clientudp->SendPacket(response, destip, destport, sender->ShouldReceiveCryptUDPPackets(), sender->GetUserHash().GetHash(), false, 0);
1718 				} else {
1719 					theApp->clientudp->SendPacket(response, destip, destport, false, NULL, false, 0);
1720 				}
1721 				break;
1722 			}
1723 
1724 			if (sender) {
1725 				//Make sure we are still thinking about the same file
1726 				if (hash == sender->GetUploadFileID()) {
1727 					sender->AddAskedCount();
1728 					sender->SetLastUpRequest();
1729 					//I messed up when I first added extended info to UDP
1730 					//I should have originally used the entire ProcessExtenedInfo the first time.
1731 					//So now I am forced to check UDPVersion to see if we are sending all the extended info.
1732 					//For now on, we should not have to change anything here if we change
1733 					//anything to the extended info data as this will be taken care of in ProcessExtendedInfo()
1734 					//Update extended info.
1735 					if (sender->GetUDPVersion() > 3) {
1736 						sender->ProcessExtendedInfo(&data_in, reqfile);
1737 					} else if (sender->GetUDPVersion() > 2) {
1738 						//Update our complete source counts.
1739 						uint16 nCompleteCountLast= sender->GetUpCompleteSourcesCount();
1740 						uint16 nCompleteCountNew = data_in.ReadUInt16();
1741 						sender->SetUpCompleteSourcesCount(nCompleteCountNew);
1742 						if (nCompleteCountLast != nCompleteCountNew) {
1743 							reqfile->UpdatePartsInfo();
1744 						}
1745 					}
1746 
1747 					CMemFile data_out(128);
1748 					if(sender->GetUDPVersion() > 3) {
1749 						if (reqfile->IsPartFile()) {
1750 							static_cast<CPartFile*>(reqfile)->WritePartStatus(&data_out);
1751 						} else {
1752 							data_out.WriteUInt16(0);
1753 						}
1754 					}
1755 
1756 					data_out.WriteUInt16(sender->GetUploadQueueWaitingPosition());
1757 					CPacket* response = new CPacket(data_out, OP_EMULEPROT, OP_REASKACK);
1758 					theStats::AddUpOverheadFileRequest(response->GetPacketSize());
1759 					AddDebugLogLineN( logLocalClient, wxT("Local Client UDP: OP_REASKACK to ") + m_client->GetFullIP()  );
1760 					theApp->clientudp->SendPacket(response, destip, destport, sender->ShouldReceiveCryptUDPPackets(), sender->GetUserHash().GetHash(), false, 0);
1761 				} else {
1762 					AddDebugLogLineN(logListenSocket, wxT("Client UDP socket; OP_REASKCALLBACKTCP; reqfile does not match"));
1763 				}
1764 			} else {
1765 				if (!bSenderMultipleIpUnknown){
1766 					if ((theStats::GetWaitingUserCount() + 50) > thePrefs::GetQueueSize()) {
1767 						AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_QUEUEFULL to ") + m_client->GetFullIP()  );
1768 						CPacket* response = new CPacket(OP_QUEUEFULL,0,OP_EMULEPROT);
1769 						theStats::AddUpOverheadFileRequest(response->GetPacketSize());
1770 						theApp->clientudp->SendPacket(response, destip, destport, false, NULL, false, 0);
1771 					}
1772 				} else {
1773 					AddDebugLogLineN(logRemoteClient, CFormat(wxT("OP_REASKCALLBACKTCP Packet received - multiple clients with the same IP but different UDP port found. Possible UDP Portmapping problem, enforcing TCP connection. IP: %s, Port: %u")) % Uint32toStringIP(destip) % destport);
1774 				}
1775 			}
1776 			break;
1777 		}
1778 		case OP_CHATCAPTCHAREQ:
1779 		{
1780 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_CHATCAPTCHAREQ from ") + m_client->GetFullIP());
1781 			theStats::AddDownOverheadOther(size);
1782 			CMemFile data_in(buffer, size);
1783 			m_client->ProcessCaptchaRequest(&data_in);
1784 			break;
1785 		}
1786 		case OP_CHATCAPTCHARES:
1787 		{
1788 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_CHATCAPTCHARES from ") + m_client->GetFullIP());
1789 			theStats::AddDownOverheadOther(size);
1790 			if (size) {
1791 				m_client->ProcessCaptchaReqRes(buffer[0]);
1792 			}
1793 			break;
1794 		}
1795 		case OP_FWCHECKUDPREQ: { // Support required for Kadversion >= 6
1796 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_FWCHECKUDPREQ from ") + m_client->GetFullIP());
1797 			theStats::AddDownOverheadOther(size);
1798 			CMemFile data_in(buffer, size);
1799 			m_client->ProcessFirewallCheckUDPRequest(&data_in);
1800 			break;
1801 		}
1802 		case OP_KAD_FWTCPCHECK_ACK: { // Support required for Kadversion >= 7
1803 			AddDebugLogLineN(logRemoteClient, wxT("Remote Client: OP_KAD_FWTCPCHECK_ACK from ") + m_client->GetFullIP());
1804 			if (theApp->clientlist->IsKadFirewallCheckIP(m_client->GetIP())) {
1805 				if (Kademlia::CKademlia::IsRunning()) {
1806 					Kademlia::CKademlia::GetPrefs()->IncFirewalled();
1807 				}
1808 			} else {
1809 				AddDebugLogLineN(logListenSocket, wxT("Received unrequested OP_KAD_FWTCPCHECK_ACK packet from ") + m_client->GetFullIP());
1810 			}
1811 			break;
1812 		}
1813 		default:
1814 			theStats::AddDownOverheadOther(size);
1815 			AddDebugLogLineN(logRemoteClient, CFormat(wxT("eMule packet : unknown opcode: %i %x from %s")) % opcode % opcode % m_client->GetFullIP());
1816 			break;
1817 	}
1818 
1819 	return true;
1820 }
1821 
ProcessED2Kv2Packet(const byte * buffer,uint32 size,uint8 opcode)1822 bool CClientTCPSocket::ProcessED2Kv2Packet(const byte* buffer, uint32 size, uint8 opcode)
1823 {
1824 	#ifdef __PACKET_RECV_DUMP__
1825 	//printf("Rec: OPCODE %x ED2Kv2\n",opcode);
1826 	DumpMem(buffer,size);
1827 	#endif
1828 
1829 	if (!m_client) {
1830 		throw wxString(wxT("Unknown clients sends extended ED2Kv2 protocol packet"));
1831 	}
1832 
1833 	CMemFile data(buffer, size);
1834 	try {
1835 		switch(opcode) {
1836 			case OP_QUEUERANK: {
1837 				AddDebugLogLineN( logRemoteClient, wxT("Remote Client: ED2Kv2 OP_QUEUERANK from ") + m_client->GetFullIP() );
1838 
1839 				uint8 numtags = data.ReadUInt8();
1840 				wxASSERT(numtags == 1);
1841 				if(numtags){}	// prevent GCC warning
1842 
1843 				m_client->SetRemoteQueueRank(data.GetIntTagValue());
1844 
1845 				theStats::AddDownOverheadFileRequest(size);
1846 				break;
1847 			}
1848 
1849 			case OP_REQUESTPARTS: {
1850 				AddDebugLogLineN( logRemoteClient, wxT("Remote Client: ED2Kv2 OP_REQUESTPARTS from ") + m_client->GetFullIP() );
1851 
1852 				m_client->ProcessRequestPartsPacketv2(data);
1853 
1854 				theStats::AddDownOverheadFileRequest(size);
1855 				break;
1856 			}
1857 
1858 			default:
1859 				theStats::AddDownOverheadOther(size);
1860 				AddDebugLogLineN(logRemoteClient, CFormat(wxT("ED2Kv2 packet : unknown opcode: %i %x from %s")) % opcode % opcode % m_client->GetFullIP());
1861 		}
1862 	} catch (...) {
1863 		AddDebugLogLineN(logRemoteClient, CFormat(wxT("ED2Kv2 packet is corrupt at pos %i! opcode: %i %x from %s")) % data.GetPosition() % opcode % opcode % m_client->GetFullIP());
1864 		throw;
1865 	}
1866 
1867 	return true;
1868 }
1869 
OnConnect(int nErrorCode)1870 void CClientTCPSocket::OnConnect(int nErrorCode)
1871 {
1872 	if (nErrorCode) {
1873 		OnError(nErrorCode);
1874 	} else if (!m_client) {
1875 		// and now? Disconnect? not?
1876 		AddDebugLogLineN( logClient, wxT("Couldn't send hello packet (Client deleted!)") );
1877 	} else if (!m_client->SendHelloPacket()) {
1878 		// and now? Disconnect? not?
1879 		AddDebugLogLineN( logClient, wxT("Couldn't send hello packet (Client deleted by SendHelloPacket!)") );
1880 	} else {
1881 		ResetTimeOutTimer();
1882 	}
1883 }
1884 
1885 
OnSend(int nErrorCode)1886 void CClientTCPSocket::OnSend(int nErrorCode)
1887 {
1888 	ResetTimeOutTimer();
1889 	CEMSocket::OnSend(nErrorCode);
1890 }
1891 
1892 
OnReceive(int nErrorCode)1893 void CClientTCPSocket::OnReceive(int nErrorCode)
1894 {
1895 	ResetTimeOutTimer();
1896 	// We might have updated ipfilter
1897 	wxASSERT(m_remoteip);
1898 
1899 	if (theApp->ipfilter->IsFiltered(m_remoteip)) {
1900 		if (m_client) {
1901 			m_client->Safe_Delete();
1902 		}
1903 		Safe_Delete();
1904 		AddDebugLogLineN( logIPFilter, wxT("A connected client was dropped by IPFilter on new packet received"));
1905 	} else {
1906 		CEMSocket::OnReceive(nErrorCode);
1907 	}
1908 }
1909 
1910 
OnError(int nErrorCode)1911 void CClientTCPSocket::OnError(int nErrorCode)
1912 {
1913 	//printf("* Called OnError for %p\n",this);
1914 	// 0.42e + Kry changes for handling of socket lost events
1915 	wxString strError;
1916 
1917 	if ((nErrorCode == 0) || (nErrorCode == 7) || (nErrorCode == 0xFEFF)) {
1918 		if (m_client) {
1919 			if (!m_client->GetUserName().IsEmpty()) {
1920 				strError = wxT("Client '") + m_client->GetUserName() + wxT("'");
1921 			} else {
1922 				strError = wxT("An unnamed client");
1923 			}
1924 			strError += wxT(" (IP:") + m_client->GetFullIP() + wxT(") ");
1925 		} else {
1926 			strError = wxT("A client ");
1927 		}
1928 		if (nErrorCode == 0) {
1929 			strError += wxT("closed connection.");
1930 		} else if (nErrorCode == 0xFEFF) {
1931 			strError += wxT(" caused a wxSOCKET_LOST event.");
1932 		}	else {
1933 			strError += wxT("caused a socket blocking error.");
1934 		}
1935 	} else {
1936 		if (theLogger.IsEnabled(logClient) && nErrorCode != 107) {
1937 			// 0    -> No Error / Disconect
1938 			// 107  -> Transport endpoint is not connected
1939 			if (m_client) {
1940 				if (!m_client->GetUserName().IsEmpty()) {
1941 					strError = CFormat(wxT("OnError: Client '%s' (IP:%s) caused an error: %u. Disconnecting client!"))
1942 						% m_client->GetUserName() % m_client->GetFullIP() % nErrorCode;
1943 				} else {
1944 					strError = CFormat(wxT("OnError: Unknown client (IP:%s) caused an error: %u. Disconnecting client!"))
1945 						% m_client->GetFullIP() % nErrorCode;
1946 				}
1947 			} else {
1948 				strError = CFormat(wxT("OnError: A client caused an error or did something bad (error %u). Disconnecting client !"))
1949 					% nErrorCode;
1950 			}
1951 		} else {
1952 			strError = wxT("Error 107 (Transport endpoint is not connected)");
1953 		}
1954 	}
1955 
1956 	Disconnect(strError);
1957 }
1958 
1959 
PacketReceived(CPacket * packet)1960 bool CClientTCPSocket::PacketReceived(CPacket* packet)
1961 {
1962 	// 0.42e
1963 	bool bResult = false;
1964 	uint32 uRawSize = packet->GetPacketSize();
1965 
1966 	AddDebugLogLineN( logRemoteClient,
1967 		CFormat(wxT("Packet with protocol %x, opcode %x, size %u received from %s"))
1968 			% packet->GetProtocol()
1969 			% packet->GetOpCode()
1970 			% packet->GetPacketSize()
1971 			% ( m_client ? m_client->GetFullIP() : wxT("Unknown Client") )
1972 	);
1973 
1974 	wxString exception;
1975 
1976 	try {
1977 		bool process = true;
1978 
1979 		if ((packet->GetProtocol() == OP_PACKEDPROT) ||
1980 			(packet->GetProtocol() == OP_ED2KV2PACKEDPROT)) {
1981 
1982 			if (!packet->UnPackPacket()) {
1983 				AddDebugLogLineN(logZLib, wxT("Failed to decompress client TCP packet."));
1984 				bResult = false;
1985 				process = false;
1986 			} else {
1987 				AddDebugLogLineN(logRemoteClient, CFormat(wxT("Packet unpacked, new protocol %x, opcode %x, size %u"))
1988 					% packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize());
1989 			}
1990 		}
1991 
1992 		if (process) {
1993 			switch (packet->GetProtocol()) {
1994 				case OP_EDONKEYPROT:
1995 					bResult = ProcessPacket(packet->GetDataBuffer(),uRawSize,packet->GetOpCode());
1996 					break;
1997 				case OP_EMULEPROT:
1998 					bResult = ProcessExtPacket(packet->GetDataBuffer(), packet->GetPacketSize(), packet->GetOpCode());
1999 					break;
2000 				case OP_ED2KV2HEADER:
2001 					bResult = ProcessED2Kv2Packet(packet->GetDataBuffer(), packet->GetPacketSize(), packet->GetOpCode());
2002 					break;
2003 				case OP_ED2KV2PACKEDPROT:
2004 				case OP_PACKEDPROT:
2005 					// Packed inside packed?
2006 					wxFAIL;
2007 					break;
2008 				default: {
2009 					theStats::AddDownOverheadOther(uRawSize);
2010 					if (m_client) {
2011 						m_client->SetDownloadState(DS_ERROR);
2012 					}
2013 					Disconnect(wxT("Unknown protocol"));
2014 					bResult = false;
2015 				}
2016 			}
2017 		}
2018 	} catch (const CEOFException& err) {
2019 		exception = wxT("EOF exception: ") + err.what();
2020 	} catch (const CInvalidPacket& err) {
2021 		exception = wxT("InvalidPacket exception: ") + err.what();
2022 	} catch (const wxString& error) {
2023 		exception = wxT("error: ") + (error.IsEmpty() ? wxString(wxT("Unknown error")) : error);
2024 	}
2025 
2026 	if (!exception.IsEmpty()) {
2027 		AddDebugLogLineN( logPacketErrors,
2028 			CFormat(wxT("Caught %s\nOn packet with protocol %x, opcode %x, size %u\tClientData: %s\n"))
2029 				% exception
2030 				% packet->GetProtocol()
2031 				% packet->GetOpCode()
2032 				% packet->GetPacketSize()
2033 				% ( m_client ? m_client->GetClientFullInfo() : wxT("Unknown") )
2034 		);
2035 
2036 		if (m_client) {
2037 			m_client->SetDownloadState(DS_ERROR);
2038 		}
2039 
2040 		AddDebugLogLineN( logClient,
2041 			CFormat( wxT("Client '%s' (IP: %s) caused an error (%s). Disconnecting client!" ) )
2042 				% ( m_client ? m_client->GetUserName() : wxString(wxT("Unknown")) )
2043 				% ( m_client ? m_client->GetFullIP() : wxString(wxT("Unknown")) )
2044 				% exception
2045 		);
2046 
2047 		Disconnect(wxT("Caught exception on CClientTCPSocket::ProcessPacket\n"));
2048 	}
2049 
2050 	return bResult;
2051 }
2052 
2053 
SendControlData(uint32 maxNumberOfBytesToSend,uint32 overchargeMaxBytesToSend)2054 SocketSentBytes CClientTCPSocket::SendControlData(uint32 maxNumberOfBytesToSend, uint32 overchargeMaxBytesToSend)
2055 {
2056     SocketSentBytes returnStatus = CEMSocket::SendControlData(maxNumberOfBytesToSend, overchargeMaxBytesToSend);
2057 
2058     if(returnStatus.success && (returnStatus.sentBytesControlPackets > 0 || returnStatus.sentBytesStandardPackets > 0)) {
2059         ResetTimeOutTimer();
2060     }
2061 
2062     return returnStatus;
2063 }
2064 
2065 
SendFileAndControlData(uint32 maxNumberOfBytesToSend,uint32 overchargeMaxBytesToSend)2066 SocketSentBytes CClientTCPSocket::SendFileAndControlData(uint32 maxNumberOfBytesToSend, uint32 overchargeMaxBytesToSend)
2067 {
2068 	SocketSentBytes returnStatus = CEMSocket::SendFileAndControlData(maxNumberOfBytesToSend, overchargeMaxBytesToSend);
2069 
2070     if(returnStatus.success && (returnStatus.sentBytesControlPackets > 0 || returnStatus.sentBytesStandardPackets > 0)) {
2071         ResetTimeOutTimer();
2072     }
2073 
2074     return returnStatus;
2075 }
2076 
2077 
SendPacket(CPacket * packet,bool delpacket,bool controlpacket,uint32 actualPayloadSize)2078 void CClientTCPSocket::SendPacket(CPacket* packet, bool delpacket, bool controlpacket, uint32 actualPayloadSize)
2079 {
2080 	ResetTimeOutTimer();
2081 	CEMSocket::SendPacket(packet,delpacket,controlpacket, actualPayloadSize);
2082 }
2083 // File_checked_for_headers
2084