2 // This file is part of the aMule Project.
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
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.
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.
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
25 #include "ClientTCPSocket.h" // Interface declarations
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>
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_*
57 //#define __PACKET_RECV_DUMP__
59 //------------------------------------------------------------------------------
60 // CClientTCPSocketHandler
61 //------------------------------------------------------------------------------
63 class CClientTCPSocketHandler
: public wxEvtHandler
66 CClientTCPSocketHandler() {};
69 void ClientTCPSocketHandler(wxSocketEvent
& event
);
73 BEGIN_EVENT_TABLE(CClientTCPSocketHandler
, wxEvtHandler
)
74 EVT_SOCKET(ID_CLIENTTCPSOCKET_EVENT
, CClientTCPSocketHandler::ClientTCPSocketHandler
)
77 void CClientTCPSocketHandler::ClientTCPSocketHandler(wxSocketEvent
& event
)
79 wxSocketBase
* baseSocket
= event
.GetSocket();
80 // wxASSERT(baseSocket); // Rather want a log message right now. Enough other wx problems. >:(
81 if (!baseSocket
) { // WTF?
82 AddDebugLogLineN(logClient
, wxT("received bad wxSocketEvent"));
86 CClientTCPSocket
*socket
= dynamic_cast<CClientTCPSocket
*>(baseSocket
);
92 if (socket
->OnDestroy() || socket
->ForDeletion()) {
96 switch(event
.GetSocketEvent()) {
98 socket
->OnError(0xFEFF /* SOCKET_LOST is not an error */);
101 socket
->OnReceive(0);
103 case wxSOCKET_OUTPUT
:
106 case wxSOCKET_CONNECTION
:
107 // connection stablished, nothing to do about it?
108 socket
->OnConnect(socket
->Error() ? socket
->LastError() : 0);
111 // Nothing should arrive here...
118 // There can be only one. :)
120 static CClientTCPSocketHandler g_clientReqSocketHandler
;
123 //------------------------------------------------------------------------------
125 //------------------------------------------------------------------------------
127 CClientTCPSocket::CClientTCPSocket(CUpDownClient
* in_client
, const CProxyData
*ProxyData
)
128 : CEMSocket(ProxyData
)
130 SetClient(in_client
);
132 m_remoteip
= wxUINT32_SWAP_ALWAYS(in_client
->GetUserIDHybrid());
138 m_ForDeletion
= false;
140 SetEventHandler(g_clientReqSocketHandler
, ID_CLIENTTCPSOCKET_EVENT
);
142 wxSOCKET_CONNECTION_FLAG
|
143 wxSOCKET_INPUT_FLAG
|
144 wxSOCKET_OUTPUT_FLAG
|
148 theApp
->listensocket
->AddSocket(this);
149 theApp
->listensocket
->AddConnection();
152 CClientTCPSocket::~CClientTCPSocket()
154 // remove event handler
159 m_client
->SetSocket( NULL
);
163 if (theApp
->listensocket
&& !theApp
->listensocket
->OnShutdown()) {
164 theApp
->listensocket
->RemoveSocket(this);
168 bool CClientTCPSocket::InitNetworkData()
170 wxASSERT(!m_remoteip
);
172 amuleIPV4Address addr
;
174 m_remoteip
= StringIPtoUint32(addr
.IPAddress());
176 MULE_CHECK(m_remoteip
, false);
178 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
179 AddDebugLogLineN(logClient
, wxT("Denied connection from ") + addr
.IPAddress() + wxT("(Filtered IP)"));
181 } else if (theApp
->clientlist
->IsBannedClient(m_remoteip
)) {
182 AddDebugLogLineN(logClient
, wxT("Denied connection from ") + addr
.IPAddress() + wxT("(Banned IP)"));
185 AddDebugLogLineN(logClient
, wxT("Accepted connection from ") + addr
.IPAddress());
190 void CClientTCPSocket::ResetTimeOutTimer()
192 timeout_timer
= ::GetTickCount();
196 bool CClientTCPSocket::CheckTimeOut()
199 uint32 uTimeout
= GetTimeOut();
202 if (m_client
->GetKadState() == KS_CONNECTED_BUDDY
) {
203 //We originally ignored the timeout here for buddies.
204 //This was a stupid idea on my part. There is now a ping/pong system
205 //for buddies. This ping/pong system now prevents timeouts.
206 //This release will allow lowID clients with KadVersion 0 to remain connected.
207 //But a soon future version needs to allow these older clients to time out to prevent dead connections from continuing.
208 //JOHNTODO: Don't forget to remove backward support in a future release.
209 if ( m_client
->GetKadVersion() == 0 ) {
213 uTimeout
+= MIN2MS(15);
216 if (m_client
->GetChatState() != MS_NONE
) {
217 uTimeout
+= CONNECTION_TIMEOUT
;
221 if (::GetTickCount() - timeout_timer
> uTimeout
){
222 timeout_timer
= ::GetTickCount();
223 Disconnect(wxT("Timeout"));
231 void CClientTCPSocket::SetClient(CUpDownClient
* pClient
)
235 m_client
->SetSocket( this );
240 void CClientTCPSocket::OnClose(int nErrorCode
)
243 wxASSERT(theApp
->listensocket
->IsValidSocket(this));
244 CEMSocket::OnClose(nErrorCode
);
246 Disconnect(CFormat(wxT("Closed: %u")) % nErrorCode
);
248 Disconnect(wxT("Close"));
253 void CClientTCPSocket::Disconnect(const wxString
& strReason
)
255 byConnected
= ES_DISCONNECTED
;
257 if (m_client
->Disconnected(strReason
, true)) {
258 // Somehow, Safe_Delete() is beeing called by Disconnected(),
259 // or any other function that sets m_client to NULL,
260 // so we must check m_client first.
262 m_client
->SetSocket( NULL
);
263 m_client
->Safe_Delete();
273 void CClientTCPSocket::Safe_Delete()
275 // More paranoia - make sure client is unlinked in any case
277 m_client
->SetSocket( NULL
);
281 if ( !ForDeletion() && !OnDestroy() ) {
285 // lfroen: first of all - stop handler
286 m_ForDeletion
= true;
288 byConnected
= ES_DISCONNECTED
;
289 Close(); // Destroy is suposed to call Close(), but.. it doesn't hurt.
295 void CClientTCPSocket::Safe_Delete_Client()
298 m_client
->Safe_Delete();
304 bool CClientTCPSocket::ProcessPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
306 #ifdef __PACKET_RECV_DUMP__
307 //printf("Rec: OPCODE %x \n",opcode);
308 DumpMem(buffer
, size
);
310 if (!m_client
&& opcode
!= OP_HELLO
) {
311 throw wxString(wxT("Asks for something without saying hello"));
312 } else if (m_client
&& opcode
!= OP_HELLO
&& opcode
!= OP_HELLOANSWER
) {
313 m_client
->CheckHandshakeFinished();
317 case OP_HELLOANSWER
: { // 0.43b
318 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_HELLOANSWER from ") + m_client
->GetFullIP());
319 theStats::AddDownOverheadOther(size
);
320 m_client
->ProcessHelloAnswer(buffer
, size
);
322 // start secure identification, if
323 // - we have received OP_EMULEINFO and OP_HELLOANSWER (old eMule)
324 // - we have received eMule-OP_HELLOANSWER (new eMule)
325 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
326 m_client
->InfoPacketsReceived();
329 // Socket might die because of sending in InfoPacketsReceived, so check
331 m_client
->ConnectionEstablished();
334 // Socket might die on ConnectionEstablished somehow. Check it.
336 Notify_SharedCtrlRefreshClient( m_client
->ECID() , AVAILABLE_SOURCE
);
341 case OP_HELLO
: { // 0.43b
343 theStats::AddDownOverheadOther(size
);
344 bool bNewClient
= !m_client
;
346 // create new client to save standart informations
347 m_client
= new CUpDownClient(this);
351 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_HELLO from ") + m_client
->GetFullIP() );
353 bool bIsMuleHello
= false;
356 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
358 if (bNewClient
&& m_client
) {
359 // Don't let CUpDownClient::Disconnected be processed for a client which is not in the list of clients.
360 m_client
->Safe_Delete();
366 if (thePrefs::ParanoidFilter() && !IsLowID(m_client
->GetUserIDHybrid()) && (GetRemoteIP() != wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid()))) {
367 wxString reason
= wxT("Client claims a different IP from the one we received the hello packet from: ");
368 reason
+= Uint32toStringIP(wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid())) + wxT(" / ") + Uint32toStringIP(GetRemoteIP());
369 AddDebugLogLineN(logClient
, reason
);
371 m_client
->Safe_Delete();
374 Disconnect(wxT("Paranoid disconecting: ") + reason
);
378 // if IP is filtered, dont reply but disconnect...
379 if (theApp
->ipfilter
->IsFiltered(m_client
->GetIP())) {
381 m_client
->Safe_Delete();
384 Disconnect(wxT("IPFilter"));
390 // now we check if we know this client already. if yes this socket will
391 // be attached to the known client, the new client will be deleted
392 // and the var. "client" will point to the known client.
393 // if not we keep our new-constructed client ;)
394 if (theApp
->clientlist
->AttachToAlreadyKnown(&m_client
,this)) {
395 // update the old client informations
396 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
398 theApp
->clientlist
->AddClient(m_client
);
399 m_client
->SetCommentDirty();
401 Notify_SharedCtrlRefreshClient( m_client
->ECID(), AVAILABLE_SOURCE
);
402 // send a response packet with standart informations
403 if ((m_client
->GetHashType() == SO_EMULE
) && !bIsMuleHello
) {
404 m_client
->SendMuleInfoPacket(false);
407 // Client might die from Sending in SendMuleInfoPacket, so check
409 m_client
->SendHelloAnswer();
412 // Kry - If the other side supports it, send OS_INFO
413 // Client might die from Sending in SendHelloAnswer, so check
414 if (m_client
&& m_client
->GetOSInfoSupport()) {
415 m_client
->SendMuleInfoPacket(false,true); // Send the OS Info tag on the recycled Mule Info
418 // Client might die from Sending in SendMuleInfoPacket, so check
420 m_client
->ConnectionEstablished();
423 // start secure identification, if
424 // - we have received eMule-OP_HELLO (new eMule)
425 if (m_client
&& m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
426 m_client
->InfoPacketsReceived();
431 case OP_REQUESTFILENAME
: { // 0.43b
432 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTFILENAME from ") + m_client
->GetFullIP() );
434 theStats::AddDownOverheadFileRequest(size
);
435 // IP banned, no answer for this request
436 if (m_client
->IsBanned()) {
440 if (!m_client
->GetWaitStartTime()) {
441 m_client
->SetWaitStartTime();
443 CMemFile
data_in(buffer
, size
);
444 CMD4Hash reqfilehash
= data_in
.ReadHash();
445 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
446 if ( reqfile
== NULL
) {
447 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
448 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
452 // if we are downloading this file, this could be a new source
453 // no passive adding of files with only one part
454 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
455 if (thePrefs::GetMaxSourcePerFile() >
456 ((CPartFile
*)reqfile
)->GetSourceCount()) {
457 theApp
->downloadqueue
->CheckAndAddKnownSource((CPartFile
*)reqfile
, m_client
);
461 // check to see if this is a new file they are asking for
462 if (m_client
->GetUploadFileID() != reqfilehash
) {
463 m_client
->SetCommentDirty();
466 m_client
->SetUploadFileID(reqfile
);
467 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
470 CMemFile
data_out(128);
471 data_out
.WriteHash(reqfile
->GetFileHash());
473 // Since it's for somebody else to see, we need to send the prettified
474 // filename, rather than the (possibly) mangled actual filename.
475 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
477 CPacket
* packet
= new CPacket(data_out
, OP_EDONKEYPROT
, OP_REQFILENAMEANSWER
);
478 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
479 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_REQFILENAMEANSWER to ") + m_client
->GetFullIP() );
480 SendPacket(packet
,true);
482 // SendPacket might kill the socket, so check
484 m_client
->SendCommentInfo(reqfile
);
488 throw wxString(wxT("Invalid OP_REQUESTFILENAME packet size"));
491 case OP_SETREQFILEID
: { // 0.43b EXCEPT track of bad clients
492 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SETREQFILEID from ") + m_client
->GetFullIP() );
494 theStats::AddDownOverheadFileRequest(size
);
496 if (m_client
->IsBanned()) {
502 if (!m_client
->GetWaitStartTime()) {
503 m_client
->SetWaitStartTime();
506 const CMD4Hash
fileID(buffer
);
507 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
508 if ( reqfile
== NULL
) {
509 reqfile
= theApp
->downloadqueue
->GetFileByID(fileID
);
510 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
511 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
512 replypacket
->Copy16ToDataBuffer(fileID
.GetHash());
513 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
514 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILERE to ") + m_client
->GetFullIP() );
515 SendPacket(replypacket
, true);
520 // check to see if this is a new file they are asking for
521 if (m_client
->GetUploadFileID() != fileID
) {
522 m_client
->SetCommentDirty();
525 m_client
->SetUploadFileID(reqfile
);
527 CMemFile
data(16+16);
528 data
.WriteHash(reqfile
->GetFileHash());
529 if (reqfile
->IsPartFile()) {
530 ((CPartFile
*)reqfile
)->WritePartStatus(&data
);
534 CPacket
* packet
= new CPacket(data
, OP_EDONKEYPROT
, OP_FILESTATUS
);
535 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
536 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILESTATUS to ") + m_client
->GetFullIP() );
537 SendPacket(packet
, true);
540 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
545 case OP_FILEREQANSNOFIL
: { // 0.43b protocol, lacks ZZ's download manager on swap
546 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILEREQANSNOFIL from ") + m_client
->GetFullIP() );
548 theStats::AddDownOverheadFileRequest(size
);
550 // if that client does not have my file maybe has another different
551 CPartFile
* reqfile
= theApp
->downloadqueue
->GetFileByID(CMD4Hash(buffer
));
553 reqfile
->AddDeadSource( m_client
);
558 // we try to swap to another file ignoring no needed parts files
559 switch (m_client
->GetDownloadState()) {
562 case DS_NONEEDEDPARTS
:
563 if (!m_client
->SwapToAnotherFile(true, true, true, NULL
)) {
564 theApp
->downloadqueue
->RemoveSource(m_client
);
570 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
574 case OP_REQFILENAMEANSWER
: { // 0.43b except check for bad clients
575 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQFILENAMEANSWER from ") + m_client
->GetFullIP() );
577 theStats::AddDownOverheadFileRequest(size
);
578 CMemFile
data(buffer
, size
);
579 CMD4Hash hash
= data
.ReadHash();
580 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
581 m_client
->ProcessFileInfo(&data
, file
);
585 case OP_FILESTATUS
: { // 0.43b except check for bad clients
586 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILESTATUS from ") + m_client
->GetFullIP() );
588 theStats::AddDownOverheadFileRequest(size
);
589 CMemFile
data(buffer
, size
);
590 CMD4Hash hash
= data
.ReadHash();
591 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
592 m_client
->ProcessFileStatus(false, &data
, file
);
596 case OP_STARTUPLOADREQ
: {
597 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_STARTUPLOADREQ from ") + m_client
->GetFullIP() );
599 theStats::AddDownOverheadFileRequest(size
);
601 if (!m_client
->CheckHandshakeFinished()) {
605 m_client
->CheckForAggressive();
606 if ( m_client
->IsBanned() ) {
611 const CMD4Hash
fileID(buffer
);
612 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
614 if (m_client
->GetUploadFileID() != fileID
) {
615 m_client
->SetCommentDirty();
617 m_client
->SetUploadFileID(reqfile
);
618 m_client
->SendCommentInfo(reqfile
);
620 // Socket might die because of SendCommentInfo, so check
622 theApp
->uploadqueue
->AddClientToQueue(m_client
);
628 case OP_QUEUERANK
: { // 0.43b
629 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_QUEUERANK from ") + m_client
->GetFullIP() );
631 theStats::AddDownOverheadFileRequest(size
);
632 CMemFile
data(buffer
, size
);
633 uint32 rank
= data
.ReadUInt32();
635 m_client
->SetRemoteQueueRank(rank
);
639 case OP_ACCEPTUPLOADREQ
: { // 0.42e (xcept khaos stats)
640 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ACCEPTUPLOADREQ from ") + m_client
->GetFullIP() );
642 theStats::AddDownOverheadFileRequest(size
);
643 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
644 if (m_client
->GetDownloadState() == DS_ONQUEUE
) {
645 m_client
->SetDownloadState(DS_DOWNLOADING
);
646 m_client
->SetLastPartAsked(0xffff); // Reset current downloaded Chunk // Maella -Enhanced Chunk Selection- (based on jicxicmic)
647 m_client
->SendBlockRequests();
650 if (!m_client
->GetSentCancelTransfer()) {
651 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
652 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
653 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
654 m_client
->SendPacket(packet
,true,true);
656 // SendPacket can cause the socket to die, so check
658 m_client
->SetSentCancelTransfer(1);
662 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
667 case OP_REQUESTPARTS
: { // 0.43b
668 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
670 theStats::AddDownOverheadFileRequest(size
);
672 m_client
->ProcessRequestPartsPacket(buffer
, size
, false);
677 case OP_CANCELTRANSFER
: { // 0.43b
678 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CANCELTRANSFER from ") + m_client
->GetFullIP() );
680 theStats::AddDownOverheadFileRequest(size
);
681 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
682 AddDebugLogLineN( logClient
, m_client
->GetUserName() + wxT(": Upload session ended due canceled transfer."));
686 case OP_END_OF_DOWNLOAD
: { // 0.43b except check for bad clients
687 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_END_OF_DOWNLOAD from ") + m_client
->GetFullIP() );
689 theStats::AddDownOverheadFileRequest(size
);
690 if (size
>=16 && m_client
->GetUploadFileID() == CMD4Hash(buffer
)) {
691 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
692 AddDebugLogLineN( logClient
, m_client
->GetUserName() + wxT(": Upload session ended due ended transfer."));
697 case OP_HASHSETREQUEST
: { // 0.43b except check for bad clients
698 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_HASHSETREQUEST from ") + m_client
->GetFullIP() );
701 theStats::AddDownOverheadFileRequest(size
);
703 throw wxString(wxT("Invalid OP_HASHSETREQUEST packet size"));
705 m_client
->SendHashsetPacket(CMD4Hash(buffer
));
709 case OP_HASHSETANSWER
: { // 0.43b
710 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_HASHSETANSWER from ") + m_client
->GetFullIP() );
712 theStats::AddDownOverheadFileRequest(size
);
713 m_client
->ProcessHashSet(buffer
, size
);
717 case OP_SENDINGPART
: { // 0.47a
718 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SENDINGPART from ") + m_client
->GetFullIP() );
720 if ( m_client
->GetRequestFile() &&
721 !m_client
->GetRequestFile()->IsStopped() &&
722 (m_client
->GetRequestFile()->GetStatus() == PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
724 m_client
->ProcessBlockPacket(buffer
, size
, false, false);
727 ( m_client
->GetRequestFile()->IsStopped() ||
728 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
729 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
) ) {
730 if (!m_client
->GetSentCancelTransfer()) {
731 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
732 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
733 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
734 m_client
->SendPacket(packet
,true,true);
736 // Socket might die because of SendPacket, so check
738 m_client
->SetSentCancelTransfer(1);
742 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
745 if (!m_client
->GetSentCancelTransfer()) {
746 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
747 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
748 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
749 m_client
->SendPacket(packet
,true,true);
751 // Socket might die because of SendPacket, so check
752 m_client
->SetSentCancelTransfer(1);
754 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
759 case OP_OUTOFPARTREQS
: { // 0.43b
760 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_OUTOFPARTREQS from ") + m_client
->GetFullIP() );
762 theStats::AddDownOverheadFileRequest(size
);
763 if (m_client
->GetDownloadState() == DS_DOWNLOADING
) {
764 m_client
->SetDownloadState(DS_ONQUEUE
);
769 case OP_CHANGE_CLIENT_ID
: { // Kad reviewed
770 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CHANGE_CLIENT_ID from ") + m_client
->GetFullIP() );
772 theStats::AddDownOverheadOther(size
);
773 CMemFile
data(buffer
, size
);
774 uint32 nNewUserID
= data
.ReadUInt32();
775 uint32 nNewServerIP
= data
.ReadUInt32();
777 if (IsLowID(nNewUserID
)) { // client changed server and gots a LowID
778 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
779 if (pNewServer
!= NULL
){
780 m_client
->SetUserIDHybrid(nNewUserID
); // update UserID only if we know the server
781 m_client
->SetServerIP(nNewServerIP
);
782 m_client
->SetServerPort(pNewServer
->GetPort());
784 } else if (nNewUserID
== m_client
->GetIP()) { // client changed server and gots a HighID(IP)
785 m_client
->SetUserIDHybrid(wxUINT32_SWAP_ALWAYS(nNewUserID
));
786 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
787 if (pNewServer
!= NULL
){
788 m_client
->SetServerIP(nNewServerIP
);
789 m_client
->SetServerPort(pNewServer
->GetPort());
796 case OP_CHANGE_SLOT
:{ // 0.43b
797 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CHANGE_SLOT from ") + m_client
->GetFullIP() );
799 // sometimes sent by Hybrid
800 theStats::AddDownOverheadOther(size
);
804 case OP_MESSAGE
: { // 0.43b
805 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MESSAGE from ") + m_client
->GetFullIP() );
807 theStats::AddDownOverheadOther(size
);
810 throw wxString(wxT("invalid message packet"));
812 CMemFile
message_file(buffer
, size
);
813 uint16 length
= message_file
.ReadUInt16();
814 if (length
+ 2u != size
) {
815 throw wxString(wxT("invalid message packet"));
818 // limit message length
819 static const uint16 MAX_CLIENT_MSG_LEN
= 450;
821 if (length
> MAX_CLIENT_MSG_LEN
) {
822 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Message from '%s' (IP:%s) exceeds limit by %u chars, truncated."))
823 % m_client
->GetUserName() % m_client
->GetFullIP() % (length
- MAX_CLIENT_MSG_LEN
));
824 length
= MAX_CLIENT_MSG_LEN
;
827 wxString message
= message_file
.ReadOnlyString((m_client
->GetUnicodeSupport() != utf8strNone
), length
);
828 m_client
->ProcessChatMessage(message
);
833 case OP_ASKSHAREDFILES
: { // 0.43b (well, er, it does the same, but in our own way)
834 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILES from ") + m_client
->GetFullIP() );
836 // client wants to know what we have in share, let's see if we allow him to know that
837 theStats::AddDownOverheadOther(size
);
838 // IP banned, no answer for this request
839 if (m_client
->IsBanned()) {
843 if (thePrefs::CanSeeShares() == vsfaEverybody
|| (thePrefs::CanSeeShares() == vsfaFriends
&& m_client
->IsFriend())) {
844 AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Accepted"))
845 % m_client
->GetUserName()
846 % m_client
->GetUserIDHybrid() );
848 std::vector
<CKnownFile
*> list
;
849 theApp
->sharedfiles
->CopyFileList(list
);
851 CMemFile
tempfile(80);
852 tempfile
.WriteUInt32(list
.size());
853 for (unsigned i
= 0; i
< list
.size(); ++i
) {
854 if (!list
[i
]->IsLargeFile() || m_client
->SupportsLargeFiles()) {
855 list
[i
]->CreateOfferedFilePacket(&tempfile
, NULL
, m_client
);
859 // create a packet and send it
860 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESANSWER
);
861 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESANSWER to ") + m_client
->GetFullIP() );
862 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
863 SendPacket(replypacket
, true, true);
865 AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Denied"))
866 % m_client
->GetUserName()
867 % m_client
->GetUserIDHybrid() );
869 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
870 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
871 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
872 SendPacket(replypacket
, true, true);
878 case OP_ASKSHAREDFILESANSWER
: { // 0.43b
879 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESANSWER from ") + m_client
->GetFullIP() );
881 theStats::AddDownOverheadOther(size
);
883 m_client
->ProcessSharedFileList(buffer
, size
, EmptyStr
);
887 case OP_ASKSHAREDDIRS
: { // 0.43b
888 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRS from ") + m_client
->GetFullIP() );
890 theStats::AddDownOverheadOther(size
);
891 wxASSERT( size
== 0 );
892 // IP banned, no answer for this request
893 if (m_client
->IsBanned()) {
896 if ((thePrefs::CanSeeShares()==vsfaEverybody
) || ((thePrefs::CanSeeShares()==vsfaFriends
) && m_client
->IsFriend())) {
897 AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Accepted") )
898 % m_client
->GetUserName()
899 % m_client
->GetUserIDHybrid() );
900 // send the list of shared directories
901 m_client
->SendSharedDirectories();
903 AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Denied") )
904 % m_client
->GetUserName()
905 % m_client
->GetUserIDHybrid() );
907 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
908 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
909 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
910 SendPacket(replypacket
, true, true);
916 case OP_ASKSHAREDFILESDIR
: { // 0.43b
917 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIR from ") + m_client
->GetFullIP() );
919 theStats::AddDownOverheadOther(size
);
920 // IP banned, no answer for this request
921 if (m_client
->IsBanned()) {
924 CMemFile
data(buffer
, size
);
926 wxString strReqDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
927 if (thePrefs::CanSeeShares()==vsfaEverybody
|| (thePrefs::CanSeeShares()==vsfaFriends
&& m_client
->IsFriend())) {
928 AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> accepted")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
929 wxASSERT( data
.GetPosition() == data
.GetLength() );
930 // send the list of shared files for the requested directory
931 m_client
->SendSharedFilesOfDirectory(strReqDir
);
933 AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> denied")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
935 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
936 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
937 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
938 SendPacket(replypacket
, true, true);
943 case OP_ASKSHAREDDIRSANS
:{ // 0.43b
944 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRSANS from ") + m_client
->GetFullIP() );
946 theStats::AddDownOverheadOther(size
);
947 if (m_client
->GetFileListRequested() == 1){
948 CMemFile
data(buffer
, size
);
949 uint32 uDirs
= data
.ReadUInt32();
950 for (uint32 i
= 0; i
< uDirs
; i
++){
951 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
952 AddLogLineC(CFormat( _("User %s (%u) shares directory '%s'") )
953 % m_client
->GetUserName()
954 % m_client
->GetUserIDHybrid()
957 CMemFile
tempfile(80);
958 tempfile
.WriteString(strDir
, m_client
->GetUnicodeSupport());
959 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESDIR
);
960 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
961 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESDIR to ") + m_client
->GetFullIP() );
962 SendPacket(replypacket
, true, true);
964 wxASSERT( data
.GetPosition() == data
.GetLength() );
965 m_client
->SetFileListRequested(uDirs
);
967 AddLogLineC(CFormat( _("User %s (%u) sent unrequested shared dirs.") )
968 % m_client
->GetUserName()
969 % m_client
->GetUserIDHybrid() );
974 case OP_ASKSHAREDFILESDIRANS
: { // 0.43b
975 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIRANS from ") + m_client
->GetFullIP() );
977 theStats::AddDownOverheadOther(size
);
978 CMemFile
data(buffer
, size
);
979 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
981 if (m_client
->GetFileListRequested() > 0){
982 AddLogLineC(CFormat( _("User %s (%u) sent sharedfiles-list for directory '%s'") )
983 % m_client
->GetUserName()
984 % m_client
->GetUserIDHybrid()
987 m_client
->ProcessSharedFileList(buffer
+ data
.GetPosition(), size
- data
.GetPosition(), strDir
);
988 if (m_client
->GetFileListRequested() == 0) {
989 AddLogLineC(CFormat( _("User %s (%u) finished sending sharedfiles-list") )
990 % m_client
->GetUserName()
991 % m_client
->GetUserIDHybrid() );
994 AddLogLineC(CFormat( _("User %s (%u) sent unwanted sharedfiles-list") )
995 % m_client
->GetUserName()
996 % m_client
->GetUserIDHybrid() );
1001 case OP_ASKSHAREDDENIEDANS
:
1002 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDENIEDANS from ") + m_client
->GetFullIP() );
1004 theStats::AddDownOverheadOther(size
);
1005 wxASSERT( size
== 0 );
1006 AddLogLineC(CFormat( _("User %s (%u) denied access to shared directories/files list") )
1007 % m_client
->GetUserName()
1008 % m_client
->GetUserIDHybrid() );
1010 m_client
->SetFileListRequested(0);
1014 theStats::AddDownOverheadOther(size
);
1015 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Edonkey packet: unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1023 bool CClientTCPSocket::ProcessExtPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
1025 #ifdef __PACKET_RECV_DUMP__
1026 //printf("Rec: OPCODE %x \n",opcode);
1027 DumpMem(buffer
,size
);
1030 // 0.42e - except the catchs on mem exception and file exception
1032 throw wxString(wxT("Unknown clients sends extended protocol packet"));
1035 if (!client->CheckHandshakeFinished()) {
1036 // Here comes an extended packet without finishing the handshake.
1037 // IMHO, we should disconnect the client.
1038 throw wxString(wxT("Client send extended packet before finishing handshake"));
1042 case OP_MULTIPACKET_EXT
:
1043 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET_EXT from ") + m_client
->GetFullIP());
1044 case OP_MULTIPACKET
: {
1045 if (opcode
== OP_MULTIPACKET
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET from ") + m_client
->GetFullIP() );
1047 theStats::AddDownOverheadFileRequest(size
);
1049 if (m_client
->IsBanned()) {
1053 if (!m_client
->CheckHandshakeFinished()) {
1054 // Here comes an extended packet without finishing the handshake.
1055 // IMHO, we should disconnect the client.
1056 throw wxString(wxT("Client send OP_MULTIPACKET before finishing handshake"));
1059 CMemFile
data_in(buffer
, size
);
1060 CMD4Hash reqfilehash
= data_in
.ReadHash();
1061 uint64 nSize
= (opcode
== OP_MULTIPACKET_EXT
) ? data_in
.ReadUInt64() : 0;
1063 bool file_not_found
= false;
1064 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
1065 if ( reqfile
== NULL
){
1066 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1067 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
1068 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a non-shared file"));
1069 file_not_found
= true;
1073 if (!file_not_found
&& reqfile
->IsLargeFile() && !m_client
->SupportsLargeFiles()) {
1074 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a large file but doesn't support them"));
1075 file_not_found
= true;
1078 if (!file_not_found
&& nSize
&& (reqfile
->GetFileSize() != nSize
)) {
1079 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a file but specified wrong size"));
1080 file_not_found
= true;
1083 if (file_not_found
) {
1084 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
1085 replypacket
->Copy16ToDataBuffer(reqfilehash
.GetHash());
1086 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
1087 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILEREQANSNOFIL to ") + m_client
->GetFullIP() );
1088 SendPacket(replypacket
, true);
1092 if (!m_client
->GetWaitStartTime()) {
1093 m_client
->SetWaitStartTime();
1095 // if we are downloading this file, this could be a new source
1096 // no passive adding of files with only one part
1097 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
1098 if (thePrefs::GetMaxSourcePerFile() > ((CPartFile
*)reqfile
)->GetSourceCount()) {
1099 theApp
->downloadqueue
->CheckAndAddKnownSource((CPartFile
*)reqfile
, m_client
);
1102 // check to see if this is a new file they are asking for
1103 if (m_client
->GetUploadFileID() != reqfilehash
) {
1104 m_client
->SetCommentDirty();
1106 m_client
->SetUploadFileID(reqfile
);
1107 CMemFile
data_out(128);
1108 data_out
.WriteHash(reqfile
->GetFileHash());
1109 while(data_in
.GetLength()-data_in
.GetPosition()) {
1111 throw wxString(wxT("Client suddenly disconnected"));
1113 uint8 opcode_in
= data_in
.ReadUInt8();
1115 case OP_REQUESTFILENAME
: {
1116 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTFILENAME") );
1117 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
1118 data_out
.WriteUInt8(OP_REQFILENAMEANSWER
);
1120 // Since it's for somebody else to see, we need to send the prettified
1121 // filename, rather than the (possibly) mangled actual filename
1122 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
1125 case OP_AICHFILEHASHREQ
: {
1126 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_AICHFILEHASHANS") );
1127 if (m_client
->IsSupportingAICH() && reqfile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1128 && reqfile
->GetAICHHashset()->HasValidMasterHash())
1130 data_out
.WriteUInt8(OP_AICHFILEHASHANS
);
1131 reqfile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1135 case OP_SETREQFILEID
: {
1136 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_SETREQFILEID") );
1137 data_out
.WriteUInt8(OP_FILESTATUS
);
1138 if (reqfile
->IsPartFile()) {
1139 ((CPartFile
*)reqfile
)->WritePartStatus(&data_out
);
1141 data_out
.WriteUInt16(0);
1145 //We still send the source packet separately..
1146 //We could send it within this packet.. If agreeded, I will fix it..
1147 case OP_REQUESTSOURCES2
:
1148 case OP_REQUESTSOURCES
: {
1149 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTSOURCES(2)") );
1150 uint8 byRequestedVersion
= 0;
1151 uint16 byRequestedOptions
= 0;
1152 if (opcode_in
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1153 byRequestedVersion
= data_in
.ReadUInt8();
1154 byRequestedOptions
= data_in
.ReadUInt16();
1157 //Although this shouldn't happen, it's a just in case to any Mods that mess with version numbers.
1159 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() > 1) {
1160 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1161 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1163 //if not complete and file is rare
1164 ( reqfile
->IsPartFile()
1165 && (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1166 && ((CPartFile
*)reqfile
)->GetSourceCount() <= RARE_FILE
1168 //OR if file is not rare or if file is complete
1169 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1172 m_client
->SetLastSrcReqTime();
1173 CPacket
* tosend
= reqfile
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1175 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1176 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1177 SendPacket(tosend
, true);
1186 if( data_out
.GetLength() > 16 ) {
1187 CPacket
* reply
= new CPacket(data_out
, OP_EMULEPROT
, OP_MULTIPACKETANSWER
);
1188 theStats::AddUpOverheadFileRequest(reply
->GetPacketSize());
1189 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_MULTIPACKETANSWER to ") + m_client
->GetFullIP() );
1190 SendPacket(reply
, true);
1195 case OP_MULTIPACKETANSWER
: { // 0.43b
1196 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKETANSWER from ") + m_client
->GetFullIP() );
1198 theStats::AddDownOverheadFileRequest(size
);
1200 if (m_client
->IsBanned()) {
1204 if (m_client
->GetKadPort() && m_client
->GetKadVersion() > 1) {
1205 Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(m_client
->GetIP()), m_client
->GetKadPort());
1208 if (!m_client
->CheckHandshakeFinished()) {
1209 // Here comes an extended packet without finishing the handshake.
1210 // IMHO, we should disconnect the client.
1211 throw wxString(wxT("Client send OP_MULTIPACKETANSWER before finishing handshake"));
1214 CMemFile
data_in(buffer
, size
);
1215 CMD4Hash reqfilehash
= data_in
.ReadHash();
1216 const CPartFile
*reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1217 //Make sure we are downloading this file.
1219 throw wxString(wxT(" Wrong File ID: (OP_MULTIPACKETANSWER; reqfile==NULL)"));
1221 if ( !m_client
->GetRequestFile() ) {
1223 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; client->reqfile==NULL)"));
1225 if (reqfile
!= m_client
->GetRequestFile()) {
1226 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; reqfile!=client->reqfile)"));
1228 while (data_in
.GetLength()-data_in
.GetPosition()) {
1229 // Some of the cases down there can actually send a packet and lose the client
1231 throw wxString(wxT("Client suddenly disconnected"));
1233 uint8 opcode_in
= data_in
.ReadUInt8();
1235 case OP_REQFILENAMEANSWER
: {
1237 throw wxString(wxT("Client suddenly disconnected"));
1239 m_client
->ProcessFileInfo(&data_in
, reqfile
);
1243 case OP_FILESTATUS
: {
1245 throw wxString(wxT("Client suddenly disconnected"));
1247 m_client
->ProcessFileStatus(false, &data_in
, reqfile
);
1251 case OP_AICHFILEHASHANS
: {
1253 throw wxString(wxT("Client suddenly disconnected"));
1255 m_client
->ProcessAICHFileHash(&data_in
, reqfile
);
1265 case OP_EMULEINFO
: { // 0.43b
1266 theStats::AddDownOverheadOther(size
);
1268 if (!m_client
->ProcessMuleInfoPacket(buffer
, size
)) {
1269 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFO from ") + m_client
->GetFullIP() );
1271 // If it's not a OS Info packet, is an old client
1272 // start secure identification, if
1273 // - we have received eD2K and eMule info (old eMule)
1274 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1275 m_client
->InfoPacketsReceived();
1277 m_client
->SendMuleInfoPacket(true);
1279 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFO is an OS_INFO") );
1283 case OP_EMULEINFOANSWER
: { // 0.43b
1284 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFOANSWER from ") + m_client
->GetFullIP() );
1285 theStats::AddDownOverheadOther(size
);
1287 m_client
->ProcessMuleInfoPacket(buffer
, size
);
1288 // start secure identification, if
1289 // - we have received eD2K and eMule info (old eMule)
1291 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1292 m_client
->InfoPacketsReceived();
1298 case OP_SECIDENTSTATE
:{ // 0.43b
1299 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SECIDENTSTATE from ") + m_client
->GetFullIP() );
1301 if (!m_client
->CheckHandshakeFinished()) {
1302 // Here comes an extended packet without finishing the handshake.
1303 // IMHO, we should disconnect the client.
1304 throw wxString(wxT("Client send OP_SECIDENTSTATE before finishing handshake"));
1306 m_client
->ProcessSecIdentStatePacket(buffer
, size
);
1307 // ProcessSecIdentStatePacket() might cause the socket to die, so check
1309 int SecureIdentState
= m_client
->GetSecureIdentState();
1310 if (SecureIdentState
== IS_SIGNATURENEEDED
) {
1311 m_client
->SendSignaturePacket();
1312 } else if (SecureIdentState
== IS_KEYANDSIGNEEDED
) {
1313 m_client
->SendPublicKeyPacket();
1314 // SendPublicKeyPacket() might cause the socket to die, so check
1316 m_client
->SendSignaturePacket();
1323 case OP_PUBLICKEY
: { // 0.43b
1324 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICKEY from ") + m_client
->GetFullIP() );
1326 if (m_client
->IsBanned() ){
1330 if (!m_client
->CheckHandshakeFinished()) {
1331 // Here comes an extended packet without finishing the handshake.
1332 // IMHO, we should disconnect the client.
1333 throw wxString(wxT("Client send OP_PUBLICKEY before finishing handshake"));
1336 m_client
->ProcessPublicKeyPacket(buffer
, size
);
1339 case OP_SIGNATURE
:{ // 0.43b
1340 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SIGNATURE from ") + m_client
->GetFullIP() );
1342 if (!m_client
->CheckHandshakeFinished()) {
1343 // Here comes an extended packet without finishing the handshake.
1344 // IMHO, we should disconnect the client.
1345 throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1348 m_client
->ProcessSignaturePacket(buffer
, size
);
1351 case OP_SENDINGPART_I64
:
1352 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SENDINGPART_I64 from ") + m_client
->GetFullIP() );
1353 case OP_COMPRESSEDPART_I64
:
1354 if (opcode
== OP_COMPRESSEDPART_I64
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART_I64 from ") + m_client
->GetFullIP() );
1355 case OP_COMPRESSEDPART
: { // 0.47a
1356 if (opcode
== OP_COMPRESSEDPART
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART from ") + m_client
->GetFullIP() );
1358 if (!m_client
->CheckHandshakeFinished()) {
1359 // Here comes an extended packet without finishing the handshake.
1360 // IMHO, we should disconnect the client.
1361 throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1364 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
1366 m_client
->ProcessBlockPacket(buffer
, size
, (opcode
!= OP_SENDINGPART_I64
), (opcode
== OP_COMPRESSEDPART_I64
) || (opcode
== OP_SENDINGPART_I64
));
1369 m_client
->GetRequestFile()->IsStopped() ||
1370 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
1371 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
)) {
1372 if (!m_client
->GetSentCancelTransfer()) {
1373 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1374 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1375 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1376 m_client
->SendPacket(packet
,true,true);
1379 m_client
->SetSentCancelTransfer(1);
1384 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
1388 if (!m_client
->GetSentCancelTransfer()) {
1389 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1390 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1391 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1392 m_client
->SendPacket(packet
,true,true);
1395 m_client
->SetSentCancelTransfer(1);
1400 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
1405 case OP_REQUESTPARTS_I64
: {
1406 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS_I64 from ") + m_client
->GetFullIP() );
1408 theStats::AddDownOverheadFileRequest(size
);
1410 m_client
->ProcessRequestPartsPacket(buffer
, size
, true);
1414 case OP_QUEUERANKING
: { // 0.43b
1415 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_QUEUERANKING from ") + m_client
->GetFullIP() );
1417 theStats::AddDownOverheadOther(size
);
1419 if (!m_client
->CheckHandshakeFinished()) {
1420 // Here comes an extended packet without finishing the handshake.
1421 // IMHO, we should disconnect the client.
1422 throw wxString(wxT("Client send OP_QUEUERANKING before finishing handshake"));
1426 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1429 uint16 newrank
= PeekUInt16(buffer
);
1430 m_client
->SetRemoteQueueFull(false);
1431 m_client
->SetRemoteQueueRank(newrank
);
1434 case OP_REQUESTSOURCES2
:
1435 case OP_REQUESTSOURCES
:{
1436 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTSOURCES from ") + m_client
->GetFullIP() );
1438 theStats::AddDownOverheadSourceExchange(size
);
1440 if (!m_client
->CheckHandshakeFinished()) {
1441 // Here comes an extended packet without finishing the handshake.
1442 // IMHO, we should disconnect the client.
1443 throw wxString(wxT("Client send OP_REQUESTSOURCES before finishing handshake"));
1446 uint8 byRequestedVersion
= 0;
1447 uint16 byRequestedOptions
= 0;
1448 CMemFile
data_in(buffer
, size
);
1449 if (opcode
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1450 byRequestedVersion
= data_in
.ReadUInt8();
1451 byRequestedOptions
= data_in
.ReadUInt16();
1454 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() >= 1) {
1456 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1458 //first check shared file list, then download list
1459 const CMD4Hash
fileID(buffer
);
1460 CKnownFile
* file
= theApp
->sharedfiles
->GetFileByID(fileID
);
1462 file
= theApp
->downloadqueue
->GetFileByID(fileID
);
1465 // There are some clients which do not follow the correct protocol procedure of sending
1466 // the sequence OP_REQUESTFILENAME, OP_SETREQFILEID, OP_REQUESTSOURCES. If those clients
1467 // are doing this, they will not get the optimal set of sources which we could offer if
1468 // they would follow the above noted protocol sequence. They better do it the right way
1469 // or they will get just a random set of sources because we do not know their download
1470 // part status which may get cleared with the call of 'SetUploadFileID'.
1471 m_client
->SetUploadFileID(file
);
1473 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1474 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1476 //if not complete and file is rare, allow once every 40 minutes
1477 ( file
->IsPartFile() &&
1478 ((CPartFile
*)file
)->GetSourceCount() <= RARE_FILE
&&
1479 (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1481 //OR if file is not rare or if file is complete, allow every 90 minutes
1482 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1485 m_client
->SetLastSrcReqTime();
1486 CPacket
* tosend
= file
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1488 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1489 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1490 SendPacket(tosend
, true, true);
1497 case OP_ANSWERSOURCES
: {
1498 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ANSWERSOURCES from ") + m_client
->GetFullIP() );
1500 theStats::AddDownOverheadSourceExchange(size
);
1502 if (!m_client
->CheckHandshakeFinished()) {
1503 // Here comes an extended packet without finishing the handshake.
1504 // IMHO, we should disconnect the client.
1505 throw wxString(wxT("Client send OP_ANSWERSOURCES before finishing handshake"));
1508 CMemFile
data(buffer
, size
);
1509 CMD4Hash hash
= data
.ReadHash();
1510 const CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1512 if (file
->IsPartFile()){
1513 //set the client's answer time
1514 m_client
->SetLastSrcAnswerTime();
1515 //and set the file's last answer time
1516 ((CPartFile
*)file
)->SetLastAnsweredTime();
1518 ((CPartFile
*)file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, m_client
->GetSourceExchange1Version(), false, m_client
);
1523 case OP_ANSWERSOURCES2
: {
1524 //printf("Received OP_ANSWERSOURCES2\n");
1525 theStats::AddDownOverheadSourceExchange(size
);
1527 if (!m_client
->CheckHandshakeFinished()) {
1528 // Here comes an extended packet without finishing the handshake.
1529 // IMHO, we should disconnect the client.
1530 throw wxString(wxT("Client send OP_ANSWERSOURCES2 before finishing handshake"));
1533 CMemFile
data(buffer
, size
);
1534 uint8 byVersion
= data
.ReadUInt8();
1535 CMD4Hash hash
= data
.ReadHash();
1536 const CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1538 if (file
->IsPartFile()){
1539 //set the client's answer time
1540 m_client
->SetLastSrcAnswerTime();
1541 //and set the file's last answer time
1542 ((CPartFile
*)file
)->SetLastAnsweredTime();
1543 ((CPartFile
*)file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, byVersion
, true, m_client
);
1548 case OP_FILEDESC
: { // 0.43b
1549 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILEDESC from ") + m_client
->GetFullIP() );
1551 theStats::AddDownOverheadFileRequest(size
);
1553 if (!m_client
->CheckHandshakeFinished()) {
1554 // Here comes an extended packet without finishing the handshake.
1555 // IMHO, we should disconnect the client.
1556 throw wxString(wxT("Client send OP_FILEDESC before finishing handshake"));
1559 m_client
->ProcessMuleCommentPacket(buffer
, size
);
1564 case OP_REQUESTPREVIEW
: {
1565 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPREVIEW from ") + m_client
->GetFullIP() );
1569 case OP_PREVIEWANSWER
: {
1570 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PREVIEWANSWER from ") + m_client
->GetFullIP() );
1574 case OP_PUBLICIP_ANSWER
: {
1575 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_ANSWER from ") + m_client
->GetFullIP() );
1576 theStats::AddDownOverheadOther(size
);
1577 m_client
->ProcessPublicIPAnswer(buffer
, size
);
1580 case OP_PUBLICIP_REQ
: {
1581 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_REQ from ") + m_client
->GetFullIP() );
1582 theStats::AddDownOverheadOther(size
);
1583 CPacket
* pPacket
= new CPacket(OP_PUBLICIP_ANSWER
, 4, OP_EMULEPROT
);
1584 pPacket
->CopyUInt32ToDataBuffer(m_client
->GetIP());
1585 theStats::AddUpOverheadOther(pPacket
->GetPacketSize());
1586 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_PUBLICIP_ANSWER to") + m_client
->GetFullIP());
1587 SendPacket(pPacket
);
1590 case OP_AICHANSWER
: {
1591 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHANSWER from ") + m_client
->GetFullIP() );
1592 theStats::AddDownOverheadOther(size
);
1593 m_client
->ProcessAICHAnswer(buffer
, size
);
1596 case OP_AICHREQUEST
: {
1597 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHREQUEST from ") + m_client
->GetFullIP() );
1598 theStats::AddDownOverheadOther(size
);
1599 m_client
->ProcessAICHRequest(buffer
, size
);
1602 case OP_AICHFILEHASHANS
: {
1603 // those should not be received normally, since we should only get those in MULTIPACKET
1604 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHANS from ") + m_client
->GetFullIP() );
1605 theStats::AddDownOverheadOther(size
);
1606 CMemFile
data(buffer
, size
);
1607 m_client
->ProcessAICHFileHash(&data
, NULL
);
1610 case OP_AICHFILEHASHREQ
: {
1611 // those should not be received normally, since we should only get those in MULTIPACKET
1612 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHREQ from ") + m_client
->GetFullIP() );
1613 CMemFile
data(buffer
, size
);
1614 CMD4Hash hash
= data
.ReadHash();
1615 CKnownFile
* pPartFile
= theApp
->sharedfiles
->GetFileByID(hash
);
1616 if (pPartFile
== NULL
){
1620 if (m_client
->IsSupportingAICH() && pPartFile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1621 && pPartFile
->GetAICHHashset()->HasValidMasterHash()) {
1623 data_out
.WriteHash(hash
);
1624 pPartFile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1625 CPacket
* packet
= new CPacket(data_out
, OP_EMULEPROT
, OP_AICHFILEHASHANS
);
1626 theStats::AddUpOverheadOther(packet
->GetPacketSize());
1627 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_AICHFILEHASHANS to") + m_client
->GetFullIP());
1633 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CALLBACK from ") + m_client
->GetFullIP() );
1634 theStats::AddDownOverheadFileRequest(size
);
1635 if(!Kademlia::CKademlia::IsRunning()) {
1638 CMemFile
data(buffer
, size
);
1639 CUInt128 check
= data
.ReadUInt128();
1640 check
.XOR(Kademlia::CUInt128(true));
1641 if( check
.CompareTo(Kademlia::CKademlia::GetPrefs()->GetKadID())) {
1644 CUInt128 fileid
= data
.ReadUInt128();
1646 fileid
.ToByteArray(fileid2
);
1647 const CMD4Hash
fileHash(fileid2
);
1648 if (theApp
->sharedfiles
->GetFileByID(fileHash
) == NULL
) {
1649 if (theApp
->downloadqueue
->GetFileByID(fileHash
) == NULL
) {
1654 uint32 ip
= data
.ReadUInt32();
1655 uint16 tcp
= data
.ReadUInt16();
1656 CUpDownClient
* callback
;
1657 callback
= theApp
->clientlist
->FindClientByIP(wxUINT32_SWAP_ALWAYS(ip
), tcp
);
1658 if( callback
== NULL
) {
1659 //#warning Do we actually have to check friend status here?
1660 callback
= new CUpDownClient(tcp
,ip
,0,0,NULL
,false, false);
1661 theApp
->clientlist
->AddClient(callback
);
1663 callback
->TryToConnect(true);
1667 case OP_BUDDYPING
: {
1668 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_BUDDYPING from ") + m_client
->GetFullIP() );
1669 theStats::AddDownOverheadKad(size
);
1671 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1672 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 || !m_client
->AllowIncomeingBuddyPingPong() ) {
1673 //This ping was not from our buddy or wrong version or packet sent to fast. Ignore
1677 m_client
->SetLastBuddyPingPongTime();
1678 CPacket
* replypacket
= new CPacket(OP_BUDDYPONG
, 0, OP_EMULEPROT
);
1679 theStats::AddUpOverheadKad(replypacket
->GetPacketSize());
1680 AddDebugLogLineN(logLocalClient
,wxT("Local Client: OP_BUDDYPONG to ") + m_client
->GetFullIP());
1681 SendPacket(replypacket
);
1684 case OP_BUDDYPONG
: {
1685 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_BUDDYPONG from ") + m_client
->GetFullIP() );
1686 theStats::AddDownOverheadKad(size
);
1688 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1689 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 ) {
1690 //This pong was not from our buddy or wrong version. Ignore
1693 m_client
->SetLastBuddyPingPongTime();
1694 //All this is for is to reset our socket timeout.
1697 case OP_REASKCALLBACKTCP
: {
1698 theStats::AddDownOverheadFileRequest(size
);
1699 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1700 if (buddy
!= m_client
) {
1701 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() + wxT(" which is not our buddy!") );
1702 //This callback was not from our buddy.. Ignore.
1705 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() );
1706 CMemFile
data_in(buffer
, size
);
1707 uint32 destip
= data_in
.ReadUInt32();
1708 uint16 destport
= data_in
.ReadUInt16();
1709 CMD4Hash hash
= data_in
.ReadHash();
1710 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(hash
);
1712 bool bSenderMultipleIpUnknown
= false;
1713 CUpDownClient
* sender
= theApp
->uploadqueue
->GetWaitingClientByIP_UDP(destip
, destport
, true, &bSenderMultipleIpUnknown
);
1715 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILENOTFOUND to ") + m_client
->GetFullIP() );
1716 CPacket
* response
= new CPacket(OP_FILENOTFOUND
,0,OP_EMULEPROT
);
1717 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1719 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1721 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1727 //Make sure we are still thinking about the same file
1728 if (hash
== sender
->GetUploadFileID()) {
1729 sender
->AddAskedCount();
1730 sender
->SetLastUpRequest();
1731 //I messed up when I first added extended info to UDP
1732 //I should have originally used the entire ProcessExtenedInfo the first time.
1733 //So now I am forced to check UDPVersion to see if we are sending all the extended info.
1734 //For now on, we should not have to change anything here if we change
1735 //anything to the extended info data as this will be taken care of in ProcessExtendedInfo()
1736 //Update extended info.
1737 if (sender
->GetUDPVersion() > 3) {
1738 sender
->ProcessExtendedInfo(&data_in
, reqfile
);
1739 } else if (sender
->GetUDPVersion() > 2) {
1740 //Update our complete source counts.
1741 uint16 nCompleteCountLast
= sender
->GetUpCompleteSourcesCount();
1742 uint16 nCompleteCountNew
= data_in
.ReadUInt16();
1743 sender
->SetUpCompleteSourcesCount(nCompleteCountNew
);
1744 if (nCompleteCountLast
!= nCompleteCountNew
) {
1745 reqfile
->UpdatePartsInfo();
1749 CMemFile
data_out(128);
1750 if(sender
->GetUDPVersion() > 3) {
1751 if (reqfile
->IsPartFile()) {
1752 ((CPartFile
*)reqfile
)->WritePartStatus(&data_out
);
1754 data_out
.WriteUInt16(0);
1758 data_out
.WriteUInt16(sender
->GetUploadQueueWaitingPosition());
1759 CPacket
* response
= new CPacket(data_out
, OP_EMULEPROT
, OP_REASKACK
);
1760 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1761 AddDebugLogLineN( logLocalClient
, wxT("Local Client UDP: OP_REASKACK to ") + m_client
->GetFullIP() );
1762 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1764 AddDebugLogLineN(logListenSocket
, wxT("Client UDP socket; OP_REASKCALLBACKTCP; reqfile does not match"));
1767 if (!bSenderMultipleIpUnknown
){
1768 if ((theStats::GetWaitingUserCount() + 50) > thePrefs::GetQueueSize()) {
1769 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_QUEUEFULL to ") + m_client
->GetFullIP() );
1770 CPacket
* response
= new CPacket(OP_QUEUEFULL
,0,OP_EMULEPROT
);
1771 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1772 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1775 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
);
1780 case OP_CHATCAPTCHAREQ
:
1782 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHAREQ from ") + m_client
->GetFullIP());
1783 theStats::AddDownOverheadOther(size
);
1784 CMemFile
data_in(buffer
, size
);
1785 m_client
->ProcessCaptchaRequest(&data_in
);
1788 case OP_CHATCAPTCHARES
:
1790 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHARES from ") + m_client
->GetFullIP());
1791 theStats::AddDownOverheadOther(size
);
1793 m_client
->ProcessCaptchaReqRes(buffer
[0]);
1797 case OP_FWCHECKUDPREQ
: { // Support required for Kadversion >= 6
1798 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_FWCHECKUDPREQ from ") + m_client
->GetFullIP());
1799 theStats::AddDownOverheadOther(size
);
1800 CMemFile
data_in(buffer
, size
);
1801 m_client
->ProcessFirewallCheckUDPRequest(&data_in
);
1804 case OP_KAD_FWTCPCHECK_ACK
: { // Support required for Kadversion >= 7
1805 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_KAD_FWTCPCHECK_ACK from ") + m_client
->GetFullIP());
1806 if (theApp
->clientlist
->IsKadFirewallCheckIP(m_client
->GetIP())) {
1807 if (Kademlia::CKademlia::IsRunning()) {
1808 Kademlia::CKademlia::GetPrefs()->IncFirewalled();
1811 AddDebugLogLineN(logListenSocket
, wxT("Received unrequested OP_KAD_FWTCPCHECK_ACK packet from ") + m_client
->GetFullIP());
1816 theStats::AddDownOverheadOther(size
);
1817 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("eMule packet : unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1824 bool CClientTCPSocket::ProcessED2Kv2Packet(const byte
* buffer
, uint32 size
, uint8 opcode
)
1826 #ifdef __PACKET_RECV_DUMP__
1827 //printf("Rec: OPCODE %x ED2Kv2\n",opcode);
1828 DumpMem(buffer
,size
);
1832 throw wxString(wxT("Unknown clients sends extended ED2Kv2 protocol packet"));
1835 CMemFile
data(buffer
, size
);
1838 case OP_QUEUERANK
: {
1839 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_QUEUERANK from ") + m_client
->GetFullIP() );
1841 uint8 numtags
= data
.ReadUInt8();
1842 wxASSERT(numtags
== 1);
1843 if(numtags
){} // prevent GCC warning
1845 m_client
->SetRemoteQueueRank(data
.GetIntTagValue());
1847 theStats::AddDownOverheadFileRequest(size
);
1851 case OP_REQUESTPARTS
: {
1852 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
1854 m_client
->ProcessRequestPartsPacketv2(data
);
1856 theStats::AddDownOverheadFileRequest(size
);
1861 theStats::AddDownOverheadOther(size
);
1862 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("ED2Kv2 packet : unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1865 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("ED2Kv2 packet is corrupt at pos %i! opcode: %i %x from %s")) % data
.GetPosition() % opcode
% opcode
% m_client
->GetFullIP());
1872 void CClientTCPSocket::OnConnect(int nErrorCode
)
1875 OnError(nErrorCode
);
1876 } else if (!m_client
) {
1877 // and now? Disconnect? not?
1878 AddDebugLogLineN( logClient
, wxT("Couldn't send hello packet (Client deleted!)") );
1879 } else if (!m_client
->SendHelloPacket()) {
1880 // and now? Disconnect? not?
1881 AddDebugLogLineN( logClient
, wxT("Couldn't send hello packet (Client deleted by SendHelloPacket!)") );
1883 ResetTimeOutTimer();
1888 void CClientTCPSocket::OnSend(int nErrorCode
)
1890 ResetTimeOutTimer();
1891 CEMSocket::OnSend(nErrorCode
);
1895 void CClientTCPSocket::OnReceive(int nErrorCode
)
1897 ResetTimeOutTimer();
1898 // We might have updated ipfilter
1899 wxASSERT(m_remoteip
);
1901 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
1903 m_client
->Safe_Delete();
1906 AddDebugLogLineN( logIPFilter
, wxT("A connected client was dropped by IPFilter on new packet received"));
1908 CEMSocket::OnReceive(nErrorCode
);
1913 void CClientTCPSocket::OnError(int nErrorCode
)
1915 //printf("* Called OnError for %p\n",this);
1916 // 0.42e + Kry changes for handling of socket lost events
1919 if ((nErrorCode
== 0) || (nErrorCode
== 7) || (nErrorCode
== 0xFEFF)) {
1921 if (!m_client
->GetUserName().IsEmpty()) {
1922 strError
= wxT("Client '") + m_client
->GetUserName() + wxT("'");
1924 strError
= wxT("An unnamed client");
1926 strError
+= wxT(" (IP:") + m_client
->GetFullIP() + wxT(") ");
1928 strError
= wxT("A client ");
1930 if (nErrorCode
== 0) {
1931 strError
+= wxT("closed connection.");
1932 } else if (nErrorCode
== 0xFEFF) {
1933 strError
+= wxT(" caused a wxSOCKET_LOST event.");
1935 strError
+= wxT("caused a socket blocking error.");
1938 if (theLogger
.IsEnabled(logClient
) && nErrorCode
!= 107) {
1939 // 0 -> No Error / Disconect
1940 // 107 -> Transport endpoint is not connected
1942 if (!m_client
->GetUserName().IsEmpty()) {
1943 strError
= CFormat(wxT("OnError: Client '%s' (IP:%s) caused an error: %u. Disconnecting client!"))
1944 % m_client
->GetUserName() % m_client
->GetFullIP() % nErrorCode
;
1946 strError
= CFormat(wxT("OnError: Unknown client (IP:%s) caused an error: %u. Disconnecting client!"))
1947 % m_client
->GetFullIP() % nErrorCode
;
1950 strError
= CFormat(wxT("OnError: A client caused an error or did something bad (error %u). Disconnecting client !"))
1954 strError
= wxT("Error 107 (Transport endpoint is not connected)");
1958 Disconnect(strError
);
1962 bool CClientTCPSocket::PacketReceived(CPacket
* packet
)
1965 bool bResult
= false;
1966 uint32 uRawSize
= packet
->GetPacketSize();
1968 AddDebugLogLineN( logRemoteClient
,
1969 CFormat(wxT("Packet with protocol %x, opcode %x, size %u received from %s"))
1970 % packet
->GetProtocol()
1971 % packet
->GetOpCode()
1972 % packet
->GetPacketSize()
1973 % ( m_client
? m_client
->GetFullIP() : wxT("Unknown Client") )
1979 bool process
= true;
1981 if ((packet
->GetProtocol() == OP_PACKEDPROT
) ||
1982 (packet
->GetProtocol() == OP_ED2KV2PACKEDPROT
)) {
1984 if (!packet
->UnPackPacket()) {
1985 AddDebugLogLineN(logZLib
, wxT("Failed to decompress client TCP packet."));
1989 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Packet unpacked, new protocol %x, opcode %x, size %u"))
1990 % packet
->GetProtocol() % packet
->GetOpCode() % packet
->GetPacketSize());
1995 switch (packet
->GetProtocol()) {
1996 case OP_EDONKEYPROT
:
1997 bResult
= ProcessPacket(packet
->GetDataBuffer(),uRawSize
,packet
->GetOpCode());
2000 bResult
= ProcessExtPacket(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
2002 case OP_ED2KV2HEADER
:
2003 bResult
= ProcessED2Kv2Packet(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
2005 case OP_ED2KV2PACKEDPROT
:
2007 // Packed inside packed?
2011 theStats::AddDownOverheadOther(uRawSize
);
2013 m_client
->SetDownloadState(DS_ERROR
);
2015 Disconnect(wxT("Unknown protocol"));
2020 } catch (const CEOFException
& err
) {
2021 exception
= wxT("EOF exception: ") + err
.what();
2022 } catch (const CInvalidPacket
& err
) {
2023 exception
= wxT("InvalidPacket exception: ") + err
.what();
2024 } catch (const wxString
& error
) {
2025 exception
= wxT("error: ") + (error
.IsEmpty() ? wxString(wxT("Unknown error")) : error
);
2028 if (!exception
.IsEmpty()) {
2029 AddDebugLogLineN( logPacketErrors
,
2030 CFormat(wxT("Caught %s\nOn packet with protocol %x, opcode %x, size %u\tClientData: %s\n"))
2032 % packet
->GetProtocol()
2033 % packet
->GetOpCode()
2034 % packet
->GetPacketSize()
2035 % ( m_client
? m_client
->GetClientFullInfo() : wxT("Unknown") )
2039 m_client
->SetDownloadState(DS_ERROR
);
2042 AddDebugLogLineN( logClient
,
2043 CFormat( wxT("Client '%s' (IP: %s) caused an error (%s). Disconnecting client!" ) )
2044 % ( m_client
? m_client
->GetUserName() : wxString(wxT("Unknown")) )
2045 % ( m_client
? m_client
->GetFullIP() : wxString(wxT("Unknown")) )
2049 Disconnect(wxT("Caught exception on CClientTCPSocket::ProcessPacket\n"));
2056 SocketSentBytes
CClientTCPSocket::SendControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2058 SocketSentBytes returnStatus
= CEMSocket::SendControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2060 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2061 ResetTimeOutTimer();
2064 return returnStatus
;
2068 SocketSentBytes
CClientTCPSocket::SendFileAndControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2070 SocketSentBytes returnStatus
= CEMSocket::SendFileAndControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2072 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2073 ResetTimeOutTimer();
2076 return returnStatus
;
2080 void CClientTCPSocket::SendPacket(CPacket
* packet
, bool delpacket
, bool controlpacket
, uint32 actualPayloadSize
)
2082 ResetTimeOutTimer();
2083 CEMSocket::SendPacket(packet
,delpacket
,controlpacket
, actualPayloadSize
);
2085 // File_checked_for_headers