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
->IsDestroying()) {
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
->LastError());
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());
139 SetEventHandler(g_clientReqSocketHandler
, ID_CLIENTTCPSOCKET_EVENT
);
141 wxSOCKET_CONNECTION_FLAG
|
142 wxSOCKET_INPUT_FLAG
|
143 wxSOCKET_OUTPUT_FLAG
|
147 theApp
->listensocket
->AddSocket(this);
148 theApp
->listensocket
->AddConnection();
151 CClientTCPSocket::~CClientTCPSocket()
153 // remove event handler
158 m_client
->SetSocket( NULL
);
162 if (theApp
->listensocket
&& !theApp
->listensocket
->OnShutdown()) {
163 theApp
->listensocket
->RemoveSocket(this);
167 bool CClientTCPSocket::InitNetworkData()
169 wxASSERT(!m_remoteip
);
171 m_remoteip
= GetPeerInt();
173 MULE_CHECK(m_remoteip
, false);
175 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
176 AddDebugLogLineN(logClient
, wxT("Denied connection from ") + GetPeer() + wxT("(Filtered IP)"));
178 } else if (theApp
->clientlist
->IsBannedClient(m_remoteip
)) {
179 AddDebugLogLineN(logClient
, wxT("Denied connection from ") + GetPeer() + wxT("(Banned IP)"));
182 AddDebugLogLineN(logClient
, wxT("Accepted connection from ") + GetPeer());
187 void CClientTCPSocket::ResetTimeOutTimer()
189 timeout_timer
= ::GetTickCount();
193 bool CClientTCPSocket::CheckTimeOut()
196 uint32 uTimeout
= GetTimeOut();
199 if (m_client
->GetKadState() == KS_CONNECTED_BUDDY
) {
200 //We originally ignored the timeout here for buddies.
201 //This was a stupid idea on my part. There is now a ping/pong system
202 //for buddies. This ping/pong system now prevents timeouts.
203 //This release will allow lowID clients with KadVersion 0 to remain connected.
204 //But a soon future version needs to allow these older clients to time out to prevent dead connections from continuing.
205 //JOHNTODO: Don't forget to remove backward support in a future release.
206 if ( m_client
->GetKadVersion() == 0 ) {
210 uTimeout
+= MIN2MS(15);
213 if (m_client
->GetChatState() != MS_NONE
) {
214 uTimeout
+= CONNECTION_TIMEOUT
;
218 if (::GetTickCount() - timeout_timer
> uTimeout
){
219 timeout_timer
= ::GetTickCount();
220 Disconnect(wxT("Timeout"));
228 void CClientTCPSocket::SetClient(CUpDownClient
* pClient
)
232 m_client
->SetSocket( this );
237 void CClientTCPSocket::OnClose(int nErrorCode
)
240 wxASSERT(theApp
->listensocket
->IsValidSocket(this));
241 CEMSocket::OnClose(nErrorCode
);
243 Disconnect(CFormat(wxT("Closed: %u")) % nErrorCode
);
245 Disconnect(wxT("Close"));
250 void CClientTCPSocket::Disconnect(const wxString
& strReason
)
252 byConnected
= ES_DISCONNECTED
;
254 if (m_client
->Disconnected(strReason
, true)) {
255 // Somehow, Safe_Delete() is beeing called by Disconnected(),
256 // or any other function that sets m_client to NULL,
257 // so we must check m_client first.
259 m_client
->SetSocket( NULL
);
260 m_client
->Safe_Delete();
270 void CClientTCPSocket::Safe_Delete()
272 // More paranoia - make sure client is unlinked in any case
274 m_client
->SetSocket( NULL
);
278 // Destroy may be called several times
279 byConnected
= ES_DISCONNECTED
;
284 void CClientTCPSocket::Safe_Delete_Client()
287 m_client
->Safe_Delete();
293 bool CClientTCPSocket::ProcessPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
295 #ifdef __PACKET_RECV_DUMP__
296 //printf("Rec: OPCODE %x \n",opcode);
297 DumpMem(buffer
, size
);
299 if (!m_client
&& opcode
!= OP_HELLO
) {
300 throw wxString(wxT("Asks for something without saying hello"));
301 } else if (m_client
&& opcode
!= OP_HELLO
&& opcode
!= OP_HELLOANSWER
) {
302 m_client
->CheckHandshakeFinished();
306 case OP_HELLOANSWER
: { // 0.43b
307 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_HELLOANSWER from ") + m_client
->GetFullIP());
308 theStats::AddDownOverheadOther(size
);
309 m_client
->ProcessHelloAnswer(buffer
, size
);
311 // start secure identification, if
312 // - we have received OP_EMULEINFO and OP_HELLOANSWER (old eMule)
313 // - we have received eMule-OP_HELLOANSWER (new eMule)
314 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
315 m_client
->InfoPacketsReceived();
318 // Socket might die because of sending in InfoPacketsReceived, so check
320 m_client
->ConnectionEstablished();
323 // Socket might die on ConnectionEstablished somehow. Check it.
325 Notify_SharedCtrlRefreshClient( m_client
->ECID() , AVAILABLE_SOURCE
);
330 case OP_HELLO
: { // 0.43b
332 theStats::AddDownOverheadOther(size
);
333 bool bNewClient
= !m_client
;
335 // create new client to save standart informations
336 m_client
= new CUpDownClient(this);
340 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_HELLO from ") + m_client
->GetFullIP() );
342 bool bIsMuleHello
= false;
345 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
347 if (bNewClient
&& m_client
) {
348 // Don't let CUpDownClient::Disconnected be processed for a client which is not in the list of clients.
349 m_client
->Safe_Delete();
355 if (thePrefs::ParanoidFilter() && !IsLowID(m_client
->GetUserIDHybrid()) && (GetRemoteIP() != wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid()))) {
356 wxString reason
= wxT("Client claims a different IP from the one we received the hello packet from: ");
357 reason
+= Uint32toStringIP(wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid())) + wxT(" / ") + Uint32toStringIP(GetRemoteIP());
358 AddDebugLogLineN(logClient
, reason
);
360 m_client
->Safe_Delete();
363 Disconnect(wxT("Paranoid disconecting: ") + reason
);
367 // if IP is filtered, dont reply but disconnect...
368 if (theApp
->ipfilter
->IsFiltered(m_client
->GetIP())) {
370 m_client
->Safe_Delete();
373 Disconnect(wxT("IPFilter"));
379 // now we check if we know this client already. if yes this socket will
380 // be attached to the known client, the new client will be deleted
381 // and the var. "client" will point to the known client.
382 // if not we keep our new-constructed client ;)
383 if (theApp
->clientlist
->AttachToAlreadyKnown(&m_client
,this)) {
384 // update the old client informations
385 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
387 theApp
->clientlist
->AddClient(m_client
);
388 m_client
->SetCommentDirty();
390 Notify_SharedCtrlRefreshClient( m_client
->ECID(), AVAILABLE_SOURCE
);
391 // send a response packet with standart informations
392 if ((m_client
->GetHashType() == SO_EMULE
) && !bIsMuleHello
) {
393 m_client
->SendMuleInfoPacket(false);
396 // Client might die from Sending in SendMuleInfoPacket, so check
398 m_client
->SendHelloAnswer();
401 // Kry - If the other side supports it, send OS_INFO
402 // Client might die from Sending in SendHelloAnswer, so check
403 if (m_client
&& m_client
->GetOSInfoSupport()) {
404 m_client
->SendMuleInfoPacket(false,true); // Send the OS Info tag on the recycled Mule Info
407 // Client might die from Sending in SendMuleInfoPacket, so check
409 m_client
->ConnectionEstablished();
412 // start secure identification, if
413 // - we have received eMule-OP_HELLO (new eMule)
414 if (m_client
&& m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
415 m_client
->InfoPacketsReceived();
420 case OP_REQUESTFILENAME
: { // 0.43b
421 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTFILENAME from ") + m_client
->GetFullIP() );
423 theStats::AddDownOverheadFileRequest(size
);
424 // IP banned, no answer for this request
425 if (m_client
->IsBanned()) {
429 if (!m_client
->GetWaitStartTime()) {
430 m_client
->SetWaitStartTime();
432 CMemFile
data_in(buffer
, size
);
433 CMD4Hash reqfilehash
= data_in
.ReadHash();
434 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
435 if ( reqfile
== NULL
) {
436 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
437 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
441 // if we are downloading this file, this could be a new source
442 // no passive adding of files with only one part
443 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
444 if (thePrefs::GetMaxSourcePerFile() > static_cast<CPartFile
*>(reqfile
)->GetSourceCount()) {
445 theApp
->downloadqueue
->CheckAndAddKnownSource(static_cast<CPartFile
*>(reqfile
), m_client
);
449 // check to see if this is a new file they are asking for
450 if (m_client
->GetUploadFileID() != reqfilehash
) {
451 m_client
->SetCommentDirty();
454 m_client
->SetUploadFileID(reqfile
);
455 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
458 CMemFile
data_out(128);
459 data_out
.WriteHash(reqfile
->GetFileHash());
461 // Since it's for somebody else to see, we need to send the prettified
462 // filename, rather than the (possibly) mangled actual filename.
463 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
465 CPacket
* packet
= new CPacket(data_out
, OP_EDONKEYPROT
, OP_REQFILENAMEANSWER
);
466 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
467 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_REQFILENAMEANSWER to ") + m_client
->GetFullIP() );
468 SendPacket(packet
,true);
470 // SendPacket might kill the socket, so check
472 m_client
->SendCommentInfo(reqfile
);
476 throw wxString(wxT("Invalid OP_REQUESTFILENAME packet size"));
479 case OP_SETREQFILEID
: { // 0.43b EXCEPT track of bad clients
480 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SETREQFILEID from ") + m_client
->GetFullIP() );
482 theStats::AddDownOverheadFileRequest(size
);
484 if (m_client
->IsBanned()) {
490 if (!m_client
->GetWaitStartTime()) {
491 m_client
->SetWaitStartTime();
494 const CMD4Hash
fileID(buffer
);
495 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
496 if ( reqfile
== NULL
) {
497 reqfile
= theApp
->downloadqueue
->GetFileByID(fileID
);
498 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
499 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
500 replypacket
->Copy16ToDataBuffer(fileID
.GetHash());
501 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
502 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILERE to ") + m_client
->GetFullIP() );
503 SendPacket(replypacket
, true);
508 // check to see if this is a new file they are asking for
509 if (m_client
->GetUploadFileID() != fileID
) {
510 m_client
->SetCommentDirty();
513 m_client
->SetUploadFileID(reqfile
);
515 CMemFile
data(16+16);
516 data
.WriteHash(reqfile
->GetFileHash());
517 if (reqfile
->IsPartFile()) {
518 static_cast<CPartFile
*>(reqfile
)->WritePartStatus(&data
);
522 CPacket
* packet
= new CPacket(data
, OP_EDONKEYPROT
, OP_FILESTATUS
);
523 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
524 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILESTATUS to ") + m_client
->GetFullIP() );
525 SendPacket(packet
, true);
528 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
533 case OP_FILEREQANSNOFIL
: { // 0.43b protocol, lacks ZZ's download manager on swap
534 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILEREQANSNOFIL from ") + m_client
->GetFullIP() );
536 theStats::AddDownOverheadFileRequest(size
);
538 // if that client does not have my file maybe has another different
539 CPartFile
* reqfile
= theApp
->downloadqueue
->GetFileByID(CMD4Hash(buffer
));
541 reqfile
->AddDeadSource( m_client
);
546 // we try to swap to another file ignoring no needed parts files
547 switch (m_client
->GetDownloadState()) {
550 case DS_NONEEDEDPARTS
:
551 if (!m_client
->SwapToAnotherFile(true, true, true, NULL
)) {
552 theApp
->downloadqueue
->RemoveSource(m_client
);
558 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
562 case OP_REQFILENAMEANSWER
: { // 0.43b except check for bad clients
563 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQFILENAMEANSWER from ") + m_client
->GetFullIP() );
565 theStats::AddDownOverheadFileRequest(size
);
566 CMemFile
data(buffer
, size
);
567 CMD4Hash hash
= data
.ReadHash();
568 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
569 m_client
->ProcessFileInfo(&data
, file
);
573 case OP_FILESTATUS
: { // 0.43b except check for bad clients
574 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILESTATUS from ") + m_client
->GetFullIP() );
576 theStats::AddDownOverheadFileRequest(size
);
577 CMemFile
data(buffer
, size
);
578 CMD4Hash hash
= data
.ReadHash();
579 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
580 m_client
->ProcessFileStatus(false, &data
, file
);
584 case OP_STARTUPLOADREQ
: {
585 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_STARTUPLOADREQ from ") + m_client
->GetFullIP() );
587 theStats::AddDownOverheadFileRequest(size
);
589 if (!m_client
->CheckHandshakeFinished()) {
593 m_client
->CheckForAggressive();
594 if ( m_client
->IsBanned() ) {
599 const CMD4Hash
fileID(buffer
);
600 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
602 if (m_client
->GetUploadFileID() != fileID
) {
603 m_client
->SetCommentDirty();
605 m_client
->SetUploadFileID(reqfile
);
606 m_client
->SendCommentInfo(reqfile
);
608 // Socket might die because of SendCommentInfo, so check
610 theApp
->uploadqueue
->AddClientToQueue(m_client
);
616 case OP_QUEUERANK
: { // 0.43b
617 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_QUEUERANK from ") + m_client
->GetFullIP() );
619 theStats::AddDownOverheadFileRequest(size
);
620 CMemFile
data(buffer
, size
);
621 uint32 rank
= data
.ReadUInt32();
623 m_client
->SetRemoteQueueRank(rank
);
627 case OP_ACCEPTUPLOADREQ
: { // 0.42e (xcept khaos stats)
628 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ACCEPTUPLOADREQ from ") + m_client
->GetFullIP() );
630 theStats::AddDownOverheadFileRequest(size
);
631 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
632 if (m_client
->GetDownloadState() == DS_ONQUEUE
) {
633 m_client
->SetDownloadState(DS_DOWNLOADING
);
634 m_client
->SetLastPartAsked(0xffff); // Reset current downloaded Chunk // Maella -Enhanced Chunk Selection- (based on jicxicmic)
635 m_client
->SendBlockRequests();
638 if (!m_client
->GetSentCancelTransfer()) {
639 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
640 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
641 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
642 m_client
->SendPacket(packet
,true,true);
644 // SendPacket can cause the socket to die, so check
646 m_client
->SetSentCancelTransfer(1);
650 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
655 case OP_REQUESTPARTS
: { // 0.43b
656 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
658 theStats::AddDownOverheadFileRequest(size
);
660 m_client
->ProcessRequestPartsPacket(buffer
, size
, false);
665 case OP_CANCELTRANSFER
: { // 0.43b
666 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CANCELTRANSFER from ") + m_client
->GetFullIP() );
668 theStats::AddDownOverheadFileRequest(size
);
669 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
670 AddDebugLogLineN( logClient
, m_client
->GetUserName() + wxT(": Upload session ended due canceled transfer."));
674 case OP_END_OF_DOWNLOAD
: { // 0.43b except check for bad clients
675 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_END_OF_DOWNLOAD from ") + m_client
->GetFullIP() );
677 theStats::AddDownOverheadFileRequest(size
);
678 if (size
>=16 && m_client
->GetUploadFileID() == CMD4Hash(buffer
)) {
679 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
680 AddDebugLogLineN( logClient
, m_client
->GetUserName() + wxT(": Upload session ended due ended transfer."));
685 case OP_HASHSETREQUEST
: { // 0.43b except check for bad clients
686 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_HASHSETREQUEST from ") + m_client
->GetFullIP() );
689 theStats::AddDownOverheadFileRequest(size
);
691 throw wxString(wxT("Invalid OP_HASHSETREQUEST packet size"));
693 m_client
->SendHashsetPacket(CMD4Hash(buffer
));
697 case OP_HASHSETANSWER
: { // 0.43b
698 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_HASHSETANSWER from ") + m_client
->GetFullIP() );
700 theStats::AddDownOverheadFileRequest(size
);
701 m_client
->ProcessHashSet(buffer
, size
);
705 case OP_SENDINGPART
: { // 0.47a
706 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SENDINGPART from ") + m_client
->GetFullIP() );
708 if ( m_client
->GetRequestFile() &&
709 !m_client
->GetRequestFile()->IsStopped() &&
710 (m_client
->GetRequestFile()->GetStatus() == PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
712 m_client
->ProcessBlockPacket(buffer
, size
, false, false);
715 ( m_client
->GetRequestFile()->IsStopped() ||
716 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
717 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
) ) {
718 if (!m_client
->GetSentCancelTransfer()) {
719 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
720 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
721 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
722 m_client
->SendPacket(packet
,true,true);
724 // Socket might die because of SendPacket, so check
726 m_client
->SetSentCancelTransfer(1);
730 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
733 if (!m_client
->GetSentCancelTransfer()) {
734 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
735 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
736 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
737 m_client
->SendPacket(packet
,true,true);
739 // Socket might die because of SendPacket, so check
740 m_client
->SetSentCancelTransfer(1);
742 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
747 case OP_OUTOFPARTREQS
: { // 0.43b
748 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_OUTOFPARTREQS from ") + m_client
->GetFullIP() );
750 theStats::AddDownOverheadFileRequest(size
);
751 if (m_client
->GetDownloadState() == DS_DOWNLOADING
) {
752 m_client
->SetDownloadState(DS_ONQUEUE
);
757 case OP_CHANGE_CLIENT_ID
: { // Kad reviewed
758 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CHANGE_CLIENT_ID from ") + m_client
->GetFullIP() );
760 theStats::AddDownOverheadOther(size
);
761 CMemFile
data(buffer
, size
);
762 uint32 nNewUserID
= data
.ReadUInt32();
763 uint32 nNewServerIP
= data
.ReadUInt32();
765 if (IsLowID(nNewUserID
)) { // client changed server and gots a LowID
766 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
767 if (pNewServer
!= NULL
){
768 m_client
->SetUserIDHybrid(nNewUserID
); // update UserID only if we know the server
769 m_client
->SetServerIP(nNewServerIP
);
770 m_client
->SetServerPort(pNewServer
->GetPort());
772 } else if (nNewUserID
== m_client
->GetIP()) { // client changed server and gots a HighID(IP)
773 m_client
->SetUserIDHybrid(wxUINT32_SWAP_ALWAYS(nNewUserID
));
774 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
775 if (pNewServer
!= NULL
){
776 m_client
->SetServerIP(nNewServerIP
);
777 m_client
->SetServerPort(pNewServer
->GetPort());
784 case OP_CHANGE_SLOT
:{ // 0.43b
785 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CHANGE_SLOT from ") + m_client
->GetFullIP() );
787 // sometimes sent by Hybrid
788 theStats::AddDownOverheadOther(size
);
792 case OP_MESSAGE
: { // 0.43b
793 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MESSAGE from ") + m_client
->GetFullIP() );
795 theStats::AddDownOverheadOther(size
);
798 throw wxString(wxT("invalid message packet"));
800 CMemFile
message_file(buffer
, size
);
801 uint16 length
= message_file
.ReadUInt16();
802 if (length
+ 2u != size
) {
803 throw wxString(wxT("invalid message packet"));
806 // limit message length
807 static const uint16 MAX_CLIENT_MSG_LEN
= 450;
809 if (length
> MAX_CLIENT_MSG_LEN
) {
810 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Message from '%s' (IP:%s) exceeds limit by %u chars, truncated."))
811 % m_client
->GetUserName() % m_client
->GetFullIP() % (length
- MAX_CLIENT_MSG_LEN
));
812 length
= MAX_CLIENT_MSG_LEN
;
815 wxString message
= message_file
.ReadOnlyString((m_client
->GetUnicodeSupport() != utf8strNone
), length
);
816 m_client
->ProcessChatMessage(message
);
821 case OP_ASKSHAREDFILES
: { // 0.43b (well, er, it does the same, but in our own way)
822 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILES from ") + m_client
->GetFullIP() );
824 // client wants to know what we have in share, let's see if we allow him to know that
825 theStats::AddDownOverheadOther(size
);
826 // IP banned, no answer for this request
827 if (m_client
->IsBanned()) {
831 if (thePrefs::CanSeeShares() == vsfaEverybody
|| (thePrefs::CanSeeShares() == vsfaFriends
&& m_client
->IsFriend())) {
832 AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Accepted"))
833 % m_client
->GetUserName()
834 % m_client
->GetUserIDHybrid() );
836 std::vector
<CKnownFile
*> list
;
837 theApp
->sharedfiles
->CopyFileList(list
);
839 CMemFile
tempfile(80);
840 tempfile
.WriteUInt32(list
.size());
841 for (unsigned i
= 0; i
< list
.size(); ++i
) {
842 if (!list
[i
]->IsLargeFile() || m_client
->SupportsLargeFiles()) {
843 list
[i
]->CreateOfferedFilePacket(&tempfile
, NULL
, m_client
);
847 // create a packet and send it
848 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESANSWER
);
849 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESANSWER to ") + m_client
->GetFullIP() );
850 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
851 SendPacket(replypacket
, true, true);
853 AddLogLineC(CFormat( _("User %s (%u) requested your sharedfiles-list -> Denied"))
854 % m_client
->GetUserName()
855 % m_client
->GetUserIDHybrid() );
857 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
858 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
859 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
860 SendPacket(replypacket
, true, true);
866 case OP_ASKSHAREDFILESANSWER
: { // 0.43b
867 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESANSWER from ") + m_client
->GetFullIP() );
869 theStats::AddDownOverheadOther(size
);
871 m_client
->ProcessSharedFileList(buffer
, size
, EmptyStr
);
875 case OP_ASKSHAREDDIRS
: { // 0.43b
876 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRS from ") + m_client
->GetFullIP() );
878 theStats::AddDownOverheadOther(size
);
879 wxASSERT( size
== 0 );
880 // IP banned, no answer for this request
881 if (m_client
->IsBanned()) {
884 if ((thePrefs::CanSeeShares()==vsfaEverybody
) || ((thePrefs::CanSeeShares()==vsfaFriends
) && m_client
->IsFriend())) {
885 AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Accepted") )
886 % m_client
->GetUserName()
887 % m_client
->GetUserIDHybrid() );
888 // send the list of shared directories
889 m_client
->SendSharedDirectories();
891 AddLogLineC(CFormat( _("User %s (%u) requested your shareddirectories-list -> Denied") )
892 % m_client
->GetUserName()
893 % m_client
->GetUserIDHybrid() );
895 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
896 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
897 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
898 SendPacket(replypacket
, true, true);
904 case OP_ASKSHAREDFILESDIR
: { // 0.43b
905 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIR from ") + m_client
->GetFullIP() );
907 theStats::AddDownOverheadOther(size
);
908 // IP banned, no answer for this request
909 if (m_client
->IsBanned()) {
912 CMemFile
data(buffer
, size
);
914 wxString strReqDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
915 if (thePrefs::CanSeeShares()==vsfaEverybody
|| (thePrefs::CanSeeShares()==vsfaFriends
&& m_client
->IsFriend())) {
916 AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> accepted")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
917 wxASSERT( data
.GetPosition() == data
.GetLength() );
918 // send the list of shared files for the requested directory
919 m_client
->SendSharedFilesOfDirectory(strReqDir
);
921 AddLogLineC(CFormat(_("User %s (%u) requested your sharedfiles-list for directory '%s' -> denied")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
923 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
924 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
925 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
926 SendPacket(replypacket
, true, true);
931 case OP_ASKSHAREDDIRSANS
:{ // 0.43b
932 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRSANS from ") + m_client
->GetFullIP() );
934 theStats::AddDownOverheadOther(size
);
935 if (m_client
->GetFileListRequested() == 1){
936 CMemFile
data(buffer
, size
);
937 uint32 uDirs
= data
.ReadUInt32();
938 for (uint32 i
= 0; i
< uDirs
; i
++){
939 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
940 AddLogLineC(CFormat( _("User %s (%u) shares directory '%s'") )
941 % m_client
->GetUserName()
942 % m_client
->GetUserIDHybrid()
945 CMemFile
tempfile(80);
946 tempfile
.WriteString(strDir
, m_client
->GetUnicodeSupport());
947 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESDIR
);
948 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
949 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESDIR to ") + m_client
->GetFullIP() );
950 SendPacket(replypacket
, true, true);
952 wxASSERT( data
.GetPosition() == data
.GetLength() );
953 m_client
->SetFileListRequested(uDirs
);
955 AddLogLineC(CFormat( _("User %s (%u) sent unrequested shared dirs.") )
956 % m_client
->GetUserName()
957 % m_client
->GetUserIDHybrid() );
962 case OP_ASKSHAREDFILESDIRANS
: { // 0.43b
963 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIRANS from ") + m_client
->GetFullIP() );
965 theStats::AddDownOverheadOther(size
);
966 CMemFile
data(buffer
, size
);
967 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
969 if (m_client
->GetFileListRequested() > 0){
970 AddLogLineC(CFormat( _("User %s (%u) sent sharedfiles-list for directory '%s'") )
971 % m_client
->GetUserName()
972 % m_client
->GetUserIDHybrid()
975 m_client
->ProcessSharedFileList(buffer
+ data
.GetPosition(), size
- data
.GetPosition(), strDir
);
976 if (m_client
->GetFileListRequested() == 0) {
977 AddLogLineC(CFormat( _("User %s (%u) finished sending sharedfiles-list") )
978 % m_client
->GetUserName()
979 % m_client
->GetUserIDHybrid() );
982 AddLogLineC(CFormat( _("User %s (%u) sent unwanted sharedfiles-list") )
983 % m_client
->GetUserName()
984 % m_client
->GetUserIDHybrid() );
989 case OP_ASKSHAREDDENIEDANS
:
990 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDENIEDANS from ") + m_client
->GetFullIP() );
992 theStats::AddDownOverheadOther(size
);
993 wxASSERT( size
== 0 );
994 AddLogLineC(CFormat( _("User %s (%u) denied access to shared directories/files list") )
995 % m_client
->GetUserName()
996 % m_client
->GetUserIDHybrid() );
998 m_client
->SetFileListRequested(0);
1002 theStats::AddDownOverheadOther(size
);
1003 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Edonkey packet: unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1011 bool CClientTCPSocket::ProcessExtPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
1013 #ifdef __PACKET_RECV_DUMP__
1014 //printf("Rec: OPCODE %x \n",opcode);
1015 DumpMem(buffer
,size
);
1018 // 0.42e - except the catchs on mem exception and file exception
1020 throw wxString(wxT("Unknown clients sends extended protocol packet"));
1023 if (!client->CheckHandshakeFinished()) {
1024 // Here comes an extended packet without finishing the handshake.
1025 // IMHO, we should disconnect the client.
1026 throw wxString(wxT("Client send extended packet before finishing handshake"));
1030 case OP_MULTIPACKET_EXT
:
1031 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET_EXT from ") + m_client
->GetFullIP());
1032 case OP_MULTIPACKET
: {
1033 if (opcode
== OP_MULTIPACKET
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET from ") + m_client
->GetFullIP() );
1035 theStats::AddDownOverheadFileRequest(size
);
1037 if (m_client
->IsBanned()) {
1041 if (!m_client
->CheckHandshakeFinished()) {
1042 // Here comes an extended packet without finishing the handshake.
1043 // IMHO, we should disconnect the client.
1044 throw wxString(wxT("Client send OP_MULTIPACKET before finishing handshake"));
1047 CMemFile
data_in(buffer
, size
);
1048 CMD4Hash reqfilehash
= data_in
.ReadHash();
1049 uint64 nSize
= (opcode
== OP_MULTIPACKET_EXT
) ? data_in
.ReadUInt64() : 0;
1051 bool file_not_found
= false;
1052 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
1053 if ( reqfile
== NULL
){
1054 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1055 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
1056 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a non-shared file"));
1057 file_not_found
= true;
1061 if (!file_not_found
&& reqfile
->IsLargeFile() && !m_client
->SupportsLargeFiles()) {
1062 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a large file but doesn't support them"));
1063 file_not_found
= true;
1066 if (!file_not_found
&& nSize
&& (reqfile
->GetFileSize() != nSize
)) {
1067 AddDebugLogLineN(logRemoteClient
, wxT("Remote client asked for a file but specified wrong size"));
1068 file_not_found
= true;
1071 if (file_not_found
) {
1072 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
1073 replypacket
->Copy16ToDataBuffer(reqfilehash
.GetHash());
1074 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
1075 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILEREQANSNOFIL to ") + m_client
->GetFullIP() );
1076 SendPacket(replypacket
, true);
1080 if (!m_client
->GetWaitStartTime()) {
1081 m_client
->SetWaitStartTime();
1083 // if we are downloading this file, this could be a new source
1084 // no passive adding of files with only one part
1085 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
1086 if (thePrefs::GetMaxSourcePerFile() > static_cast<CPartFile
*>(reqfile
)->GetSourceCount()) {
1087 theApp
->downloadqueue
->CheckAndAddKnownSource(static_cast<CPartFile
*>(reqfile
), m_client
);
1090 // check to see if this is a new file they are asking for
1091 if (m_client
->GetUploadFileID() != reqfilehash
) {
1092 m_client
->SetCommentDirty();
1094 m_client
->SetUploadFileID(reqfile
);
1095 CMemFile
data_out(128);
1096 data_out
.WriteHash(reqfile
->GetFileHash());
1097 while(data_in
.GetLength()-data_in
.GetPosition()) {
1099 throw wxString(wxT("Client suddenly disconnected"));
1101 uint8 opcode_in
= data_in
.ReadUInt8();
1103 case OP_REQUESTFILENAME
: {
1104 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTFILENAME") );
1105 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
1106 data_out
.WriteUInt8(OP_REQFILENAMEANSWER
);
1108 // Since it's for somebody else to see, we need to send the prettified
1109 // filename, rather than the (possibly) mangled actual filename
1110 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
1113 case OP_AICHFILEHASHREQ
: {
1114 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_AICHFILEHASHANS") );
1115 if (m_client
->IsSupportingAICH() && reqfile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1116 && reqfile
->GetAICHHashset()->HasValidMasterHash())
1118 data_out
.WriteUInt8(OP_AICHFILEHASHANS
);
1119 reqfile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1123 case OP_SETREQFILEID
: {
1124 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_SETREQFILEID") );
1125 data_out
.WriteUInt8(OP_FILESTATUS
);
1126 if (reqfile
->IsPartFile()) {
1127 static_cast<CPartFile
*>(reqfile
)->WritePartStatus(&data_out
);
1129 data_out
.WriteUInt16(0);
1133 //We still send the source packet separately..
1134 //We could send it within this packet.. If agreeded, I will fix it..
1135 case OP_REQUESTSOURCES2
:
1136 case OP_REQUESTSOURCES
: {
1137 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTSOURCES(2)") );
1138 uint8 byRequestedVersion
= 0;
1139 uint16 byRequestedOptions
= 0;
1140 if (opcode_in
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1141 byRequestedVersion
= data_in
.ReadUInt8();
1142 byRequestedOptions
= data_in
.ReadUInt16();
1145 //Although this shouldn't happen, it's a just in case to any Mods that mess with version numbers.
1147 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() > 1) {
1148 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1149 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1151 //if not complete and file is rare
1152 ( reqfile
->IsPartFile()
1153 && (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1154 && static_cast<CPartFile
*>(reqfile
)->GetSourceCount() <= RARE_FILE
1156 //OR if file is not rare or if file is complete
1157 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1160 m_client
->SetLastSrcReqTime();
1161 CPacket
* tosend
= reqfile
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1163 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1164 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1165 SendPacket(tosend
, true);
1174 if( data_out
.GetLength() > 16 ) {
1175 CPacket
* reply
= new CPacket(data_out
, OP_EMULEPROT
, OP_MULTIPACKETANSWER
);
1176 theStats::AddUpOverheadFileRequest(reply
->GetPacketSize());
1177 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_MULTIPACKETANSWER to ") + m_client
->GetFullIP() );
1178 SendPacket(reply
, true);
1183 case OP_MULTIPACKETANSWER
: { // 0.43b
1184 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_MULTIPACKETANSWER from ") + m_client
->GetFullIP() );
1186 theStats::AddDownOverheadFileRequest(size
);
1188 if (m_client
->IsBanned()) {
1192 if (m_client
->GetKadPort() && m_client
->GetKadVersion() > 1) {
1193 Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(m_client
->GetIP()), m_client
->GetKadPort());
1196 if (!m_client
->CheckHandshakeFinished()) {
1197 // Here comes an extended packet without finishing the handshake.
1198 // IMHO, we should disconnect the client.
1199 throw wxString(wxT("Client send OP_MULTIPACKETANSWER before finishing handshake"));
1202 CMemFile
data_in(buffer
, size
);
1203 CMD4Hash reqfilehash
= data_in
.ReadHash();
1204 const CPartFile
*reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1205 //Make sure we are downloading this file.
1207 throw wxString(wxT(" Wrong File ID: (OP_MULTIPACKETANSWER; reqfile==NULL)"));
1209 if ( !m_client
->GetRequestFile() ) {
1211 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; client->reqfile==NULL)"));
1213 if (reqfile
!= m_client
->GetRequestFile()) {
1214 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; reqfile!=client->reqfile)"));
1216 while (data_in
.GetLength()-data_in
.GetPosition()) {
1217 // Some of the cases down there can actually send a packet and lose the client
1219 throw wxString(wxT("Client suddenly disconnected"));
1221 uint8 opcode_in
= data_in
.ReadUInt8();
1223 case OP_REQFILENAMEANSWER
: {
1225 throw wxString(wxT("Client suddenly disconnected"));
1227 m_client
->ProcessFileInfo(&data_in
, reqfile
);
1231 case OP_FILESTATUS
: {
1233 throw wxString(wxT("Client suddenly disconnected"));
1235 m_client
->ProcessFileStatus(false, &data_in
, reqfile
);
1239 case OP_AICHFILEHASHANS
: {
1241 throw wxString(wxT("Client suddenly disconnected"));
1243 m_client
->ProcessAICHFileHash(&data_in
, reqfile
);
1253 case OP_EMULEINFO
: { // 0.43b
1254 theStats::AddDownOverheadOther(size
);
1256 if (!m_client
->ProcessMuleInfoPacket(buffer
, size
)) {
1257 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFO from ") + m_client
->GetFullIP() );
1259 // If it's not a OS Info packet, is an old client
1260 // start secure identification, if
1261 // - we have received eD2K and eMule info (old eMule)
1262 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1263 m_client
->InfoPacketsReceived();
1265 m_client
->SendMuleInfoPacket(true);
1267 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFO is an OS_INFO") );
1271 case OP_EMULEINFOANSWER
: { // 0.43b
1272 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_EMULEINFOANSWER from ") + m_client
->GetFullIP() );
1273 theStats::AddDownOverheadOther(size
);
1275 m_client
->ProcessMuleInfoPacket(buffer
, size
);
1276 // start secure identification, if
1277 // - we have received eD2K and eMule info (old eMule)
1279 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1280 m_client
->InfoPacketsReceived();
1286 case OP_SECIDENTSTATE
:{ // 0.43b
1287 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SECIDENTSTATE from ") + m_client
->GetFullIP() );
1289 if (!m_client
->CheckHandshakeFinished()) {
1290 // Here comes an extended packet without finishing the handshake.
1291 // IMHO, we should disconnect the client.
1292 throw wxString(wxT("Client send OP_SECIDENTSTATE before finishing handshake"));
1294 m_client
->ProcessSecIdentStatePacket(buffer
, size
);
1295 // ProcessSecIdentStatePacket() might cause the socket to die, so check
1297 int SecureIdentState
= m_client
->GetSecureIdentState();
1298 if (SecureIdentState
== IS_SIGNATURENEEDED
) {
1299 m_client
->SendSignaturePacket();
1300 } else if (SecureIdentState
== IS_KEYANDSIGNEEDED
) {
1301 m_client
->SendPublicKeyPacket();
1302 // SendPublicKeyPacket() might cause the socket to die, so check
1304 m_client
->SendSignaturePacket();
1311 case OP_PUBLICKEY
: { // 0.43b
1312 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICKEY from ") + m_client
->GetFullIP() );
1314 if (m_client
->IsBanned() ){
1318 if (!m_client
->CheckHandshakeFinished()) {
1319 // Here comes an extended packet without finishing the handshake.
1320 // IMHO, we should disconnect the client.
1321 throw wxString(wxT("Client send OP_PUBLICKEY before finishing handshake"));
1324 m_client
->ProcessPublicKeyPacket(buffer
, size
);
1327 case OP_SIGNATURE
:{ // 0.43b
1328 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SIGNATURE from ") + m_client
->GetFullIP() );
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_COMPRESSEDPART before finishing handshake"));
1336 m_client
->ProcessSignaturePacket(buffer
, size
);
1339 case OP_SENDINGPART_I64
:
1340 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_SENDINGPART_I64 from ") + m_client
->GetFullIP() );
1341 case OP_COMPRESSEDPART_I64
:
1342 if (opcode
== OP_COMPRESSEDPART_I64
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART_I64 from ") + m_client
->GetFullIP() );
1343 case OP_COMPRESSEDPART
: { // 0.47a
1344 if (opcode
== OP_COMPRESSEDPART
) AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART from ") + m_client
->GetFullIP() );
1346 if (!m_client
->CheckHandshakeFinished()) {
1347 // Here comes an extended packet without finishing the handshake.
1348 // IMHO, we should disconnect the client.
1349 throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1352 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
1354 m_client
->ProcessBlockPacket(buffer
, size
, (opcode
!= OP_SENDINGPART_I64
), (opcode
== OP_COMPRESSEDPART_I64
) || (opcode
== OP_SENDINGPART_I64
));
1357 m_client
->GetRequestFile()->IsStopped() ||
1358 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
1359 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
)) {
1360 if (!m_client
->GetSentCancelTransfer()) {
1361 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1362 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1363 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1364 m_client
->SendPacket(packet
,true,true);
1367 m_client
->SetSentCancelTransfer(1);
1372 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
1376 if (!m_client
->GetSentCancelTransfer()) {
1377 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1378 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1379 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1380 m_client
->SendPacket(packet
,true,true);
1383 m_client
->SetSentCancelTransfer(1);
1388 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
1393 case OP_REQUESTPARTS_I64
: {
1394 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS_I64 from ") + m_client
->GetFullIP() );
1396 theStats::AddDownOverheadFileRequest(size
);
1398 m_client
->ProcessRequestPartsPacket(buffer
, size
, true);
1402 case OP_QUEUERANKING
: { // 0.43b
1403 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_QUEUERANKING from ") + m_client
->GetFullIP() );
1405 theStats::AddDownOverheadOther(size
);
1407 if (!m_client
->CheckHandshakeFinished()) {
1408 // Here comes an extended packet without finishing the handshake.
1409 // IMHO, we should disconnect the client.
1410 throw wxString(wxT("Client send OP_QUEUERANKING before finishing handshake"));
1414 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1417 uint16 newrank
= PeekUInt16(buffer
);
1418 m_client
->SetRemoteQueueFull(false);
1419 m_client
->SetRemoteQueueRank(newrank
);
1422 case OP_REQUESTSOURCES2
:
1423 case OP_REQUESTSOURCES
:{
1424 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTSOURCES from ") + m_client
->GetFullIP() );
1426 theStats::AddDownOverheadSourceExchange(size
);
1428 if (!m_client
->CheckHandshakeFinished()) {
1429 // Here comes an extended packet without finishing the handshake.
1430 // IMHO, we should disconnect the client.
1431 throw wxString(wxT("Client send OP_REQUESTSOURCES before finishing handshake"));
1434 uint8 byRequestedVersion
= 0;
1435 uint16 byRequestedOptions
= 0;
1436 CMemFile
data_in(buffer
, size
);
1437 if (opcode
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1438 byRequestedVersion
= data_in
.ReadUInt8();
1439 byRequestedOptions
= data_in
.ReadUInt16();
1442 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() >= 1) {
1444 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1446 //first check shared file list, then download list
1447 const CMD4Hash
fileID(buffer
);
1448 CKnownFile
* file
= theApp
->sharedfiles
->GetFileByID(fileID
);
1450 file
= theApp
->downloadqueue
->GetFileByID(fileID
);
1453 // There are some clients which do not follow the correct protocol procedure of sending
1454 // the sequence OP_REQUESTFILENAME, OP_SETREQFILEID, OP_REQUESTSOURCES. If those clients
1455 // are doing this, they will not get the optimal set of sources which we could offer if
1456 // they would follow the above noted protocol sequence. They better do it the right way
1457 // or they will get just a random set of sources because we do not know their download
1458 // part status which may get cleared with the call of 'SetUploadFileID'.
1459 m_client
->SetUploadFileID(file
);
1461 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1462 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1464 //if not complete and file is rare, allow once every 40 minutes
1465 ( file
->IsPartFile() &&
1466 static_cast<CPartFile
*>(file
)->GetSourceCount() <= RARE_FILE
&&
1467 (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1469 //OR if file is not rare or if file is complete, allow every 90 minutes
1470 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1473 m_client
->SetLastSrcReqTime();
1474 CPacket
* tosend
= file
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1476 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1477 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1478 SendPacket(tosend
, true, true);
1485 case OP_ANSWERSOURCES
: {
1486 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_ANSWERSOURCES from ") + m_client
->GetFullIP() );
1488 theStats::AddDownOverheadSourceExchange(size
);
1490 if (!m_client
->CheckHandshakeFinished()) {
1491 // Here comes an extended packet without finishing the handshake.
1492 // IMHO, we should disconnect the client.
1493 throw wxString(wxT("Client send OP_ANSWERSOURCES before finishing handshake"));
1496 CMemFile
data(buffer
, size
);
1497 CMD4Hash hash
= data
.ReadHash();
1498 CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1500 if (file
->IsPartFile()){
1501 //set the client's answer time
1502 m_client
->SetLastSrcAnswerTime();
1503 //and set the file's last answer time
1504 static_cast<CPartFile
*>(file
)->SetLastAnsweredTime();
1505 static_cast<CPartFile
*>(file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, m_client
->GetSourceExchange1Version(), false, m_client
);
1510 case OP_ANSWERSOURCES2
: {
1511 //printf("Received OP_ANSWERSOURCES2\n");
1512 theStats::AddDownOverheadSourceExchange(size
);
1514 if (!m_client
->CheckHandshakeFinished()) {
1515 // Here comes an extended packet without finishing the handshake.
1516 // IMHO, we should disconnect the client.
1517 throw wxString(wxT("Client send OP_ANSWERSOURCES2 before finishing handshake"));
1520 CMemFile
data(buffer
, size
);
1521 uint8 byVersion
= data
.ReadUInt8();
1522 CMD4Hash hash
= data
.ReadHash();
1523 CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1525 if (file
->IsPartFile()){
1526 //set the client's answer time
1527 m_client
->SetLastSrcAnswerTime();
1528 //and set the file's last answer time
1529 static_cast<CPartFile
*>(file
)->SetLastAnsweredTime();
1530 static_cast<CPartFile
*>(file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, byVersion
, true, m_client
);
1535 case OP_FILEDESC
: { // 0.43b
1536 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_FILEDESC from ") + m_client
->GetFullIP() );
1538 theStats::AddDownOverheadFileRequest(size
);
1540 if (!m_client
->CheckHandshakeFinished()) {
1541 // Here comes an extended packet without finishing the handshake.
1542 // IMHO, we should disconnect the client.
1543 throw wxString(wxT("Client send OP_FILEDESC before finishing handshake"));
1546 m_client
->ProcessMuleCommentPacket(buffer
, size
);
1551 case OP_REQUESTPREVIEW
: {
1552 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REQUESTPREVIEW from ") + m_client
->GetFullIP() );
1556 case OP_PREVIEWANSWER
: {
1557 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PREVIEWANSWER from ") + m_client
->GetFullIP() );
1561 case OP_PUBLICIP_ANSWER
: {
1562 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_ANSWER from ") + m_client
->GetFullIP() );
1563 theStats::AddDownOverheadOther(size
);
1564 m_client
->ProcessPublicIPAnswer(buffer
, size
);
1567 case OP_PUBLICIP_REQ
: {
1568 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_REQ from ") + m_client
->GetFullIP() );
1569 theStats::AddDownOverheadOther(size
);
1570 CPacket
* pPacket
= new CPacket(OP_PUBLICIP_ANSWER
, 4, OP_EMULEPROT
);
1571 pPacket
->CopyUInt32ToDataBuffer(m_client
->GetIP());
1572 theStats::AddUpOverheadOther(pPacket
->GetPacketSize());
1573 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_PUBLICIP_ANSWER to") + m_client
->GetFullIP());
1574 SendPacket(pPacket
);
1577 case OP_AICHANSWER
: {
1578 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHANSWER from ") + m_client
->GetFullIP() );
1579 theStats::AddDownOverheadOther(size
);
1580 m_client
->ProcessAICHAnswer(buffer
, size
);
1583 case OP_AICHREQUEST
: {
1584 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHREQUEST from ") + m_client
->GetFullIP() );
1585 theStats::AddDownOverheadOther(size
);
1586 m_client
->ProcessAICHRequest(buffer
, size
);
1589 case OP_AICHFILEHASHANS
: {
1590 // those should not be received normally, since we should only get those in MULTIPACKET
1591 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHANS from ") + m_client
->GetFullIP() );
1592 theStats::AddDownOverheadOther(size
);
1593 CMemFile
data(buffer
, size
);
1594 m_client
->ProcessAICHFileHash(&data
, NULL
);
1597 case OP_AICHFILEHASHREQ
: {
1598 // those should not be received normally, since we should only get those in MULTIPACKET
1599 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHREQ from ") + m_client
->GetFullIP() );
1600 CMemFile
data(buffer
, size
);
1601 CMD4Hash hash
= data
.ReadHash();
1602 CKnownFile
* pPartFile
= theApp
->sharedfiles
->GetFileByID(hash
);
1603 if (pPartFile
== NULL
){
1607 if (m_client
->IsSupportingAICH() && pPartFile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1608 && pPartFile
->GetAICHHashset()->HasValidMasterHash()) {
1610 data_out
.WriteHash(hash
);
1611 pPartFile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1612 CPacket
* packet
= new CPacket(data_out
, OP_EMULEPROT
, OP_AICHFILEHASHANS
);
1613 theStats::AddUpOverheadOther(packet
->GetPacketSize());
1614 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_AICHFILEHASHANS to") + m_client
->GetFullIP());
1620 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_CALLBACK from ") + m_client
->GetFullIP() );
1621 theStats::AddDownOverheadFileRequest(size
);
1622 if(!Kademlia::CKademlia::IsRunning()) {
1625 CMemFile
data(buffer
, size
);
1626 CUInt128 check
= data
.ReadUInt128();
1627 check
^= Kademlia::CUInt128(true);
1628 if (check
!= Kademlia::CKademlia::GetPrefs()->GetKadID()) {
1631 CUInt128 fileid
= data
.ReadUInt128();
1633 fileid
.ToByteArray(fileid2
);
1634 const CMD4Hash
fileHash(fileid2
);
1635 if (theApp
->sharedfiles
->GetFileByID(fileHash
) == NULL
) {
1636 if (theApp
->downloadqueue
->GetFileByID(fileHash
) == NULL
) {
1641 uint32 ip
= data
.ReadUInt32();
1642 uint16 tcp
= data
.ReadUInt16();
1643 CUpDownClient
* callback
;
1644 callback
= theApp
->clientlist
->FindClientByIP(wxUINT32_SWAP_ALWAYS(ip
), tcp
);
1645 if( callback
== NULL
) {
1646 //#warning Do we actually have to check friend status here?
1647 callback
= new CUpDownClient(tcp
,ip
,0,0,NULL
,false, false);
1648 theApp
->clientlist
->AddClient(callback
);
1650 callback
->TryToConnect(true);
1654 case OP_BUDDYPING
: {
1655 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_BUDDYPING from ") + m_client
->GetFullIP() );
1656 theStats::AddDownOverheadKad(size
);
1658 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1659 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 || !m_client
->AllowIncomeingBuddyPingPong() ) {
1660 //This ping was not from our buddy or wrong version or packet sent to fast. Ignore
1664 m_client
->SetLastBuddyPingPongTime();
1665 CPacket
* replypacket
= new CPacket(OP_BUDDYPONG
, 0, OP_EMULEPROT
);
1666 theStats::AddUpOverheadKad(replypacket
->GetPacketSize());
1667 AddDebugLogLineN(logLocalClient
,wxT("Local Client: OP_BUDDYPONG to ") + m_client
->GetFullIP());
1668 SendPacket(replypacket
);
1671 case OP_BUDDYPONG
: {
1672 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_BUDDYPONG from ") + m_client
->GetFullIP() );
1673 theStats::AddDownOverheadKad(size
);
1675 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1676 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 ) {
1677 //This pong was not from our buddy or wrong version. Ignore
1680 m_client
->SetLastBuddyPingPongTime();
1681 //All this is for is to reset our socket timeout.
1684 case OP_REASKCALLBACKTCP
: {
1685 theStats::AddDownOverheadFileRequest(size
);
1686 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1687 if (buddy
!= m_client
) {
1688 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() + wxT(" which is not our buddy!") );
1689 //This callback was not from our buddy.. Ignore.
1692 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() );
1693 CMemFile
data_in(buffer
, size
);
1694 uint32 destip
= data_in
.ReadUInt32();
1695 uint16 destport
= data_in
.ReadUInt16();
1696 CMD4Hash hash
= data_in
.ReadHash();
1697 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(hash
);
1699 bool bSenderMultipleIpUnknown
= false;
1700 CUpDownClient
* sender
= theApp
->uploadqueue
->GetWaitingClientByIP_UDP(destip
, destport
, true, &bSenderMultipleIpUnknown
);
1702 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_FILENOTFOUND to ") + m_client
->GetFullIP() );
1703 CPacket
* response
= new CPacket(OP_FILENOTFOUND
,0,OP_EMULEPROT
);
1704 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1706 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1708 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1714 //Make sure we are still thinking about the same file
1715 if (hash
== sender
->GetUploadFileID()) {
1716 sender
->AddAskedCount();
1717 sender
->SetLastUpRequest();
1718 //I messed up when I first added extended info to UDP
1719 //I should have originally used the entire ProcessExtenedInfo the first time.
1720 //So now I am forced to check UDPVersion to see if we are sending all the extended info.
1721 //For now on, we should not have to change anything here if we change
1722 //anything to the extended info data as this will be taken care of in ProcessExtendedInfo()
1723 //Update extended info.
1724 if (sender
->GetUDPVersion() > 3) {
1725 sender
->ProcessExtendedInfo(&data_in
, reqfile
);
1726 } else if (sender
->GetUDPVersion() > 2) {
1727 //Update our complete source counts.
1728 uint16 nCompleteCountLast
= sender
->GetUpCompleteSourcesCount();
1729 uint16 nCompleteCountNew
= data_in
.ReadUInt16();
1730 sender
->SetUpCompleteSourcesCount(nCompleteCountNew
);
1731 if (nCompleteCountLast
!= nCompleteCountNew
) {
1732 reqfile
->UpdatePartsInfo();
1736 CMemFile
data_out(128);
1737 if(sender
->GetUDPVersion() > 3) {
1738 if (reqfile
->IsPartFile()) {
1739 static_cast<CPartFile
*>(reqfile
)->WritePartStatus(&data_out
);
1741 data_out
.WriteUInt16(0);
1745 data_out
.WriteUInt16(sender
->GetUploadQueueWaitingPosition());
1746 CPacket
* response
= new CPacket(data_out
, OP_EMULEPROT
, OP_REASKACK
);
1747 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1748 AddDebugLogLineN( logLocalClient
, wxT("Local Client UDP: OP_REASKACK to ") + m_client
->GetFullIP() );
1749 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1751 AddDebugLogLineN(logListenSocket
, wxT("Client UDP socket; OP_REASKCALLBACKTCP; reqfile does not match"));
1754 if (!bSenderMultipleIpUnknown
){
1755 if ((theStats::GetWaitingUserCount() + 50) > thePrefs::GetQueueSize()) {
1756 AddDebugLogLineN( logLocalClient
, wxT("Local Client: OP_QUEUEFULL to ") + m_client
->GetFullIP() );
1757 CPacket
* response
= new CPacket(OP_QUEUEFULL
,0,OP_EMULEPROT
);
1758 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1759 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1762 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
);
1767 case OP_CHATCAPTCHAREQ
:
1769 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHAREQ from ") + m_client
->GetFullIP());
1770 theStats::AddDownOverheadOther(size
);
1771 CMemFile
data_in(buffer
, size
);
1772 m_client
->ProcessCaptchaRequest(&data_in
);
1775 case OP_CHATCAPTCHARES
:
1777 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHARES from ") + m_client
->GetFullIP());
1778 theStats::AddDownOverheadOther(size
);
1780 m_client
->ProcessCaptchaReqRes(buffer
[0]);
1784 case OP_FWCHECKUDPREQ
: { // Support required for Kadversion >= 6
1785 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_FWCHECKUDPREQ from ") + m_client
->GetFullIP());
1786 theStats::AddDownOverheadOther(size
);
1787 CMemFile
data_in(buffer
, size
);
1788 m_client
->ProcessFirewallCheckUDPRequest(&data_in
);
1791 case OP_KAD_FWTCPCHECK_ACK
: { // Support required for Kadversion >= 7
1792 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_KAD_FWTCPCHECK_ACK from ") + m_client
->GetFullIP());
1793 if (theApp
->clientlist
->IsKadFirewallCheckIP(m_client
->GetIP())) {
1794 if (Kademlia::CKademlia::IsRunning()) {
1795 Kademlia::CKademlia::GetPrefs()->IncFirewalled();
1798 AddDebugLogLineN(logListenSocket
, wxT("Received unrequested OP_KAD_FWTCPCHECK_ACK packet from ") + m_client
->GetFullIP());
1803 theStats::AddDownOverheadOther(size
);
1804 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("eMule packet : unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1811 bool CClientTCPSocket::ProcessED2Kv2Packet(const byte
* buffer
, uint32 size
, uint8 opcode
)
1813 #ifdef __PACKET_RECV_DUMP__
1814 //printf("Rec: OPCODE %x ED2Kv2\n",opcode);
1815 DumpMem(buffer
,size
);
1819 throw wxString(wxT("Unknown clients sends extended ED2Kv2 protocol packet"));
1822 CMemFile
data(buffer
, size
);
1825 case OP_QUEUERANK
: {
1826 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_QUEUERANK from ") + m_client
->GetFullIP() );
1828 uint8 numtags
= data
.ReadUInt8();
1829 wxASSERT(numtags
== 1);
1830 if(numtags
){} // prevent GCC warning
1832 m_client
->SetRemoteQueueRank(data
.GetIntTagValue());
1834 theStats::AddDownOverheadFileRequest(size
);
1838 case OP_REQUESTPARTS
: {
1839 AddDebugLogLineN( logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
1841 m_client
->ProcessRequestPartsPacketv2(data
);
1843 theStats::AddDownOverheadFileRequest(size
);
1848 theStats::AddDownOverheadOther(size
);
1849 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("ED2Kv2 packet : unknown opcode: %i %x from %s")) % opcode
% opcode
% m_client
->GetFullIP());
1852 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("ED2Kv2 packet is corrupt at pos %i! opcode: %i %x from %s")) % data
.GetPosition() % opcode
% opcode
% m_client
->GetFullIP());
1859 void CClientTCPSocket::OnConnect(int nErrorCode
)
1862 OnError(nErrorCode
);
1863 } else if (!m_client
) {
1864 // and now? Disconnect? not?
1865 AddDebugLogLineN( logClient
, wxT("Couldn't send hello packet (Client deleted!)") );
1866 } else if (!m_client
->SendHelloPacket()) {
1867 // and now? Disconnect? not?
1868 AddDebugLogLineN( logClient
, wxT("Couldn't send hello packet (Client deleted by SendHelloPacket!)") );
1870 ResetTimeOutTimer();
1875 void CClientTCPSocket::OnSend(int nErrorCode
)
1877 ResetTimeOutTimer();
1878 CEMSocket::OnSend(nErrorCode
);
1882 void CClientTCPSocket::OnReceive(int nErrorCode
)
1884 ResetTimeOutTimer();
1885 // We might have updated ipfilter
1886 wxASSERT(m_remoteip
);
1888 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
1890 m_client
->Safe_Delete();
1893 AddDebugLogLineN( logIPFilter
, wxT("A connected client was dropped by IPFilter on new packet received"));
1895 CEMSocket::OnReceive(nErrorCode
);
1900 void CClientTCPSocket::OnError(int nErrorCode
)
1902 //printf("* Called OnError for %p\n",this);
1903 // 0.42e + Kry changes for handling of socket lost events
1906 if ((nErrorCode
== 0) || (nErrorCode
== 7) || (nErrorCode
== 0xFEFF)) {
1908 if (!m_client
->GetUserName().IsEmpty()) {
1909 strError
= wxT("Client '") + m_client
->GetUserName() + wxT("'");
1911 strError
= wxT("An unnamed client");
1913 strError
+= wxT(" (IP:") + m_client
->GetFullIP() + wxT(") ");
1915 strError
= wxT("A client ");
1917 if (nErrorCode
== 0) {
1918 strError
+= wxT("closed connection.");
1919 } else if (nErrorCode
== 0xFEFF) {
1920 strError
+= wxT(" caused a wxSOCKET_LOST event.");
1922 strError
+= wxT("caused a socket blocking error.");
1925 if (theLogger
.IsEnabled(logClient
) && nErrorCode
!= 107) {
1926 // 0 -> No Error / Disconect
1927 // 107 -> Transport endpoint is not connected
1929 if (!m_client
->GetUserName().IsEmpty()) {
1930 strError
= CFormat(wxT("OnError: Client '%s' (IP:%s) caused an error: %u. Disconnecting client!"))
1931 % m_client
->GetUserName() % m_client
->GetFullIP() % nErrorCode
;
1933 strError
= CFormat(wxT("OnError: Unknown client (IP:%s) caused an error: %u. Disconnecting client!"))
1934 % m_client
->GetFullIP() % nErrorCode
;
1937 strError
= CFormat(wxT("OnError: A client caused an error or did something bad (error %u). Disconnecting client !"))
1941 strError
= wxT("Error 107 (Transport endpoint is not connected)");
1945 Disconnect(strError
);
1949 bool CClientTCPSocket::PacketReceived(CPacket
* packet
)
1952 bool bResult
= false;
1953 uint32 uRawSize
= packet
->GetPacketSize();
1955 AddDebugLogLineN( logRemoteClient
,
1956 CFormat(wxT("Packet with protocol %x, opcode %x, size %u received from %s"))
1957 % packet
->GetProtocol()
1958 % packet
->GetOpCode()
1959 % packet
->GetPacketSize()
1960 % ( m_client
? m_client
->GetFullIP() : wxT("Unknown Client") )
1966 bool process
= true;
1968 if ((packet
->GetProtocol() == OP_PACKEDPROT
) ||
1969 (packet
->GetProtocol() == OP_ED2KV2PACKEDPROT
)) {
1971 if (!packet
->UnPackPacket()) {
1972 AddDebugLogLineN(logZLib
, wxT("Failed to decompress client TCP packet."));
1976 AddDebugLogLineN(logRemoteClient
, CFormat(wxT("Packet unpacked, new protocol %x, opcode %x, size %u"))
1977 % packet
->GetProtocol() % packet
->GetOpCode() % packet
->GetPacketSize());
1982 switch (packet
->GetProtocol()) {
1983 case OP_EDONKEYPROT
:
1984 bResult
= ProcessPacket(packet
->GetDataBuffer(),uRawSize
,packet
->GetOpCode());
1987 bResult
= ProcessExtPacket(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
1989 case OP_ED2KV2HEADER
:
1990 bResult
= ProcessED2Kv2Packet(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
1992 case OP_ED2KV2PACKEDPROT
:
1994 // Packed inside packed?
1998 theStats::AddDownOverheadOther(uRawSize
);
2000 m_client
->SetDownloadState(DS_ERROR
);
2002 Disconnect(wxT("Unknown protocol"));
2007 } catch (const CEOFException
& err
) {
2008 exception
= wxT("EOF exception: ") + err
.what();
2009 } catch (const CInvalidPacket
& err
) {
2010 exception
= wxT("InvalidPacket exception: ") + err
.what();
2011 } catch (const wxString
& error
) {
2012 exception
= wxT("error: ") + (error
.IsEmpty() ? wxString(wxT("Unknown error")) : error
);
2015 if (!exception
.IsEmpty()) {
2016 AddDebugLogLineN( logPacketErrors
,
2017 CFormat(wxT("Caught %s\nOn packet with protocol %x, opcode %x, size %u\tClientData: %s\n"))
2019 % packet
->GetProtocol()
2020 % packet
->GetOpCode()
2021 % packet
->GetPacketSize()
2022 % ( m_client
? m_client
->GetClientFullInfo() : wxT("Unknown") )
2026 m_client
->SetDownloadState(DS_ERROR
);
2029 AddDebugLogLineN( logClient
,
2030 CFormat( wxT("Client '%s' (IP: %s) caused an error (%s). Disconnecting client!" ) )
2031 % ( m_client
? m_client
->GetUserName() : wxString(wxT("Unknown")) )
2032 % ( m_client
? m_client
->GetFullIP() : wxString(wxT("Unknown")) )
2036 Disconnect(wxT("Caught exception on CClientTCPSocket::ProcessPacket\n"));
2043 SocketSentBytes
CClientTCPSocket::SendControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2045 SocketSentBytes returnStatus
= CEMSocket::SendControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2047 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2048 ResetTimeOutTimer();
2051 return returnStatus
;
2055 SocketSentBytes
CClientTCPSocket::SendFileAndControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2057 SocketSentBytes returnStatus
= CEMSocket::SendFileAndControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2059 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2060 ResetTimeOutTimer();
2063 return returnStatus
;
2067 void CClientTCPSocket::SendPacket(CPacket
* packet
, bool delpacket
, bool controlpacket
, uint32 actualPayloadSize
)
2069 ResetTimeOutTimer();
2070 CEMSocket::SendPacket(packet
,delpacket
,controlpacket
, actualPayloadSize
);
2072 // File_checked_for_headers