2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 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 CClientTCPSocket
*socket
= dynamic_cast<CClientTCPSocket
*>(event
.GetSocket());
85 if (socket
->OnDestroy() || socket
->ForDeletion()) {
89 switch(event
.GetSocketEvent()) {
91 socket
->OnError(0xFEFF /* SOCKET_LOST is not an error */);
99 case wxSOCKET_CONNECTION
:
100 // connection stablished, nothing to do about it?
101 socket
->OnConnect(socket
->Error() ? socket
->LastError() : 0);
104 // Nothing should arrive here...
111 // There can be only one. :)
113 static CClientTCPSocketHandler g_clientReqSocketHandler
;
116 //------------------------------------------------------------------------------
118 //------------------------------------------------------------------------------
120 CClientTCPSocket::CClientTCPSocket(CUpDownClient
* in_client
, const CProxyData
*ProxyData
)
121 : CEMSocket(ProxyData
)
123 SetClient(in_client
);
125 m_remoteip
= wxUINT32_SWAP_ALWAYS(in_client
->GetUserIDHybrid());
131 m_ForDeletion
= false;
133 SetEventHandler(g_clientReqSocketHandler
, ID_CLIENTTCPSOCKET_EVENT
);
135 wxSOCKET_CONNECTION_FLAG
|
136 wxSOCKET_INPUT_FLAG
|
137 wxSOCKET_OUTPUT_FLAG
|
141 theApp
->listensocket
->AddSocket(this);
142 theApp
->listensocket
->AddConnection();
145 CClientTCPSocket::~CClientTCPSocket()
147 // remove event handler
152 m_client
->SetSocket( NULL
);
156 if (theApp
->listensocket
&& !theApp
->listensocket
->OnShutdown()) {
157 theApp
->listensocket
->RemoveSocket(this);
161 bool CClientTCPSocket::InitNetworkData()
163 wxASSERT(!m_remoteip
);
165 amuleIPV4Address addr
;
167 m_remoteip
= StringIPtoUint32(addr
.IPAddress());
169 MULE_CHECK(m_remoteip
, false);
171 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
172 AddDebugLogLineM(false, logClient
, wxT("Denied connection from ") + addr
.IPAddress() + wxT("(Filtered IP)"));
174 } else if (theApp
->clientlist
->IsBannedClient(m_remoteip
)) {
175 AddDebugLogLineM(false, logClient
, wxT("Denied connection from ") + addr
.IPAddress() + wxT("(Banned IP)"));
178 AddDebugLogLineM(false, logClient
, wxT("Accepted connection from ") + addr
.IPAddress());
183 void CClientTCPSocket::ResetTimeOutTimer()
185 timeout_timer
= ::GetTickCount();
189 bool CClientTCPSocket::CheckTimeOut()
192 uint32 uTimeout
= GetTimeOut();
195 if (m_client
->GetKadState() == KS_CONNECTED_BUDDY
) {
196 //We originally ignored the timeout here for buddies.
197 //This was a stupid idea on my part. There is now a ping/pong system
198 //for buddies. This ping/pong system now prevents timeouts.
199 //This release will allow lowID clients with KadVersion 0 to remain connected.
200 //But a soon future version needs to allow these older clients to time out to prevent dead connections from continuing.
201 //JOHNTODO: Don't forget to remove backward support in a future release.
202 if ( m_client
->GetKadVersion() == 0 ) {
206 uTimeout
+= MIN2MS(15);
209 if (m_client
->GetChatState() != MS_NONE
) {
210 uTimeout
+= CONNECTION_TIMEOUT
;
214 if (::GetTickCount() - timeout_timer
> uTimeout
){
215 timeout_timer
= ::GetTickCount();
216 Disconnect(wxT("Timeout"));
224 void CClientTCPSocket::SetClient(CUpDownClient
* pClient
)
228 m_client
->SetSocket( this );
233 void CClientTCPSocket::OnClose(int nErrorCode
)
236 wxASSERT(theApp
->listensocket
->IsValidSocket(this));
237 CEMSocket::OnClose(nErrorCode
);
239 Disconnect(wxString::Format(wxT("Closed: %u"), nErrorCode
));
241 Disconnect(wxT("Close"));
246 void CClientTCPSocket::Disconnect(const wxString
& strReason
)
248 byConnected
= ES_DISCONNECTED
;
250 if (m_client
->Disconnected(strReason
, true)) {
251 // Somehow, Safe_Delete() is beeing called by Disconnected(),
252 // or any other function that sets m_client to NULL,
253 // so we must check m_client first.
255 m_client
->SetSocket( NULL
);
256 m_client
->Safe_Delete();
266 void CClientTCPSocket::Safe_Delete()
268 if ( !ForDeletion() && !OnDestroy() ) {
272 // lfroen: first of all - stop handler
273 m_ForDeletion
= true;
276 m_client
->SetSocket( NULL
);
280 byConnected
= ES_DISCONNECTED
;
281 Close(); // Destroy is suposed to call Close(), but.. it doesn't hurt.
287 bool CClientTCPSocket::ProcessPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
289 #ifdef __PACKET_RECV_DUMP__
290 //printf("Rec: OPCODE %x \n",opcode);
291 DumpMem(buffer
, size
);
293 if (!m_client
&& opcode
!= OP_HELLO
) {
294 throw wxString(wxT("Asks for something without saying hello"));
295 } else if (m_client
&& opcode
!= OP_HELLO
&& opcode
!= OP_HELLOANSWER
) {
296 m_client
->CheckHandshakeFinished(OP_EDONKEYPROT
, opcode
);
300 case OP_HELLOANSWER
: { // 0.43b
301 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_HELLOANSWER from ") + m_client
->GetFullIP());
302 theStats::AddDownOverheadOther(size
);
303 m_client
->ProcessHelloAnswer(buffer
, size
);
305 // start secure identification, if
306 // - we have received OP_EMULEINFO and OP_HELLOANSWER (old eMule)
307 // - we have received eMule-OP_HELLOANSWER (new eMule)
308 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
309 m_client
->InfoPacketsReceived();
312 // Socket might die because of sending in InfoPacketsReceived, so check
314 m_client
->ConnectionEstablished();
317 // Socket might die on ConnectionEstablished somehow. Check it.
319 Notify_UploadCtrlRefreshClient( m_client
);
324 case OP_HELLO
: { // 0.43b
326 theStats::AddDownOverheadOther(size
);
327 bool bNewClient
= !m_client
;
329 // create new client to save standart informations
330 m_client
= new CUpDownClient(this);
334 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_HELLO from ") + m_client
->GetFullIP() );
336 bool bIsMuleHello
= false;
339 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
341 if (bNewClient
&& m_client
) {
342 // Don't let CUpDownClient::Disconnected be processed for a client which is not in the list of clients.
343 m_client
->Safe_Delete();
349 if (thePrefs::ParanoidFilter() && !IsLowID(m_client
->GetUserIDHybrid()) && (GetRemoteIP() != wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid()))) {
350 wxString reason
= wxT("Client claims a different IP from the one we received the hello packet from: ");
351 reason
+= Uint32toStringIP(wxUINT32_SWAP_ALWAYS(m_client
->GetUserIDHybrid())) + wxT(" / ") + Uint32toStringIP(GetRemoteIP());
352 AddDebugLogLineM(false, logClient
, reason
);
354 m_client
->Safe_Delete();
357 Disconnect(wxT("Paranoid disconecting: ") + reason
);
361 // if IP is filtered, dont reply but disconnect...
362 if (theApp
->ipfilter
->IsFiltered(m_client
->GetIP())) {
364 m_client
->Safe_Delete();
367 Disconnect(wxT("IPFilter"));
373 // now we check if we now this client already. if yes this socket will
374 // be attached to the known client, the new client will be deleted
375 // and the var. "client" will point to the known client.
376 // if not we keep our new-constructed client ;)
377 if (theApp
->clientlist
->AttachToAlreadyKnown(&m_client
,this)) {
378 // update the old client informations
379 bIsMuleHello
= m_client
->ProcessHelloPacket(buffer
, size
);
381 theApp
->clientlist
->AddClient(m_client
);
382 m_client
->SetCommentDirty();
384 Notify_UploadCtrlRefreshClient( m_client
);
385 // send a response packet with standart informations
386 if ((m_client
->GetHashType() == SO_EMULE
) && !bIsMuleHello
) {
387 m_client
->SendMuleInfoPacket(false);
390 // Client might die from Sending in SendMuleInfoPacket, so check
392 m_client
->SendHelloAnswer();
395 // Kry - If the other side supports it, send OS_INFO
396 // Client might die from Sending in SendHelloAnswer, so check
397 if (m_client
&& m_client
->GetOSInfoSupport()) {
398 m_client
->SendMuleInfoPacket(false,true); // Send the OS Info tag on the recycled Mule Info
401 // Client might die from Sending in SendMuleInfoPacket, so check
403 m_client
->ConnectionEstablished();
406 // start secure identification, if
407 // - we have received eMule-OP_HELLO (new eMule)
408 if (m_client
&& m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
409 m_client
->InfoPacketsReceived();
414 case OP_REQUESTFILENAME
: { // 0.43b
415 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQUESTFILENAME from ") + m_client
->GetFullIP() );
417 theStats::AddDownOverheadFileRequest(size
);
418 // IP banned, no answer for this request
419 if (m_client
->IsBanned()) {
423 if (!m_client
->GetWaitStartTime()) {
424 m_client
->SetWaitStartTime();
426 CMemFile
data_in(buffer
, size
);
427 CMD4Hash reqfilehash
= data_in
.ReadHash();
428 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
429 if ( reqfile
== NULL
) {
430 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
431 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
435 // if we are downloading this file, this could be a new source
436 // no passive adding of files with only one part
437 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
438 if (thePrefs::GetMaxSourcePerFile() >
439 ((CPartFile
*)reqfile
)->GetSourceCount()) {
440 theApp
->downloadqueue
->CheckAndAddKnownSource((CPartFile
*)reqfile
, m_client
);
444 // check to see if this is a new file they are asking for
445 if (m_client
->GetUploadFileID() != reqfilehash
) {
446 m_client
->SetCommentDirty();
449 m_client
->SetUploadFileID(reqfile
);
450 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
453 CMemFile
data_out(128);
454 data_out
.WriteHash(reqfile
->GetFileHash());
456 // Since it's for somebody else to see, we need to send the prettified
457 // filename, rather than the (possibly) mangled actual filename.
458 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
460 CPacket
* packet
= new CPacket(data_out
, OP_EDONKEYPROT
, OP_REQFILENAMEANSWER
);
461 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
462 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_REQFILENAMEANSWER to ") + m_client
->GetFullIP() );
463 SendPacket(packet
,true);
465 // SendPacket might kill the socket, so check
467 m_client
->SendCommentInfo(reqfile
);
471 throw wxString(wxT("Invalid OP_REQUESTFILENAME packet size"));
474 case OP_SETREQFILEID
: { // 0.43b EXCEPT track of bad clients
475 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_SETREQFILEID from ") + m_client
->GetFullIP() );
477 theStats::AddDownOverheadFileRequest(size
);
479 if (m_client
->IsBanned()) {
485 if (!m_client
->GetWaitStartTime()) {
486 m_client
->SetWaitStartTime();
489 const CMD4Hash
fileID(buffer
);
490 CKnownFile
*reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
491 if ( reqfile
== NULL
) {
492 reqfile
= theApp
->downloadqueue
->GetFileByID(fileID
);
493 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
494 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
495 replypacket
->Copy16ToDataBuffer(fileID
.GetHash());
496 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
497 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_FILERE to ") + m_client
->GetFullIP() );
498 SendPacket(replypacket
, true);
503 // check to see if this is a new file they are asking for
504 if (m_client
->GetUploadFileID() != fileID
) {
505 m_client
->SetCommentDirty();
508 m_client
->SetUploadFileID(reqfile
);
510 CMemFile
data(16+16);
511 data
.WriteHash(reqfile
->GetFileHash());
512 if (reqfile
->IsPartFile()) {
513 ((CPartFile
*)reqfile
)->WritePartStatus(&data
);
517 CPacket
* packet
= new CPacket(data
, OP_EDONKEYPROT
, OP_FILESTATUS
);
518 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
519 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_FILESTATUS to ") + m_client
->GetFullIP() );
520 SendPacket(packet
, true);
523 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
528 case OP_FILEREQANSNOFIL
: { // 0.43b protocol, lacks ZZ's download manager on swap
529 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_FILEREQANSNOFIL from ") + m_client
->GetFullIP() );
531 theStats::AddDownOverheadFileRequest(size
);
533 // if that client does not have my file maybe has another different
534 CPartFile
* reqfile
= theApp
->downloadqueue
->GetFileByID(CMD4Hash(buffer
));
536 reqfile
->AddDeadSource( m_client
);
541 // we try to swap to another file ignoring no needed parts files
542 switch (m_client
->GetDownloadState()) {
545 case DS_NONEEDEDPARTS
:
546 if (!m_client
->SwapToAnotherFile(true, true, true, NULL
)) {
547 theApp
->downloadqueue
->RemoveSource(m_client
);
553 throw wxString(wxT("Invalid OP_FILEREQUEST packet size"));
557 case OP_REQFILENAMEANSWER
: { // 0.43b except check for bad clients
558 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQFILENAMEANSWER from ") + m_client
->GetFullIP() );
560 theStats::AddDownOverheadFileRequest(size
);
561 CMemFile
data(buffer
, size
);
562 CMD4Hash hash
= data
.ReadHash();
563 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
564 m_client
->ProcessFileInfo(&data
, file
);
568 case OP_FILESTATUS
: { // 0.43b except check for bad clients
569 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_FILESTATUS from ") + m_client
->GetFullIP() );
571 theStats::AddDownOverheadFileRequest(size
);
572 CMemFile
data(buffer
, size
);
573 CMD4Hash hash
= data
.ReadHash();
574 const CPartFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
575 m_client
->ProcessFileStatus(false, &data
, file
);
579 case OP_STARTUPLOADREQ
: {
580 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_STARTUPLOADREQ from ") + m_client
->GetFullIP() );
582 theStats::AddDownOverheadFileRequest(size
);
584 if (!m_client
->CheckHandshakeFinished(OP_EDONKEYPROT
, opcode
)) {
588 m_client
->CheckForAggressive();
589 if ( m_client
->IsBanned() ) {
594 const CMD4Hash
fileID(buffer
);
595 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(fileID
);
597 if (m_client
->GetUploadFileID() != fileID
) {
598 m_client
->SetCommentDirty();
600 m_client
->SetUploadFileID(reqfile
);
601 m_client
->SendCommentInfo(reqfile
);
603 // Socket might die because of SendCommentInfo, so check
605 theApp
->uploadqueue
->AddClientToQueue(m_client
);
611 case OP_QUEUERANK
: { // 0.43b
612 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_QUEUERANK from ") + m_client
->GetFullIP() );
614 theStats::AddDownOverheadFileRequest(size
);
615 CMemFile
data(buffer
, size
);
616 uint32 rank
= data
.ReadUInt32();
618 m_client
->SetRemoteQueueRank(rank
);
622 case OP_ACCEPTUPLOADREQ
: { // 0.42e (xcept khaos stats)
623 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ACCEPTUPLOADREQ from ") + m_client
->GetFullIP() );
625 theStats::AddDownOverheadFileRequest(size
);
626 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
627 if (m_client
->GetDownloadState() == DS_ONQUEUE
) {
628 m_client
->SetDownloadState(DS_DOWNLOADING
);
629 m_client
->SetLastPartAsked(0xffff); // Reset current downloaded Chunk // Maella -Enhanced Chunk Selection- (based on jicxicmic)
630 m_client
->SendBlockRequests();
633 if (!m_client
->GetSentCancelTransfer()) {
634 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
635 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
636 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
637 m_client
->SendPacket(packet
,true,true);
639 // SendPacket can cause the socket to die, so check
641 m_client
->SetSentCancelTransfer(1);
645 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
650 case OP_REQUESTPARTS
: { // 0.43b
651 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
653 theStats::AddDownOverheadFileRequest(size
);
655 m_client
->ProcessRequestPartsPacket(buffer
, size
, false);
660 case OP_CANCELTRANSFER
: { // 0.43b
661 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_CANCELTRANSFER from ") + m_client
->GetFullIP() );
663 theStats::AddDownOverheadFileRequest(size
);
664 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
665 AddDebugLogLineM( false, logClient
, m_client
->GetUserName() + wxT(": Upload session ended due canceled transfer."));
669 case OP_END_OF_DOWNLOAD
: { // 0.43b except check for bad clients
670 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_END_OF_DOWNLOAD from ") + m_client
->GetFullIP() );
672 theStats::AddDownOverheadFileRequest(size
);
673 if (size
>=16 && m_client
->GetUploadFileID() == CMD4Hash(buffer
)) {
674 theApp
->uploadqueue
->RemoveFromUploadQueue(m_client
);
675 AddDebugLogLineM( false, logClient
, m_client
->GetUserName() + wxT(": Upload session ended due ended transfer."));
680 case OP_HASHSETREQUEST
: { // 0.43b except check for bad clients
681 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_HASHSETREQUEST from ") + m_client
->GetFullIP() );
684 theStats::AddDownOverheadFileRequest(size
);
686 throw wxString(wxT("Invalid OP_HASHSETREQUEST packet size"));
688 m_client
->SendHashsetPacket(CMD4Hash(buffer
));
692 case OP_HASHSETANSWER
: { // 0.43b
693 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_HASHSETANSWER from ") + m_client
->GetFullIP() );
695 theStats::AddDownOverheadFileRequest(size
);
696 m_client
->ProcessHashSet(buffer
, size
);
700 case OP_SENDINGPART
: { // 0.47a
701 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_SENDINGPART from ") + m_client
->GetFullIP() );
703 if ( m_client
->GetRequestFile() &&
704 !m_client
->GetRequestFile()->IsStopped() &&
705 (m_client
->GetRequestFile()->GetStatus() == PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
707 m_client
->ProcessBlockPacket(buffer
, size
, false, false);
710 ( m_client
->GetRequestFile()->IsStopped() ||
711 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
712 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
) ) {
713 if (!m_client
->GetSentCancelTransfer()) {
714 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
715 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
716 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
717 m_client
->SendPacket(packet
,true,true);
719 // Socket might die because of SendPacket, so check
721 m_client
->SetSentCancelTransfer(1);
725 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
728 if (!m_client
->GetSentCancelTransfer()) {
729 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
730 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
731 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
732 m_client
->SendPacket(packet
,true,true);
734 // Socket might die because of SendPacket, so check
735 m_client
->SetSentCancelTransfer(1);
737 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
742 case OP_OUTOFPARTREQS
: { // 0.43b
743 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_OUTOFPARTREQS from ") + m_client
->GetFullIP() );
745 theStats::AddDownOverheadFileRequest(size
);
746 if (m_client
->GetDownloadState() == DS_DOWNLOADING
) {
747 m_client
->SetDownloadState(DS_ONQUEUE
);
752 case OP_CHANGE_CLIENT_ID
: { // Kad reviewed
753 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_CHANGE_CLIENT_ID from ") + m_client
->GetFullIP() );
755 theStats::AddDownOverheadOther(size
);
756 CMemFile
data(buffer
, size
);
757 uint32 nNewUserID
= data
.ReadUInt32();
758 uint32 nNewServerIP
= data
.ReadUInt32();
760 if (IsLowID(nNewUserID
)) { // client changed server and gots a LowID
761 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
762 if (pNewServer
!= NULL
){
763 m_client
->SetUserIDHybrid(nNewUserID
); // update UserID only if we know the server
764 m_client
->SetServerIP(nNewServerIP
);
765 m_client
->SetServerPort(pNewServer
->GetPort());
767 } else if (nNewUserID
== m_client
->GetIP()) { // client changed server and gots a HighID(IP)
768 m_client
->SetUserIDHybrid(wxUINT32_SWAP_ALWAYS(nNewUserID
));
769 CServer
* pNewServer
= theApp
->serverlist
->GetServerByIP(nNewServerIP
);
770 if (pNewServer
!= NULL
){
771 m_client
->SetServerIP(nNewServerIP
);
772 m_client
->SetServerPort(pNewServer
->GetPort());
779 case OP_CHANGE_SLOT
:{ // 0.43b
780 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_CHANGE_SLOT from ") + m_client
->GetFullIP() );
782 // sometimes sent by Hybrid
783 theStats::AddDownOverheadOther(size
);
787 case OP_MESSAGE
: { // 0.43b
788 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MESSAGE from ") + m_client
->GetFullIP() );
790 theStats::AddDownOverheadOther(size
);
792 CMemFile
message_file(buffer
, size
);
794 wxString message
= message_file
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
795 if (IsMessageFiltered(message
, m_client
)) {
796 AddLogLineM( true, CFormat(_("Message filtered from '%s' (IP:%s)")) % m_client
->GetUserName() % m_client
->GetFullIP());
798 wxString logMsg
= CFormat(_("New message from '%s' (IP:%s)")) % m_client
->GetUserName() % m_client
->GetFullIP();
799 if(thePrefs::ShowMessagesInLog()) {
800 logMsg
+= wxT(": ") + message
;
802 AddLogLineM( true, logMsg
);
804 Notify_ChatProcessMsg(GUI_ID(m_client
->GetIP(),m_client
->GetUserPort()), m_client
->GetUserName() + wxT("|") + message
);
809 case OP_ASKSHAREDFILES
: { // 0.43b (well, er, it does the same, but in our own way)
810 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILES from ") + m_client
->GetFullIP() );
812 // client wants to know what we have in share, let's see if we allow him to know that
813 theStats::AddDownOverheadOther(size
);
814 // IP banned, no answer for this request
815 if (m_client
->IsBanned()) {
819 if (thePrefs::CanSeeShares() == vsfaEverybody
|| (thePrefs::CanSeeShares() == vsfaFriends
&& m_client
->IsFriend())) {
820 AddLogLineM( true, CFormat( _("User %s (%u) requested your sharedfiles-list -> Accepted"))
821 % m_client
->GetUserName()
822 % m_client
->GetUserIDHybrid() );
824 std::vector
<CKnownFile
*> list
;
825 theApp
->sharedfiles
->CopyFileList(list
);
827 CMemFile
tempfile(80);
828 tempfile
.WriteUInt32(list
.size());
829 for (unsigned i
= 0; i
< list
.size(); ++i
) {
830 if (!list
[i
]->IsLargeFile() || m_client
->SupportsLargeFiles()) {
831 theApp
->sharedfiles
->CreateOfferedFilePacket(list
[i
], &tempfile
, NULL
, m_client
);
835 // create a packet and send it
836 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESANSWER
);
837 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESANSWER to ") + m_client
->GetFullIP() );
838 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
839 SendPacket(replypacket
, true, true);
841 AddLogLineM( true, CFormat( _("User %s (%u) requested your sharedfiles-list -> Denied"))
842 % m_client
->GetUserName()
843 % m_client
->GetUserIDHybrid() );
845 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
846 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
847 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
848 SendPacket(replypacket
, true, true);
854 case OP_ASKSHAREDFILESANSWER
: { // 0.43b
855 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESANSWER from ") + m_client
->GetFullIP() );
857 theStats::AddDownOverheadOther(size
);
859 m_client
->ProcessSharedFileList(buffer
, size
, EmptyStr
);
863 case OP_ASKSHAREDDIRS
: { // 0.43b
864 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRS from ") + m_client
->GetFullIP() );
866 theStats::AddDownOverheadOther(size
);
867 wxASSERT( size
== 0 );
868 // IP banned, no answer for this request
869 if (m_client
->IsBanned()) {
872 if ((thePrefs::CanSeeShares()==vsfaEverybody
) || ((thePrefs::CanSeeShares()==vsfaFriends
) && m_client
->IsFriend())) {
873 AddLogLineM( true, CFormat( _("User %s (%u) requested your shareddirectories-list -> Accepted") )
874 % m_client
->GetUserName()
875 % m_client
->GetUserIDHybrid() );
877 // This list will contain all (unique) folders.
878 std::list
<CPath
> foldersToSend
;
880 // The shared folders
881 const unsigned folderCount
= theApp
->glob_prefs
->shareddir_list
.size();
882 for (unsigned i
= 0; i
< folderCount
; ++i
) {
883 foldersToSend
.push_back(theApp
->glob_prefs
->shareddir_list
[i
]);
886 // ... the categories folders ... (category 0 -> incoming)
887 for (unsigned i
= 0; i
< theApp
->glob_prefs
->GetCatCount(); ++i
) {
888 foldersToSend
.push_back(theApp
->glob_prefs
->GetCategory(i
)->path
);
891 // ... and the Magic thing from the eDonkey Hybrids...
892 foldersToSend
.push_back(CPath(OP_INCOMPLETE_SHARED_FILES
));
895 foldersToSend
.sort();
896 foldersToSend
.unique();
899 CMemFile
tempfile(80);
900 tempfile
.WriteUInt32(foldersToSend
.size());
902 std::list
<CPath
>::iterator it
= foldersToSend
.begin();
903 for (; it
!= foldersToSend
.end(); ++it
) {
904 // We need to send the 'raw' filename, so we can recognize it again.
905 tempfile
.WriteString(it
->GetRaw(), m_client
->GetUnicodeSupport());
908 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDDIRSANS
);
909 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
910 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDDIRSANS to ") + m_client
->GetFullIP() );
911 SendPacket(replypacket
, true, true);
913 AddLogLineM( true, CFormat( _("User %s (%u) requested your shareddirectories-list -> Denied") )
914 % m_client
->GetUserName()
915 % m_client
->GetUserIDHybrid() );
917 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
918 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
919 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
920 SendPacket(replypacket
, true, true);
926 case OP_ASKSHAREDFILESDIR
: { // 0.43b
927 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIR from ") + m_client
->GetFullIP() );
929 theStats::AddDownOverheadOther(size
);
930 // IP banned, no answer for this request
931 if (m_client
->IsBanned()) {
934 CMemFile
data(buffer
, size
);
936 wxString strReqDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
937 if (thePrefs::CanSeeShares()==vsfaEverybody
|| (thePrefs::CanSeeShares()==vsfaFriends
&& m_client
->IsFriend())) {
938 AddLogLineM( true, CFormat(_("User %s (%u) requested your sharedfiles-list for directory %s -> accepted")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
939 wxASSERT( data
.GetPosition() == data
.GetLength() );
941 CKnownFilePtrList list
;
943 if (strReqDir
== OP_INCOMPLETE_SHARED_FILES
) {
944 // get all shared files from download queue
945 int iQueuedFiles
= theApp
->downloadqueue
->GetFileCount();
946 for (int i
= 0; i
< iQueuedFiles
; i
++) {
947 CPartFile
* pFile
= theApp
->downloadqueue
->GetFileByIndex(i
);
948 if (pFile
== NULL
|| pFile
->GetStatus(true) != PS_READY
) {
952 list
.push_back(pFile
);
955 theApp
->sharedfiles
->GetSharedFilesByDirectory(strReqDir
, list
);
958 CMemFile
tempfile(80);
959 tempfile
.WriteString(strReqDir
, m_client
->GetUnicodeSupport());
960 tempfile
.WriteUInt32(list
.size());
962 while (!list
.empty()) {
963 if (!list
.front()->IsLargeFile() || m_client
->SupportsLargeFiles()) {
964 theApp
->sharedfiles
->CreateOfferedFilePacket(list
.front(), &tempfile
, NULL
, m_client
);
970 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESDIRANS
);
971 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
972 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESDIRANS to ") + m_client
->GetFullIP() );
973 SendPacket(replypacket
, true, true);
975 AddLogLineM( true, CFormat(_("User %s (%u) requested your sharedfiles-list for directory %s -> denied")) % m_client
->GetUserName() % m_client
->GetUserIDHybrid() % strReqDir
);
977 CPacket
* replypacket
= new CPacket(OP_ASKSHAREDDENIEDANS
, 0, OP_EDONKEYPROT
);
978 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
979 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDDENIEDANS to ") + m_client
->GetFullIP() );
980 SendPacket(replypacket
, true, true);
985 case OP_ASKSHAREDDIRSANS
:{ // 0.43b
986 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDIRSANS from ") + m_client
->GetFullIP() );
988 theStats::AddDownOverheadOther(size
);
989 if (m_client
->GetFileListRequested() == 1){
990 CMemFile
data(buffer
, size
);
991 uint32 uDirs
= data
.ReadUInt32();
992 for (uint32 i
= 0; i
< uDirs
; i
++){
993 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
994 AddLogLineM( true, CFormat( _("User %s (%u) shares directory %s") )
995 % m_client
->GetUserName()
996 % m_client
->GetUserIDHybrid()
999 CMemFile
tempfile(80);
1000 tempfile
.WriteString(strDir
, m_client
->GetUnicodeSupport());
1001 CPacket
* replypacket
= new CPacket(tempfile
, OP_EDONKEYPROT
, OP_ASKSHAREDFILESDIR
);
1002 theStats::AddUpOverheadOther(replypacket
->GetPacketSize());
1003 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ASKSHAREDFILESD to ") + m_client
->GetFullIP() );
1004 SendPacket(replypacket
, true, true);
1006 wxASSERT( data
.GetPosition() == data
.GetLength() );
1007 m_client
->SetFileListRequested(uDirs
);
1009 AddLogLineM( true, CFormat( _("User %s (%u) sent unrequested shared dirs.") )
1010 % m_client
->GetUserName()
1011 % m_client
->GetUserIDHybrid() );
1016 case OP_ASKSHAREDFILESDIRANS
: { // 0.43b
1017 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDFILESDIRANS from ") + m_client
->GetFullIP() );
1019 theStats::AddDownOverheadOther(size
);
1020 CMemFile
data(buffer
, size
);
1021 wxString strDir
= data
.ReadString((m_client
->GetUnicodeSupport() != utf8strNone
));
1023 if (m_client
->GetFileListRequested() > 0){
1024 AddLogLineM( true, CFormat( _("User %s (%u) sent sharedfiles-list for directory %s") )
1025 % m_client
->GetUserName()
1026 % m_client
->GetUserIDHybrid()
1029 m_client
->ProcessSharedFileList(buffer
+ data
.GetPosition(), size
- data
.GetPosition(), strDir
);
1030 if (m_client
->GetFileListRequested() == 0) {
1031 AddLogLineM( true, CFormat( _("User %s (%u) finished sending sharedfiles-list") )
1032 % m_client
->GetUserName()
1033 % m_client
->GetUserIDHybrid() );
1036 AddLogLineM( true, CFormat( _("User %s (%u) sent unwanted sharedfiles-list") )
1037 % m_client
->GetUserName()
1038 % m_client
->GetUserIDHybrid() );
1043 case OP_ASKSHAREDDENIEDANS
:
1044 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ASKSHAREDDENIEDANS from ") + m_client
->GetFullIP() );
1046 theStats::AddDownOverheadOther(size
);
1047 wxASSERT( size
== 0 );
1048 AddLogLineM( true, CFormat( _("User %s (%u) denied access to shared directories/files list") )
1049 % m_client
->GetUserName()
1050 % m_client
->GetUserIDHybrid() );
1052 m_client
->SetFileListRequested(0);
1056 theStats::AddDownOverheadOther(size
);
1057 AddDebugLogLineM( false, logRemoteClient
, wxString::Format(wxT("Edonkey packet: unknown opcode: %i %x from "), opcode
, opcode
) + m_client
->GetFullIP());
1065 bool CClientTCPSocket::ProcessExtPacket(const byte
* buffer
, uint32 size
, uint8 opcode
)
1067 #ifdef __PACKET_RECV_DUMP__
1068 //printf("Rec: OPCODE %x \n",opcode);
1069 DumpMem(buffer
,size
);
1072 // 0.42e - except the catchs on mem exception and file exception
1074 throw wxString(wxT("Unknown clients sends extended protocol packet"));
1077 if (!client->CheckHandshakeFinished(OP_EMULEPROT, opcode)) {
1078 // Here comes a extended packet without finishing the hanshake.
1079 // IMHO, we should disconnect the client.
1080 throw wxString(wxT("Client send extended packet before finishing handshake"));
1084 case OP_MULTIPACKET_EXT
:
1085 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET_EXT from ") + m_client
->GetFullIP());
1086 case OP_MULTIPACKET
: {
1087 if (opcode
== OP_MULTIPACKET
) AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET from ") + m_client
->GetFullIP() );
1089 theStats::AddDownOverheadFileRequest(size
);
1091 if (m_client
->IsBanned()) {
1095 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1096 // Here comes a extended packet without finishing the hanshake.
1097 // IMHO, we should disconnect the client.
1098 throw wxString(wxT("Client send OP_MULTIPACKET before finishing handshake"));
1101 CMemFile
data_in(buffer
, size
);
1102 CMD4Hash reqfilehash
= data_in
.ReadHash();
1103 uint64 nSize
= (opcode
== OP_MULTIPACKET_EXT
) ? data_in
.ReadUInt64() : 0;
1105 bool file_not_found
= false;
1106 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(reqfilehash
);
1107 if ( reqfile
== NULL
){
1108 reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1109 if ( !( reqfile
!= NULL
&& reqfile
->GetFileSize() > PARTSIZE
) ) {
1110 AddDebugLogLineM(false, logRemoteClient
, wxT("Remote client asked for a non-shared file"));
1111 file_not_found
= true;
1115 if (!file_not_found
&& reqfile
->IsLargeFile() && !m_client
->SupportsLargeFiles()) {
1116 AddDebugLogLineM(false, logRemoteClient
, wxT("Remote client asked for a large file but doesn't support them"));
1117 file_not_found
= true;
1120 if (!file_not_found
&& nSize
&& (reqfile
->GetFileSize() != nSize
)) {
1121 AddDebugLogLineM(false, logRemoteClient
, wxT("Remote client asked for a file but specified wrong size"));
1122 file_not_found
= true;
1125 if (file_not_found
) {
1126 CPacket
* replypacket
= new CPacket(OP_FILEREQANSNOFIL
, 16, OP_EDONKEYPROT
);
1127 replypacket
->Copy16ToDataBuffer(reqfilehash
.GetHash());
1128 theStats::AddUpOverheadFileRequest(replypacket
->GetPacketSize());
1129 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_FILEREQANSNOFIL to ") + m_client
->GetFullIP() );
1130 SendPacket(replypacket
, true);
1134 if (!m_client
->GetWaitStartTime()) {
1135 m_client
->SetWaitStartTime();
1137 // if we are downloading this file, this could be a new source
1138 // no passive adding of files with only one part
1139 if (reqfile
->IsPartFile() && reqfile
->GetFileSize() > PARTSIZE
) {
1140 if (thePrefs::GetMaxSourcePerFile() > ((CPartFile
*)reqfile
)->GetSourceCount()) {
1141 theApp
->downloadqueue
->CheckAndAddKnownSource((CPartFile
*)reqfile
, m_client
);
1144 // check to see if this is a new file they are asking for
1145 if (m_client
->GetUploadFileID() != reqfilehash
) {
1146 m_client
->SetCommentDirty();
1148 m_client
->SetUploadFileID(reqfile
);
1149 CMemFile
data_out(128);
1150 data_out
.WriteHash(reqfile
->GetFileHash());
1151 while(data_in
.GetLength()-data_in
.GetPosition()) {
1153 throw wxString(wxT("Client suddenly disconnected"));
1155 uint8 opcode_in
= data_in
.ReadUInt8();
1157 case OP_REQUESTFILENAME
: {
1158 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTFILENAME") );
1159 m_client
->ProcessExtendedInfo(&data_in
, reqfile
);
1160 data_out
.WriteUInt8(OP_REQFILENAMEANSWER
);
1162 // Since it's for somebody else to see, we need to send the prettified
1163 // filename, rather than the (possibly) mangled actual filename
1164 data_out
.WriteString(reqfile
->GetFileName().GetPrintable(), m_client
->GetUnicodeSupport());
1167 case OP_AICHFILEHASHREQ
: {
1168 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_AICHFILEHASHANS") );
1169 if (m_client
->IsSupportingAICH() && reqfile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1170 && reqfile
->GetAICHHashset()->HasValidMasterHash())
1172 data_out
.WriteUInt8(OP_AICHFILEHASHANS
);
1173 reqfile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1177 case OP_SETREQFILEID
: {
1178 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_SETREQFILEID") );
1179 data_out
.WriteUInt8(OP_FILESTATUS
);
1180 if (reqfile
->IsPartFile()) {
1181 ((CPartFile
*)reqfile
)->WritePartStatus(&data_out
);
1183 data_out
.WriteUInt16(0);
1187 //We still send the source packet separately..
1188 //We could send it within this packet.. If agreeded, I will fix it..
1189 case OP_REQUESTSOURCES2
:
1190 case OP_REQUESTSOURCES
: {
1191 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKET has OP_REQUESTSOURCES(2)") );
1192 uint8 byRequestedVersion
= 0;
1193 uint16 byRequestedOptions
= 0;
1194 if (opcode_in
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1195 byRequestedVersion
= data_in
.ReadUInt8();
1196 byRequestedOptions
= data_in
.ReadUInt16();
1199 //Although this shouldn't happen, it's a just in case to any Mods that mess with version numbers.
1201 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() > 1) {
1202 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1203 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1205 //if not complete and file is rare
1206 ( reqfile
->IsPartFile()
1207 && (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1208 && ((CPartFile
*)reqfile
)->GetSourceCount() <= RARE_FILE
1210 //OR if file is not rare or if file is complete
1211 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1214 m_client
->SetLastSrcReqTime();
1215 CPacket
* tosend
= reqfile
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1217 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1218 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1219 SendPacket(tosend
, true);
1228 if( data_out
.GetLength() > 16 ) {
1229 CPacket
* reply
= new CPacket(data_out
, OP_EMULEPROT
, OP_MULTIPACKETANSWER
);
1230 theStats::AddUpOverheadFileRequest(reply
->GetPacketSize());
1231 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_MULTIPACKETANSWER to ") + m_client
->GetFullIP() );
1232 SendPacket(reply
, true);
1237 case OP_MULTIPACKETANSWER
: { // 0.43b
1238 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_MULTIPACKETANSWER from ") + m_client
->GetFullIP() );
1240 theStats::AddDownOverheadFileRequest(size
);
1242 if (m_client
->IsBanned()) {
1246 if( m_client
->GetKadPort() ) {
1247 Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(m_client
->GetIP()), m_client
->GetKadPort(), m_client
->GetKadVersion() > 1);
1250 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1251 // Here comes a extended packet without finishing the hanshake.
1252 // IMHO, we should disconnect the client.
1253 throw wxString(wxT("Client send OP_MULTIPACKETANSWER before finishing handshake"));
1256 CMemFile
data_in(buffer
, size
);
1257 CMD4Hash reqfilehash
= data_in
.ReadHash();
1258 const CPartFile
*reqfile
= theApp
->downloadqueue
->GetFileByID(reqfilehash
);
1259 //Make sure we are downloading this file.
1261 throw wxString(wxT(" Wrong File ID: (OP_MULTIPACKETANSWER; reqfile==NULL)"));
1263 if ( !m_client
->GetRequestFile() ) {
1265 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; client->reqfile==NULL)"));
1267 if (reqfile
!= m_client
->GetRequestFile()) {
1268 throw wxString(wxT(" Wrong File ID: OP_MULTIPACKETANSWER; reqfile!=client->reqfile)"));
1270 while (data_in
.GetLength()-data_in
.GetPosition()) {
1271 // Some of the cases down there can actually send a packet and lose the client
1273 throw wxString(wxT("Client suddenly disconnected"));
1275 uint8 opcode_in
= data_in
.ReadUInt8();
1277 case OP_REQFILENAMEANSWER
: {
1279 throw wxString(wxT("Client suddenly disconnected"));
1281 m_client
->ProcessFileInfo(&data_in
, reqfile
);
1285 case OP_FILESTATUS
: {
1287 throw wxString(wxT("Client suddenly disconnected"));
1289 m_client
->ProcessFileStatus(false, &data_in
, reqfile
);
1293 case OP_AICHFILEHASHANS
: {
1295 throw wxString(wxT("Client suddenly disconnected"));
1297 m_client
->ProcessAICHFileHash(&data_in
, reqfile
);
1307 case OP_EMULEINFO
: { // 0.43b
1308 theStats::AddDownOverheadOther(size
);
1310 if (!m_client
->ProcessMuleInfoPacket(buffer
, size
)) {
1311 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_EMULEINFO from ") + m_client
->GetFullIP() );
1313 // If it's not a OS Info packet, is an old client
1314 // start secure identification, if
1315 // - we have received eD2K and eMule info (old eMule)
1316 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1317 m_client
->InfoPacketsReceived();
1319 m_client
->SendMuleInfoPacket(true);
1321 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_EMULEINFO is an OS_INFO") );
1325 case OP_EMULEINFOANSWER
: { // 0.43b
1326 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_EMULEINFOANSWER from ") + m_client
->GetFullIP() );
1327 theStats::AddDownOverheadOther(size
);
1329 m_client
->ProcessMuleInfoPacket(buffer
, size
);
1330 // start secure identification, if
1331 // - we have received eD2K and eMule info (old eMule)
1333 if (m_client
->GetInfoPacketsReceived() == IP_BOTH
) {
1334 m_client
->InfoPacketsReceived();
1340 case OP_SECIDENTSTATE
:{ // 0.43b
1341 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_SECIDENTSTATE from ") + m_client
->GetFullIP() );
1343 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1344 // Here comes a extended packet without finishing the hanshake.
1345 // IMHO, we should disconnect the client.
1346 throw wxString(wxT("Client send OP_SECIDENTSTATE before finishing handshake"));
1348 m_client
->ProcessSecIdentStatePacket(buffer
, size
);
1349 // ProcessSecIdentStatePacket() might cause the socket to die, so check
1351 int SecureIdentState
= m_client
->GetSecureIdentState();
1352 if (SecureIdentState
== IS_SIGNATURENEEDED
) {
1353 m_client
->SendSignaturePacket();
1354 } else if (SecureIdentState
== IS_KEYANDSIGNEEDED
) {
1355 m_client
->SendPublicKeyPacket();
1356 // SendPublicKeyPacket() might cause the socket to die, so check
1358 m_client
->SendSignaturePacket();
1365 case OP_PUBLICKEY
: { // 0.43b
1366 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_PUBLICKEY from ") + m_client
->GetFullIP() );
1368 if (m_client
->IsBanned() ){
1372 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1373 // Here comes a extended packet without finishing the hanshake.
1374 // IMHO, we should disconnect the client.
1375 throw wxString(wxT("Client send OP_PUBLICKEY before finishing handshake"));
1378 m_client
->ProcessPublicKeyPacket(buffer
, size
);
1381 case OP_SIGNATURE
:{ // 0.43b
1382 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_SIGNATURE from ") + m_client
->GetFullIP() );
1384 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1385 // Here comes a extended packet without finishing the hanshake.
1386 // IMHO, we should disconnect the client.
1387 throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1390 m_client
->ProcessSignaturePacket(buffer
, size
);
1393 case OP_SENDINGPART_I64
:
1394 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_SENDINGPART_I64 from ") + m_client
->GetFullIP() );
1395 case OP_COMPRESSEDPART_I64
:
1396 if (opcode
== OP_COMPRESSEDPART_I64
) AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART_I64 from ") + m_client
->GetFullIP() );
1397 case OP_COMPRESSEDPART
: { // 0.47a
1398 if (opcode
== OP_COMPRESSEDPART
) AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_COMPRESSEDPART from ") + m_client
->GetFullIP() );
1400 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1401 // Here comes a extended packet without finishing the hanshake.
1402 // IMHO, we should disconnect the client.
1403 throw wxString(wxT("Client send OP_COMPRESSEDPART before finishing handshake"));
1406 if (m_client
->GetRequestFile() && !m_client
->GetRequestFile()->IsStopped() && (m_client
->GetRequestFile()->GetStatus()==PS_READY
|| m_client
->GetRequestFile()->GetStatus()==PS_EMPTY
)) {
1408 m_client
->ProcessBlockPacket(buffer
, size
, (opcode
!= OP_SENDINGPART_I64
), (opcode
== OP_COMPRESSEDPART_I64
) || (opcode
== OP_SENDINGPART_I64
));
1411 m_client
->GetRequestFile()->IsStopped() ||
1412 m_client
->GetRequestFile()->GetStatus() == PS_PAUSED
||
1413 m_client
->GetRequestFile()->GetStatus() == PS_ERROR
)) {
1414 if (!m_client
->GetSentCancelTransfer()) {
1415 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1416 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1417 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1418 m_client
->SendPacket(packet
,true,true);
1421 m_client
->SetSentCancelTransfer(1);
1426 m_client
->SetDownloadState(m_client
->GetRequestFile()->IsStopped() ? DS_NONE
: DS_ONQUEUE
);
1430 if (!m_client
->GetSentCancelTransfer()) {
1431 CPacket
* packet
= new CPacket(OP_CANCELTRANSFER
, 0, OP_EDONKEYPROT
);
1432 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1433 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_CANCELTRANSFER to ") + m_client
->GetFullIP() );
1434 m_client
->SendPacket(packet
,true,true);
1437 m_client
->SetSentCancelTransfer(1);
1442 m_client
->SetDownloadState((m_client
->GetRequestFile()==NULL
|| m_client
->GetRequestFile()->IsStopped()) ? DS_NONE
: DS_ONQUEUE
);
1447 case OP_REQUESTPARTS_I64
: {
1448 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQUESTPARTS_I64 from ") + m_client
->GetFullIP() );
1450 theStats::AddDownOverheadFileRequest(size
);
1452 m_client
->ProcessRequestPartsPacket(buffer
, size
, true);
1456 case OP_QUEUERANKING
: { // 0.43b
1457 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_QUEUERANKING from ") + m_client
->GetFullIP() );
1459 theStats::AddDownOverheadOther(size
);
1461 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1462 // Here comes a extended packet without finishing the hanshake.
1463 // IMHO, we should disconnect the client.
1464 throw wxString(wxT("Client send OP_QUEUERANKING before finishing handshake"));
1468 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1471 uint16 newrank
= PeekUInt16(buffer
);
1472 m_client
->SetRemoteQueueFull(false);
1473 m_client
->SetRemoteQueueRank(newrank
);
1476 case OP_REQUESTSOURCES2
:
1477 case OP_REQUESTSOURCES
:{
1478 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQUESTSOURCES from ") + m_client
->GetFullIP() );
1480 theStats::AddDownOverheadSourceExchange(size
);
1482 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1483 // Here comes an extended packet without finishing the handshake.
1484 // IMHO, we should disconnect the client.
1485 throw wxString(wxT("Client send OP_REQUESTSOURCES before finishing handshake"));
1488 uint8 byRequestedVersion
= 0;
1489 uint16 byRequestedOptions
= 0;
1490 CMemFile
data_in(buffer
, size
);
1491 if (opcode
== OP_REQUESTSOURCES2
){ // SX2 requests contains additional data
1492 byRequestedVersion
= data_in
.ReadUInt8();
1493 byRequestedOptions
= data_in
.ReadUInt16();
1496 if (byRequestedVersion
> 0 || m_client
->GetSourceExchange1Version() >= 1) {
1498 throw wxString(wxT("Invalid size (OP_QUEUERANKING)"));
1500 //first check shared file list, then download list
1501 const CMD4Hash
fileID(buffer
);
1502 CKnownFile
* file
= theApp
->sharedfiles
->GetFileByID(fileID
);
1504 file
= theApp
->downloadqueue
->GetFileByID(fileID
);
1507 // There are some clients which do not follow the correct protocol procedure of sending
1508 // the sequence OP_REQUESTFILENAME, OP_SETREQFILEID, OP_REQUESTSOURCES. If those clients
1509 // are doing this, they will not get the optimal set of sources which we could offer if
1510 // they would follow the above noted protocol sequence. They better do it the right way
1511 // or they will get just a random set of sources because we do not know their download
1512 // part status which may get cleared with the call of 'SetUploadFileID'.
1513 m_client
->SetUploadFileID(file
);
1515 uint32 dwTimePassed
= ::GetTickCount() - m_client
->GetLastSrcReqTime() + CONNECTION_LATENCY
;
1516 bool bNeverAskedBefore
= m_client
->GetLastSrcReqTime() == 0;
1518 //if not complete and file is rare, allow once every 40 minutes
1519 ( file
->IsPartFile() &&
1520 ((CPartFile
*)file
)->GetSourceCount() <= RARE_FILE
&&
1521 (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
)
1523 //OR if file is not rare or if file is complete, allow every 90 minutes
1524 ( (bNeverAskedBefore
|| dwTimePassed
> SOURCECLIENTREASKS
* MINCOMMONPENALTY
) )
1527 m_client
->SetLastSrcReqTime();
1528 CPacket
* tosend
= file
->CreateSrcInfoPacket(m_client
, byRequestedVersion
, byRequestedOptions
);
1530 theStats::AddUpOverheadSourceExchange(tosend
->GetPacketSize());
1531 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_ANSWERSOURCES to ") + m_client
->GetFullIP() );
1532 SendPacket(tosend
, true, true);
1539 case OP_ANSWERSOURCES
: {
1540 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_ANSWERSOURCES from ") + m_client
->GetFullIP() );
1542 theStats::AddDownOverheadSourceExchange(size
);
1544 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1545 // Here comes a extended packet without finishing the hanshake.
1546 // IMHO, we should disconnect the client.
1547 throw wxString(wxT("Client send OP_ANSWERSOURCES before finishing handshake"));
1550 CMemFile
data(buffer
, size
);
1551 CMD4Hash hash
= data
.ReadHash();
1552 const CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1554 if (file
->IsPartFile()){
1555 //set the client's answer time
1556 m_client
->SetLastSrcAnswerTime();
1557 //and set the file's last answer time
1558 ((CPartFile
*)file
)->SetLastAnsweredTime();
1560 ((CPartFile
*)file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, m_client
->GetSourceExchange1Version(), false, m_client
);
1565 case OP_ANSWERSOURCES2
: {
1566 //printf("Received OP_ANSWERSOURCES2\n");
1567 theStats::AddDownOverheadSourceExchange(size
);
1569 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1570 // Here comes a extended packet without finishing the hanshake.
1571 // IMHO, we should disconnect the client.
1572 throw wxString(wxT("Client send OP_ANSWERSOURCES2 before finishing handshake"));
1575 CMemFile
data(buffer
, size
);
1576 uint8 byVersion
= data
.ReadUInt8();
1577 CMD4Hash hash
= data
.ReadHash();
1578 const CKnownFile
* file
= theApp
->downloadqueue
->GetFileByID(hash
);
1580 if (file
->IsPartFile()){
1581 //set the client's answer time
1582 m_client
->SetLastSrcAnswerTime();
1583 //and set the file's last answer time
1584 ((CPartFile
*)file
)->SetLastAnsweredTime();
1585 ((CPartFile
*)file
)->AddClientSources(&data
, SF_SOURCE_EXCHANGE
, byVersion
, true, m_client
);
1590 case OP_FILEDESC
: { // 0.43b
1591 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_FILEDESC from ") + m_client
->GetFullIP() );
1593 theStats::AddDownOverheadFileRequest(size
);
1595 if (!m_client
->CheckHandshakeFinished(OP_EMULEPROT
, opcode
)) {
1596 // Here comes a extended packet without finishing the hanshake.
1597 // IMHO, we should disconnect the client.
1598 throw wxString(wxT("Client send OP_FILEDESC before finishing handshake"));
1601 m_client
->ProcessMuleCommentPacket(buffer
, size
);
1606 case OP_REQUESTPREVIEW
: {
1607 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REQUESTPREVIEW from ") + m_client
->GetFullIP() );
1611 case OP_PREVIEWANSWER
: {
1612 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_PREVIEWANSWER from ") + m_client
->GetFullIP() );
1616 case OP_PUBLICIP_ANSWER
: {
1617 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_ANSWER from ") + m_client
->GetFullIP() );
1618 theStats::AddDownOverheadOther(size
);
1619 m_client
->ProcessPublicIPAnswer(buffer
, size
);
1622 case OP_PUBLICIP_REQ
: {
1623 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_PUBLICIP_REQ from ") + m_client
->GetFullIP() );
1624 theStats::AddDownOverheadOther(size
);
1625 CPacket
* pPacket
= new CPacket(OP_PUBLICIP_ANSWER
, 4, OP_EMULEPROT
);
1626 pPacket
->CopyUInt32ToDataBuffer(m_client
->GetIP());
1627 theStats::AddUpOverheadOther(pPacket
->GetPacketSize());
1628 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_PUBLICIP_ANSWER to") + m_client
->GetFullIP());
1629 SendPacket(pPacket
);
1632 case OP_AICHANSWER
: {
1633 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_AICHANSWER from ") + m_client
->GetFullIP() );
1634 theStats::AddDownOverheadOther(size
);
1635 m_client
->ProcessAICHAnswer(buffer
, size
);
1638 case OP_AICHREQUEST
: {
1639 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_AICHREQUEST from ") + m_client
->GetFullIP() );
1640 theStats::AddDownOverheadOther(size
);
1641 m_client
->ProcessAICHRequest(buffer
, size
);
1644 case OP_AICHFILEHASHANS
: {
1645 // those should not be received normally, since we should only get those in MULTIPACKET
1646 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHANS from ") + m_client
->GetFullIP() );
1647 theStats::AddDownOverheadOther(size
);
1648 CMemFile
data(buffer
, size
);
1649 m_client
->ProcessAICHFileHash(&data
, NULL
);
1652 case OP_AICHFILEHASHREQ
: {
1653 // those should not be received normally, since we should only get those in MULTIPACKET
1654 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_AICHFILEHASHREQ from ") + m_client
->GetFullIP() );
1655 CMemFile
data(buffer
, size
);
1656 CMD4Hash hash
= data
.ReadHash();
1657 CKnownFile
* pPartFile
= theApp
->sharedfiles
->GetFileByID(hash
);
1658 if (pPartFile
== NULL
){
1662 if (m_client
->IsSupportingAICH() && pPartFile
->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE
1663 && pPartFile
->GetAICHHashset()->HasValidMasterHash()) {
1665 data_out
.WriteHash(hash
);
1666 pPartFile
->GetAICHHashset()->GetMasterHash().Write(&data_out
);
1667 CPacket
* packet
= new CPacket(data_out
, OP_EMULEPROT
, OP_AICHFILEHASHANS
);
1668 theStats::AddUpOverheadOther(packet
->GetPacketSize());
1669 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_AICHFILEHASHANS to") + m_client
->GetFullIP());
1675 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_CALLBACK from ") + m_client
->GetFullIP() );
1676 theStats::AddDownOverheadFileRequest(size
);
1677 if(!Kademlia::CKademlia::IsRunning()) {
1680 CMemFile
data(buffer
, size
);
1681 CUInt128 check
= data
.ReadUInt128();
1682 check
.XOR(Kademlia::CUInt128(true));
1683 if( check
.CompareTo(Kademlia::CKademlia::GetPrefs()->GetKadID())) {
1686 CUInt128 fileid
= data
.ReadUInt128();
1688 fileid
.ToByteArray(fileid2
);
1689 const CMD4Hash
fileHash(fileid2
);
1690 if (theApp
->sharedfiles
->GetFileByID(fileHash
) == NULL
) {
1691 if (theApp
->downloadqueue
->GetFileByID(fileHash
) == NULL
) {
1696 uint32 ip
= data
.ReadUInt32();
1697 uint16 tcp
= data
.ReadUInt16();
1698 CUpDownClient
* callback
;
1699 callback
= theApp
->clientlist
->FindClientByIP(wxUINT32_SWAP_ALWAYS(ip
), tcp
);
1700 if( callback
== NULL
) {
1701 //#warning Do we actually have to check friend status here?
1702 callback
= new CUpDownClient(tcp
,ip
,0,0,NULL
,false, false);
1703 theApp
->clientlist
->AddClient(callback
);
1705 callback
->TryToConnect(true);
1709 case OP_BUDDYPING
: {
1710 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_BUDDYPING from ") + m_client
->GetFullIP() );
1711 theStats::AddDownOverheadKad(size
);
1713 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1714 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 || !m_client
->AllowIncomeingBuddyPingPong() ) {
1715 //This ping was not from our buddy or wrong version or packet sent to fast. Ignore
1719 m_client
->SetLastBuddyPingPongTime();
1720 CPacket
* replypacket
= new CPacket(OP_BUDDYPONG
, 0, OP_EMULEPROT
);
1721 theStats::AddUpOverheadKad(replypacket
->GetPacketSize());
1722 AddDebugLogLineM(false, logLocalClient
,wxT("Local Client: OP_BUDDYPONG to ") + m_client
->GetFullIP());
1723 SendPacket(replypacket
);
1726 case OP_BUDDYPONG
: {
1727 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_BUDDYPONG from ") + m_client
->GetFullIP() );
1728 theStats::AddDownOverheadKad(size
);
1730 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1731 if( buddy
!= m_client
|| m_client
->GetKadVersion() == 0 ) {
1732 //This pong was not from our buddy or wrong version. Ignore
1735 m_client
->SetLastBuddyPingPongTime();
1736 //All this is for is to reset our socket timeout.
1739 case OP_REASKCALLBACKTCP
: {
1740 theStats::AddDownOverheadFileRequest(size
);
1741 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1742 if (buddy
!= m_client
) {
1743 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() + wxT(" which is not our buddy!") );
1744 //This callback was not from our buddy.. Ignore.
1747 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: OP_REASKCALLBACKTCP from ") + m_client
->GetFullIP() );
1748 CMemFile
data_in(buffer
, size
);
1749 uint32 destip
= data_in
.ReadUInt32();
1750 uint16 destport
= data_in
.ReadUInt16();
1751 CMD4Hash hash
= data_in
.ReadHash();
1752 CKnownFile
* reqfile
= theApp
->sharedfiles
->GetFileByID(hash
);
1754 bool bSenderMultipleIpUnknown
= false;
1755 CUpDownClient
* sender
= theApp
->uploadqueue
->GetWaitingClientByIP_UDP(destip
, destport
, true, &bSenderMultipleIpUnknown
);
1757 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_FILENOTFOUND to ") + m_client
->GetFullIP() );
1758 CPacket
* response
= new CPacket(OP_FILENOTFOUND
,0,OP_EMULEPROT
);
1759 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1761 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1763 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1769 //Make sure we are still thinking about the same file
1770 if (hash
== sender
->GetUploadFileID()) {
1771 sender
->AddAskedCount();
1772 sender
->SetLastUpRequest();
1773 //I messed up when I first added extended info to UDP
1774 //I should have originally used the entire ProcessExtenedInfo the first time.
1775 //So now I am forced to check UDPVersion to see if we are sending all the extended info.
1776 //For now on, we should not have to change anything here if we change
1777 //anything to the extended info data as this will be taken care of in ProcessExtendedInfo()
1778 //Update extended info.
1779 if (sender
->GetUDPVersion() > 3) {
1780 sender
->ProcessExtendedInfo(&data_in
, reqfile
);
1781 } else if (sender
->GetUDPVersion() > 2) {
1782 //Update our complete source counts.
1783 uint16 nCompleteCountLast
= sender
->GetUpCompleteSourcesCount();
1784 uint16 nCompleteCountNew
= data_in
.ReadUInt16();
1785 sender
->SetUpCompleteSourcesCount(nCompleteCountNew
);
1786 if (nCompleteCountLast
!= nCompleteCountNew
) {
1787 reqfile
->UpdatePartsInfo();
1791 CMemFile
data_out(128);
1792 if(sender
->GetUDPVersion() > 3) {
1793 if (reqfile
->IsPartFile()) {
1794 ((CPartFile
*)reqfile
)->WritePartStatus(&data_out
);
1796 data_out
.WriteUInt16(0);
1800 data_out
.WriteUInt16(theApp
->uploadqueue
->GetWaitingPosition(sender
));
1801 CPacket
* response
= new CPacket(data_out
, OP_EMULEPROT
, OP_REASKACK
);
1802 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1803 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client UDP: OP_REASKACK to ") + m_client
->GetFullIP() );
1804 theApp
->clientudp
->SendPacket(response
, destip
, destport
, sender
->ShouldReceiveCryptUDPPackets(), sender
->GetUserHash().GetHash(), false, 0);
1806 AddDebugLogLineM(false, logListenSocket
, wxT("Client UDP socket; OP_REASKCALLBACKTCP; reqfile does not match"));
1809 if (!bSenderMultipleIpUnknown
){
1810 if ((theStats::GetWaitingUserCount() + 50) > thePrefs::GetQueueSize()) {
1811 AddDebugLogLineM( false, logLocalClient
, wxT("Local Client: OP_QUEUEFULL to ") + m_client
->GetFullIP() );
1812 CPacket
* response
= new CPacket(OP_QUEUEFULL
,0,OP_EMULEPROT
);
1813 theStats::AddUpOverheadFileRequest(response
->GetPacketSize());
1814 theApp
->clientudp
->SendPacket(response
, destip
, destport
, false, NULL
, false, 0);
1817 AddDebugLogLineM(false, 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
);
1822 case OP_CHATCAPTCHAREQ
:
1824 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHAREQ from ") + m_client
->GetFullIP());
1825 theStats::AddDownOverheadOther(size
);
1826 CMemFile
data_in(buffer
, size
);
1827 m_client
->ProcessCaptchaRequest(&data_in
);
1830 case OP_CHATCAPTCHARES
:
1832 AddDebugLogLineN(logRemoteClient
, wxT("Remote Client: OP_CHATCAPTCHARES from ") + m_client
->GetFullIP());
1833 theStats::AddDownOverheadOther(size
);
1835 m_client
->ProcessCaptchaReqRes(buffer
[0]);
1839 case OP_FWCHECKUDPREQ
: { // Support required for Kadversion >= 6
1840 AddDebugLogLineM(false, logRemoteClient
, wxT("Remote Client: OP_FWCHECKUDPREQ from ") + m_client
->GetFullIP());
1841 theStats::AddDownOverheadOther(size
);
1842 CMemFile
data_in(buffer
, size
);
1843 m_client
->ProcessFirewallCheckUDPRequest(&data_in
);
1846 case OP_KAD_FWTCPCHECK_ACK
: { // Support required for Kadversion >= 7
1847 AddDebugLogLineM(false, logRemoteClient
, wxT("Remote Client: OP_KAD_FWTCPCHECK_ACK from ") + m_client
->GetFullIP());
1848 if (theApp
->clientlist
->IsKadFirewallCheckIP(m_client
->GetIP())) {
1849 if (Kademlia::CKademlia::IsRunning()) {
1850 Kademlia::CKademlia::GetPrefs()->IncFirewalled();
1853 AddDebugLogLineM(false, logListenSocket
, wxT("Received unrequested OP_KAD_FWTCPCHECK_ACK packet from ") + m_client
->GetFullIP());
1858 theStats::AddDownOverheadOther(size
);
1859 AddDebugLogLineM( false, logRemoteClient
, wxString::Format(wxT("eMule packet : unknown opcode: %i %x from "),opcode
,opcode
) + m_client
->GetFullIP());
1866 bool CClientTCPSocket::ProcessED2Kv2Packet(const byte
* buffer
, uint32 size
, uint8 opcode
)
1868 #ifdef __PACKET_RECV_DUMP__
1869 //printf("Rec: OPCODE %x ED2Kv2\n",opcode);
1870 DumpMem(buffer
,size
);
1874 throw wxString(wxT("Unknown clients sends extended ED2Kv2 protocol packet"));
1877 CMemFile
data(buffer
, size
);
1880 case OP_QUEUERANK
: {
1881 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_QUEUERANK from ") + m_client
->GetFullIP() );
1883 uint8 numtags
= data
.ReadUInt8();
1884 wxASSERT(numtags
== 1);
1886 m_client
->SetRemoteQueueRank(data
.GetIntTagValue());
1888 theStats::AddDownOverheadFileRequest(size
);
1892 case OP_REQUESTPARTS
: {
1893 AddDebugLogLineM( false, logRemoteClient
, wxT("Remote Client: ED2Kv2 OP_REQUESTPARTS from ") + m_client
->GetFullIP() );
1895 m_client
->ProcessRequestPartsPacketv2(data
);
1897 theStats::AddDownOverheadFileRequest(size
);
1902 theStats::AddDownOverheadOther(size
);
1903 AddDebugLogLineM( false, logRemoteClient
, wxString::Format(wxT("ED2Kv2 packet : unknown opcode: %i %x from "), opcode
, opcode
) + m_client
->GetFullIP());
1906 AddDebugLogLineM( false, logRemoteClient
, wxString::Format(wxT("ED2Kv2 packet is corrupt at pos %i! opcode: %i %x from "),data
.GetPosition(), opcode
, opcode
) + m_client
->GetFullIP());
1913 void CClientTCPSocket::OnConnect(int nErrorCode
)
1916 OnError(nErrorCode
);
1917 } else if (!m_client
) {
1918 // and now? Disconnect? not?
1919 AddDebugLogLineM( false, logClient
, wxT("Couldn't send hello packet (Client deleted!)") );
1920 } else if (!m_client
->SendHelloPacket()) {
1921 // and now? Disconnect? not?
1922 AddDebugLogLineM( false, logClient
, wxT("Couldn't send hello packet (Client deleted by SendHelloPacket!)") );
1924 ResetTimeOutTimer();
1929 void CClientTCPSocket::OnSend(int nErrorCode
)
1931 ResetTimeOutTimer();
1932 CEMSocket::OnSend(nErrorCode
);
1936 void CClientTCPSocket::OnReceive(int nErrorCode
)
1938 ResetTimeOutTimer();
1939 // We might have updated ipfilter
1940 wxASSERT(m_remoteip
);
1942 if (theApp
->ipfilter
->IsFiltered(m_remoteip
)) {
1944 m_client
->Safe_Delete();
1947 AddDebugLogLineM( false, logIPFilter
, wxT("A connected client was dropped by IPFilter on new packet received"));
1949 CEMSocket::OnReceive(nErrorCode
);
1954 void CClientTCPSocket::OnError(int nErrorCode
)
1956 //printf("* Called OnError for %p\n",this);
1957 // 0.42e + Kry changes for handling of socket lost events
1960 if ((nErrorCode
== 0) || (nErrorCode
== 7) || (nErrorCode
== 0xFEFF)) {
1962 if (!m_client
->GetUserName().IsEmpty()) {
1963 strError
= wxT("Client '") + m_client
->GetUserName() + wxT("'");
1965 strError
= wxT("An unnamed client");
1967 strError
+= wxT(" (IP:") + m_client
->GetFullIP() + wxT(") ");
1969 strError
= wxT("A client ");
1971 if (nErrorCode
== 0) {
1972 strError
+= wxT("closed connection.");
1973 } else if (nErrorCode
== 0xFEFF) {
1974 strError
+= wxT(" caused a wxSOCKET_LOST event.");
1976 strError
+= wxT("caused a socket blocking error.");
1979 if (theLogger
.IsEnabled(logClient
) && nErrorCode
!= 107) {
1980 // 0 -> No Error / Disconect
1981 // 107 -> Transport endpoint is not connected
1983 if (!m_client
->GetUserName().IsEmpty()) {
1984 strError
= wxT("OnError: Client '") + m_client
->GetUserName() +
1985 wxT("' (IP:") + m_client
->GetFullIP() +
1986 wxString::Format(wxT(") caused an error: %u. Disconnecting client!"), nErrorCode
);
1988 strError
= wxT("OnError: Unknown client (IP:") +
1989 m_client
->GetFullIP() +
1990 wxString::Format(wxT(") caused an error: %u. Disconnecting client!"), nErrorCode
);
1993 strError
= wxString::Format(wxT("OnError: A client caused an error or did something bad (error %u). Disconnecting client !"),
1997 strError
= wxT("Error 107 (Transport endpoint is not connected)");
2001 Disconnect(strError
);
2005 bool CClientTCPSocket::PacketReceived(CPacket
* packet
)
2008 bool bResult
= false;
2009 uint32 uRawSize
= packet
->GetPacketSize();
2011 AddDebugLogLineM( false, logRemoteClient
,
2012 CFormat(wxT("Packet with protocol %x, opcode %x, size %u received from %s"))
2013 % packet
->GetProtocol()
2014 % packet
->GetOpCode()
2015 % packet
->GetPacketSize()
2016 % ( m_client
? m_client
->GetFullIP() : wxT("Unknown Client") )
2022 bool process
= true;
2024 if ((packet
->GetProtocol() == OP_PACKEDPROT
) ||
2025 (packet
->GetProtocol() == OP_ED2KV2PACKEDPROT
)) {
2027 if (!packet
->UnPackPacket()) {
2028 AddDebugLogLineM( false, logZLib
, wxT("Failed to decompress client TCP packet."));
2032 AddDebugLogLineM(false, logRemoteClient
,
2033 wxString::Format(wxT("Packet unpacked, new protocol %x, opcode %x, size %u"),
2034 packet
->GetProtocol(),
2035 packet
->GetOpCode(),
2036 packet
->GetPacketSize())
2042 switch (packet
->GetProtocol()) {
2043 case OP_EDONKEYPROT
:
2044 bResult
= ProcessPacket(packet
->GetDataBuffer(),uRawSize
,packet
->GetOpCode());
2047 bResult
= ProcessExtPacket(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
2049 case OP_ED2KV2HEADER
:
2050 bResult
= ProcessED2Kv2Packet(packet
->GetDataBuffer(), packet
->GetPacketSize(), packet
->GetOpCode());
2052 case OP_ED2KV2PACKEDPROT
:
2054 // Packed inside packed?
2058 theStats::AddDownOverheadOther(uRawSize
);
2060 m_client
->SetDownloadState(DS_ERROR
);
2062 Disconnect(wxT("Unknown protocol"));
2067 } catch (const CEOFException
& err
) {
2068 exception
= wxT("EOF exception: ") + err
.what();
2069 } catch (const CInvalidPacket
& err
) {
2070 exception
= wxT("InvalidPacket exception: ") + err
.what();
2071 } catch (const wxString
& error
) {
2072 exception
= wxT("error: ") + (error
.IsEmpty() ? wxString(wxT("Unknown error")) : error
);
2075 if (!exception
.IsEmpty()) {
2076 AddDebugLogLineM( false, logPacketErrors
,
2077 CFormat(wxT("Caught %s\nOn packet with protocol %x, opcode %x, size %u\tClientData: %s\n"))
2079 % packet
->GetProtocol()
2080 % packet
->GetOpCode()
2081 % packet
->GetPacketSize()
2082 % ( m_client
? m_client
->GetClientFullInfo() : wxT("Unknown") )
2086 m_client
->SetDownloadState(DS_ERROR
);
2089 AddDebugLogLineM( false, logClient
,
2090 CFormat( wxT("Client '%s' (IP: %s) caused an error (%s). Disconnecting client!" ) )
2091 % ( m_client
? m_client
->GetUserName() : wxString(wxT("Unknown")) )
2092 % ( m_client
? m_client
->GetFullIP() : wxString(wxT("Unknown")) )
2096 Disconnect(wxT("Caught exception on CClientTCPSocket::ProcessPacket\n"));
2103 bool CClientTCPSocket::IsMessageFiltered(const wxString
& Message
, CUpDownClient
* client
) {
2105 bool filtered
= false;
2106 // If we're chatting to the guy, we don't want to filter!
2107 if (client
->GetChatState() != MS_CHATTING
) {
2108 if (thePrefs::MsgOnlyFriends() && !client
->IsFriend()) {
2110 } else if (thePrefs::MsgOnlySecure() && client
->GetUserName().IsEmpty() ) {
2112 } else if (thePrefs::MustFilterMessages()) {
2113 filtered
= thePrefs::IsMessageFiltered(Message
);
2119 SocketSentBytes
CClientTCPSocket::SendControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2121 SocketSentBytes returnStatus
= CEMSocket::SendControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2123 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2124 ResetTimeOutTimer();
2127 return returnStatus
;
2131 SocketSentBytes
CClientTCPSocket::SendFileAndControlData(uint32 maxNumberOfBytesToSend
, uint32 overchargeMaxBytesToSend
)
2133 SocketSentBytes returnStatus
= CEMSocket::SendFileAndControlData(maxNumberOfBytesToSend
, overchargeMaxBytesToSend
);
2135 if(returnStatus
.success
&& (returnStatus
.sentBytesControlPackets
> 0 || returnStatus
.sentBytesStandardPackets
> 0)) {
2136 ResetTimeOutTimer();
2139 return returnStatus
;
2143 void CClientTCPSocket::SendPacket(CPacket
* packet
, bool delpacket
, bool controlpacket
, uint32 actualPayloadSize
)
2145 ResetTimeOutTimer();
2146 CEMSocket::SendPacket(packet
,delpacket
,controlpacket
, actualPayloadSize
);
2148 // File_checked_for_headers