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