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// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26#include "ServerSocket.h" // Interface declarations 27 28#include <protocol/Protocols.h> 29#include <common/EventIDs.h> 30#include <tags/ServerTags.h> 31 32#include <wx/tokenzr.h> 33 34#include "Packet.h" // Needed for CPacket 35#include "updownclient.h" // Needed for CUpDownClient 36#include "ClientList.h" // Needed for CClientList 37#include "MemFile.h" // Needed for CMemFile 38#include "PartFile.h" // Needed for CPartFile 39#include "SearchList.h" // Needed for CSearchList 40#include "Preferences.h" // Needed for CPreferences 41#include "DownloadQueue.h" // Needed for CDownloadQueue 42#include "ServerList.h" // Needed for CServerList 43#include "Server.h" // Needed for CServer 44#include "amule.h" // Needed for theApp 45#include "Statistics.h" // Needed for theStats 46#include "AsyncDNS.h" // Needed for CAsyncDNS 47#include "Logger.h" 48#include <common/Format.h> 49#include "IPFilter.h" 50#include "GuiEvents.h" // Needed for Notify_* 51 52 53 54//------------------------------------------------------------------------------ 55// CServerSocketHandler 56//------------------------------------------------------------------------------ 57 58//------------------------------------------------------------------------------ 59// CServerSocketHandler 60//------------------------------------------------------------------------------ 61 62 63class CServerSocketHandler: public wxEvtHandler 64{ 65public: 66 CServerSocketHandler() {}; 67 68public: 69private: 70 void ServerSocketHandler(wxSocketEvent& event); 71 DECLARE_EVENT_TABLE() 72}; 73 74 75BEGIN_EVENT_TABLE(CServerSocketHandler, wxEvtHandler) 76 EVT_SOCKET(ID_SERVERSOCKET_EVENT, CServerSocketHandler::ServerSocketHandler) 77END_EVENT_TABLE() 78 79void CServerSocketHandler::ServerSocketHandler(wxSocketEvent& event) 80{ 81 CServerSocket *socket = dynamic_cast<CServerSocket *>(event.GetSocket()); 82 wxASSERT(socket); 83 if (!socket) { 84 return; 85 } 86 87 if (socket->OnDestroy()) { 88 return; 89 } 90 91 switch(event.GetSocketEvent()) { 92 case wxSOCKET_CONNECTION: 93 socket->OnConnect(wxSOCKET_NOERROR); 94 break; 95 case wxSOCKET_LOST: 96 socket->OnError(socket->LastError()); 97 break; 98 case wxSOCKET_INPUT: 99 socket->OnReceive(wxSOCKET_NOERROR); 100 break; 101 case wxSOCKET_OUTPUT: 102 socket->OnSend(wxSOCKET_NOERROR); 103 break; 104 default: 105 wxFAIL; 106 break; 107 } 108 109 110} 111 112// 113// There can be only one. :) 114// 115static CServerSocketHandler g_serverSocketHandler; 116 117 118//------------------------------------------------------------------------------ 119// CServerSocket 120//------------------------------------------------------------------------------ 121 122CServerSocket::CServerSocket(CServerConnect* in_serverconnect, const CProxyData *ProxyData) 123: 124CEMSocket(ProxyData) 125{ 126 serverconnect = in_serverconnect; 127 connectionstate = 0; 128 cur_server = 0; 129 info.Clear(); 130 m_bIsDeleting = false; 131 132 SetEventHandler(g_serverSocketHandler, ID_SERVERSOCKET_EVENT); 133 134 SetNotify( 135 wxSOCKET_CONNECTION_FLAG | 136 wxSOCKET_INPUT_FLAG | 137 wxSOCKET_OUTPUT_FLAG | 138 wxSOCKET_LOST_FLAG); 139 Notify(true); 140 141 m_dwLastTransmission = 0; 142 m_IsSolving = false; 143 m_bNoCrypt = false; 144} 145 146CServerSocket::~CServerSocket() 147{ 148 // remove event handler... 149 SetNotify(0); 150 Notify(FALSE); 151 152 if (cur_server) { 153 delete cur_server; 154 } 155 cur_server = NULL; 156} 157 158 159void CServerSocket::OnConnect(wxSocketError nErrorCode) 160{ 161 switch (nErrorCode) { 162 case wxSOCKET_NOERROR: 163 if (cur_server->HasDynIP()) { 164 amuleIPV4Address tmpaddr; 165 GetPeer(tmpaddr); 166 uint32 server_ip = StringIPtoUint32(tmpaddr.IPAddress()); 167 cur_server->SetID(server_ip); 168 // GetServerByAddress may return NULL, so we must test! 169 // This was the reason why amule would crash when trying to 170 // connect in wxWidgets 2.5.2 171 CServer *pServer = theApp->serverlist->GetServerByAddress( 172 cur_server->GetAddress(), cur_server->GetPort()); 173 if (pServer) { 174 pServer->SetID(server_ip); 175 } else { 176 AddDebugLogLineN(logServer, wxT("theApp->serverlist->GetServerByAddress() returned NULL")); 177 return; 178 } 179 } 180 SetConnectionState(CS_WAITFORLOGIN); 181 break; 182 183 case wxSOCKET_INVADDR: 184 case wxSOCKET_NOHOST: 185 case wxSOCKET_INVPORT: 186 case wxSOCKET_TIMEDOUT: 187 m_bIsDeleting = true; 188 SetConnectionState(CS_SERVERDEAD); 189 serverconnect->DestroySocket(this); 190 return; 191 192 case wxSOCKET_IOERR: 193 case wxSOCKET_MEMERR: 194 case wxSOCKET_INVOP: 195 default: 196 m_bIsDeleting = true; 197 SetConnectionState(CS_FATALERROR); 198 serverconnect->DestroySocket(this); 199 return; 200 201 } 202 203} 204 205void CServerSocket::OnReceive(wxSocketError nErrorCode) 206{ 207 if (connectionstate != CS_CONNECTED && !serverconnect->IsConnecting()) { 208 serverconnect->DestroySocket(this); 209 return; 210 } 211 CEMSocket::OnReceive((int)nErrorCode); 212 m_dwLastTransmission = GetTickCount(); 213} 214 215bool CServerSocket::ProcessPacket(const byte* packet, uint32 size, int8 opcode) 216{ 217 try { 218 AddDebugLogLineN( logServer, wxT("Processing Server Packet: ") ); 219 220 switch(opcode) { 221 case OP_SERVERMESSAGE: { 222 /* Kry import of lugdunum 16.40 new features */ 223 AddDebugLogLineN( logServer, wxT("Server: OP_SERVERMESSAGE") ); 224 225 theStats::AddDownOverheadServer(size); 226 char* buffer = new char[size-1]; 227 memcpy(buffer,&packet[2],size-2); 228 buffer[size-2] = 0; 229 230 wxString strMessages(char2unicode(buffer)); 231 232 delete[] buffer; 233 234 // 16.40 servers do not send separate OP_SERVERMESSAGE packets for each line; 235 // instead of this they are sending all text lines with one OP_SERVERMESSAGE packet. 236 237 wxStringTokenizer token(strMessages,wxT("\r\n"),wxTOKEN_DEFAULT ); 238 239 while (token.HasMoreTokens()) { 240 wxString message = token.GetNextToken(); 241 242 bool bOutputMessage = true; 243 if (message.StartsWith(wxT("server version"))) { 244 wxString strVer = message.Mid(15,64); // truncate string to avoid misuse by servers in showing ads 245 strVer.Trim(); 246 CServer* eserver = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); 247 if (eserver) { 248 eserver->SetVersion(strVer); 249 Notify_ServerRefresh(eserver); 250 } 251 } else if (message.StartsWith(wxT("ERROR"))) { 252 CServer* pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); 253 wxString servername; 254 if (pServer) { 255 servername = pServer->GetListName(); 256 } else { 257 servername = _("Server"); 258 } 259 AddLogLineN(CFormat( _("ERROR: %s (%s) - %s") ) 260 % servername 261 % Uint32_16toStringIP_Port(cur_server->GetIP(), cur_server->GetPort()) 262 % message.Mid(5,message.Len()).Trim(wxT(" :"))); 263 bOutputMessage = false; 264 265 } else if (message.StartsWith(wxT("WARNING"))) { 266 267 CServer* pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); 268 wxString servername; 269 if (pServer) { 270 servername = pServer->GetListName(); 271 } else { 272 servername = _("Server"); 273 } 274 AddLogLineN(CFormat( _("WARNING: %s (%s) - %s") ) 275 % servername 276 % Uint32_16toStringIP_Port(cur_server->GetIP(), cur_server->GetPort()) 277 % message.Mid(5,message.Len()).Trim(wxT(" :"))); 278 279 bOutputMessage = false; 280 } 281 282 if (message.Find(wxT("[emDynIP: ")) != (-1) && message.Find(wxT("]")) != (-1) && message.Find(wxT("[emDynIP: ")) < message.Find(wxT("]"))){ 283 wxString dynip = message.Mid(message.Find(wxT("[emDynIP: "))+10,message.Find(wxT("]")) - (message.Find(wxT("[emDynIP: "))+10)); 284 dynip.Trim(wxT(" ")); 285 if ( dynip.Length() && dynip.Length() < 51){ 286 CServer* eserver = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); 287 if (eserver){ 288 eserver->SetDynIP(dynip); 289 cur_server->SetDynIP(dynip); 290 Notify_ServerRefresh(eserver); 291 } 292 } 293 } 294 295 if (bOutputMessage) { 296 theApp->AddServerMessageLine(message); 297 } 298 } 299 break; 300 } 301 case OP_IDCHANGE: { 302 AddDebugLogLineN(logServer, wxT("Server: OP_IDCHANGE")); 303 304 theStats::AddDownOverheadServer(size); 305 306 if (size < 4 /* uint32 (ID)*/) { 307 throw wxString(wxT("Corrupt or invalid loginanswer from server received")); 308 } 309 310 CMemFile data(packet, size); 311 312 uint32 new_id = data.ReadUInt32(); 313 314 // save TCP flags in 'cur_server' 315 wxASSERT(cur_server); 316 uint32 ConnPort = 0; 317 CServer* pServer = NULL; 318 if (cur_server) { 319 uint32 rport = cur_server->GetConnPort(); 320 pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(), rport); 321 if (size >= 4+4 /* uint32 (ID) + uint32 (TCP flags)*/) { 322 cur_server->SetTCPFlags(data.ReadUInt32()); 323 if (size >= 4+4+4 /* uint32 (ID) + uint32 (TCP flags) + uint32 (aux port) */) { 324 // aux port login : we should use the 'standard' port of this server to advertize to other clients 325 ConnPort = data.ReadUInt32(); 326 cur_server->SetPort(ConnPort); 327 if (cur_server->GetAuxPortsList().IsEmpty()) { 328 cur_server->SetAuxPortsList(CFormat(wxT("%u")) % rport); 329 } 330 } 331 } else { 332 cur_server->SetTCPFlags(0); 333 } 334 // copy TCP flags into the server in the server list 335 if (pServer) { 336 pServer->SetTCPFlags(cur_server->GetTCPFlags()); 337 if (ConnPort) { 338 pServer->SetPort(ConnPort); 339 if (pServer->GetAuxPortsList().IsEmpty()) { 340 pServer->SetAuxPortsList(CFormat(wxT("%u")) % pServer->GetConnPort()); 341 } 342 Notify_ServerRefresh(pServer); 343 Notify_ServerUpdateED2KInfo(); 344 } 345 } 346 } 347 348 uint32 dwServerReportedIP = 0; 349 uint32 dwObfuscationTCPPort = 0; 350 if (size >= 4 + 4 + 4 + 4 + 4 /* All of the above + reported ip + obfuscation port */) { 351 dwServerReportedIP = data.ReadUInt32(); 352 if (::IsLowID(dwServerReportedIP)){ 353 wxFAIL; 354 dwServerReportedIP = 0; 355 } 356 wxASSERT( dwServerReportedIP == new_id || ::IsLowID(new_id) ); 357 dwObfuscationTCPPort = data.ReadUInt32(); 358 if (cur_server != NULL && dwObfuscationTCPPort != 0) { 359 cur_server->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort); 360 } 361 362 if (pServer != NULL && dwObfuscationTCPPort != 0) { 363 pServer->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort); 364 } 365 } 366 367 if (new_id == 0) { 368 uint8 state = thePrefs::GetSmartIdState(); 369 if ( state > 0 ) { 370 state++; 371 if(state > 3) { 372 thePrefs::SetSmartIdState(0); 373 } else { 374 thePrefs::SetSmartIdState(state); 375 } 376 } 377 break; 378 } 379 if(thePrefs::GetSmartIdCheck()) { 380 if (!IsLowID(new_id)) { 381 thePrefs::SetSmartIdState(1); 382 } else { 383 uint8 state = thePrefs::GetSmartIdState(); 384 if ( state > 0 ) { 385 state++; 386 if(state > 3) { 387 thePrefs::SetSmartIdState(0); 388 } else { 389 thePrefs::SetSmartIdState(state); 390 } 391 break; 392 } 393 } 394 } 395 396 // we need to know our client when sending our shared files (done indirectly on SetConnectionState) 397 398 serverconnect->SetClientID(new_id); 399 400 if (::IsLowID(new_id) && dwServerReportedIP != 0) { 401 theApp->SetPublicIP(dwServerReportedIP); 402 } 403 404 if (connectionstate != CS_CONNECTED) { 405 AddDebugLogLineN(logServer, wxT("Connected")); 406 407 SetConnectionState(CS_CONNECTED); 408 theApp->OnlineSig(); // Added By Bouc7 409 } 410 411 theApp->ShowConnectionState(); 412 413 AddLogLineN(CFormat(_("New clientid is %u")) % new_id); 414 if (::IsLowID(new_id)) { 415 AddLogLineC(_("WARNING: You have received Low-ID!")); 416 AddLogLineN(_("\tMost likely this is because you're behind a firewall or router.")); 417 AddLogLineN(_("\tFor more information, please refer to http://wiki.amule.org")); 418 } 419 420 theApp->downloadqueue->ResetLocalServerRequests(); 421 break; 422 } 423 case OP_SEARCHRESULT: { 424 AddDebugLogLineN(logServer, wxT("Server: OP_SEARCHRESULT")); 425 426 theStats::AddDownOverheadServer(size); 427 CServer* cur_srv = (serverconnect) ? 428 serverconnect->GetCurrentServer() : NULL; 429 theApp->searchlist->ProcessSearchAnswer( 430 packet, 431 size, 432 true /*(cur_srv && cur_srv->GetUnicodeSupport())*/, 433 cur_srv ? cur_srv->GetIP() : 0, 434 cur_srv ? cur_srv->GetPort() : 0); 435 theApp->searchlist->LocalSearchEnd(); 436 break; 437 } 438 case OP_FOUNDSOURCES_OBFU: 439 case OP_FOUNDSOURCES: { 440 AddDebugLogLineN(logServer, CFormat(wxT("ServerMsg - OP_FoundSources; sources = %u")) % packet[16]); 441 theStats::AddDownOverheadServer(size); 442 CMemFile sources(packet,size); 443 CMD4Hash fileid = sources.ReadHash(); 444 if (CPartFile* file = theApp->downloadqueue->GetFileByID(fileid)) { 445 file->AddSources(sources, cur_server->GetIP(), cur_server->GetPort(), SF_LOCAL_SERVER, (opcode == OP_FOUNDSOURCES_OBFU)); 446 } else { 447 AddDebugLogLineN(logServer, wxT("Sources received for unknown file: ") + fileid.Encode()); 448 } 449 break; 450 } 451 case OP_SERVERSTATUS: { 452 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERSTATUS")); 453 // FIXME some statuspackets have a different size -> why? structur? 454 if (size < 8) { 455 throw wxString(wxT("Invalid server status packet")); 456 break; 457 } 458 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort()); 459 if (update) { 460 CMemFile data(packet, size); 461 update->SetUserCount(data.ReadUInt32()); 462 update->SetFileCount(data.ReadUInt32()); 463 Notify_ServerRefresh( update ); 464 theApp->ShowUserCount(); 465 } 466 break; 467 } 468 // Cleaned. 469 case OP_SERVERIDENT: { 470 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERIDENT")); 471 472 theStats::AddDownOverheadServer(size); 473 if (size<38) { 474 AddLogLineN(_("Unknown server info received! - too short")); 475 // throw wxString(wxT("Unknown server info received!")); 476 break; 477 } 478 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); 479 if (update) { 480 CMemFile data(packet,size); 481 CMD4Hash hash = data.ReadHash(); 482 if (RawPeekUInt32(hash.GetHash()) == 0x2A2A2A2A){ // No endian problem here 483 const wxString& rstrVersion = update->GetVersion(); 484 if (!rstrVersion.IsEmpty()) { 485 update->SetVersion(wxT("eFarm ") + rstrVersion); 486 } else { 487 update->SetVersion(wxT("eFarm")); 488 } 489 } 490 // Unused 491 /*uint32 nServerIP = */data.ReadUInt32(); 492 /*uint16 nServerPort = */data.ReadUInt16(); 493 494 uint32 nTags = data.ReadUInt32(); 495 for (uint32 i = 0; i < nTags; i++){ 496 CTag tag(data, update->GetUnicodeSupport()); 497 if (tag.GetNameID() == ST_SERVERNAME){ 498 update->SetListName(tag.GetStr()); 499 } else if (tag.GetNameID() == ST_DESCRIPTION){ 500 update->SetDescription(tag.GetStr()); 501 } // No more known tags from server 502 } 503 504 theApp->ShowConnectionState(); 505 Notify_ServerRefresh(update); 506 } 507 break; 508 } 509 // tecxx 1609 2002 - add server's serverlist to own serverlist 510 case OP_SERVERLIST: { 511 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERLIST")); 512 513 CMemFile* servers = new CMemFile(packet,size); 514 uint8 count = servers->ReadUInt8(); 515 if (((int32)(count*6 + 1) > size)) { 516 count = 0; 517 } 518 int addcount = 0; 519 while(count) { 520 uint32 ip = servers->ReadUInt32(); 521 uint16 port = servers->ReadUInt16(); 522 CServer* srv = new CServer( 523 port , // Port 524 Uint32toStringIP(ip)); // Ip 525 srv->SetListName(srv->GetFullIP()); 526 if (!theApp->AddServer(srv)) { 527 delete srv; 528 } else { 529 addcount++; 530 } 531 count--; 532 } 533 delete servers; 534 if (addcount) { 535 AddLogLineN(CFormat(wxPLURAL("Received %d new server", "Received %d new servers", addcount)) % addcount); 536 } 537 theApp->serverlist->SaveServerMet(); 538 AddLogLineN(_("Saving of server-list completed.")); 539 break; 540 } 541 case OP_CALLBACKREQUESTED: { 542 AddDebugLogLineN(logServer, wxT("Server: OP_CALLBACKREQUESTED")); 543 544 theStats::AddDownOverheadServer(size); 545 if (size >= 6) { 546 CMemFile data(packet,size); 547 uint32 dwIP = data.ReadUInt32(); 548 uint16 nPort = data.ReadUInt16(); 549 550 uint8 byCryptOptions = 0; 551 CMD4Hash achUserHash; 552 if (size >= 23){ 553 byCryptOptions = data.ReadUInt8();; 554 achUserHash = data.ReadHash(); 555 } 556 557 CUpDownClient* client = theApp->clientlist->FindClientByIP(dwIP,nPort); 558 559 if (!client) { 560 client = new CUpDownClient(nPort,dwIP,0,0,0, true, true); 561 theApp->clientlist->AddClient(client); 562 } 563 if (size >= 23 && client->HasValidHash()){ 564 if (client->GetUserHash() != achUserHash){ 565 AddDebugLogLineN(logServer, wxT("Reported Userhash from OP_CALLBACKREQUESTED differs with our stored hash")); 566 // disable crypt support since we dont know which hash is true 567 client->SetCryptLayerRequest(false); 568 client->SetCryptLayerSupport(false); 569 client->SetCryptLayerRequires(false); 570 } else { 571 client->SetConnectOptions(byCryptOptions, true, false); 572 } 573 } else if (size >= 23) { 574 client->SetUserHash(achUserHash); 575 client->SetConnectOptions(byCryptOptions, true, false); 576 } 577 578 client->TryToConnect(); 579 } 580 break; 581 } 582 case OP_CALLBACK_FAIL: { 583 AddDebugLogLineN(logServer, wxT("Server: OP_CALLBACK_FAIL")); 584 break; 585 } 586 case OP_REJECT: { 587 AddDebugLogLineN(logServer, wxT("Server: OP_REJECT")); 588 AddLogLineN(_("Server rejected last command")); 589 break; 590 } 591 default: 592 AddDebugLogLineN(logPacketErrors, CFormat(wxT("Unknown server packet with OPcode %x")) % opcode); 593 } 594 return true; 595 } catch (const CInvalidPacket& e) { 596 AddLogLineN(CFormat( _("Bogus packet received from server: %s") ) % e.what()); 597 } catch (const CEOFException& e) { 598 AddLogLineN(CFormat( _("Bogus packet received from server: %s") ) % e.what()); 599 } catch (const wxString& error) { 600 AddLogLineN(CFormat( _("Unhandled error while processing packet from server: %s") ) % error); 601 } 602 603 // Don't disconnect because of wrong sources. 604 if (opcode==OP_SEARCHRESULT || opcode==OP_FOUNDSOURCES) { 605 return true; 606 } 607 608 SetConnectionState(CS_DISCONNECTED); 609 return false; 610} 611 612void CServerSocket::ConnectToServer(CServer* server, bool bNoCrypt) 613{ 614 AddDebugLogLineN(logServer, wxT("Trying to connect")); 615 616 if (cur_server){ 617 wxFAIL; 618 delete cur_server; 619 cur_server = NULL; 620 } 621 622 cur_server = new CServer(server); 623 624 m_bNoCrypt = bNoCrypt; 625 626 SetConnectionState(CS_CONNECTING); 627 628 info = cur_server->GetListName(); 629 630 // This must be used if we want to reverse-check the addr of the server 631 if (cur_server->HasDynIP() || !cur_server->GetIP()) { 632 m_IsSolving = true; 633 // Send it to solving thread. 634 CAsyncDNS* dns = new CAsyncDNS(server->GetAddress(), DNS_SERVER_CONNECT, theApp, this); 635 636 if ( dns->Create() == wxTHREAD_NO_ERROR ) { 637 if ( dns->Run() != wxTHREAD_NO_ERROR ) { 638 dns->Delete(); 639 AddLogLineN(CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress()); 640 } 641 } else { 642 dns->Delete(); 643 AddLogLineN(CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress()); 644 } 645 } else { 646 // Nothing to solve, we already have the IP 647 OnHostnameResolved(cur_server->GetIP()); 648 } 649 650} 651 652void CServerSocket::OnError(wxSocketError DEBUG_ONLY(nErrorCode)) 653{ 654 AddDebugLogLineN(logServer, CFormat(wxT("Error in serversocket: %s(%s:%i): %u")) 655 % cur_server->GetListName() % cur_server->GetFullIP() % cur_server->GetPort() % (int)nErrorCode); 656 SetConnectionState(CS_DISCONNECTED); 657} 658 659 660bool CServerSocket::PacketReceived(CPacket* packet) 661{ 662 AddDebugLogLineN(logServer, CFormat(wxT("Server: Packet Received: Prot %x, Opcode %x, Length %u")) % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize()); 663 664 if (packet->GetProtocol() == OP_PACKEDPROT) { 665 if (!packet->UnPackPacket(250000)){ 666 AddDebugLogLineN(logZLib, CFormat(wxT("Failed to decompress server TCP packet: protocol=0x%02x opcode=0x%02x size=%u")) 667 % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize()); 668 theStats::AddDownOverheadServer(packet->GetPacketSize()); 669 return true; 670 } 671 672 packet->SetProtocol(OP_EDONKEYPROT); 673 } 674 675 if (packet->GetProtocol() == OP_EDONKEYPROT) { 676 ProcessPacket(packet->GetDataBuffer(), packet->GetPacketSize(), packet->GetOpCode()); 677 } else { 678 AddDebugLogLineN(logServer, CFormat(wxT("Received server TCP packet with unknown protocol: protocol=0x%02x opcode=0x%02x size=%u")) 679 % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize()); 680 theStats::AddDownOverheadServer(packet->GetPacketSize()); 681 } 682 683 return true; 684} 685 686 687void CServerSocket::OnClose(wxSocketError WXUNUSED(nErrorCode)) 688{ 689 CEMSocket::OnClose(0); 690 691 switch (connectionstate) { 692 case CS_WAITFORLOGIN: SetConnectionState(CS_SERVERFULL); break; 693 case CS_CONNECTED: SetConnectionState(CS_DISCONNECTED); break; 694 default: SetConnectionState(CS_NOTCONNECTED); 695 } 696 697 serverconnect->DestroySocket(this); 698} 699 700void CServerSocket::SetConnectionState(sint8 newstate) 701{ 702 connectionstate = newstate; 703 if (newstate < CS_CONNECTING) { 704 serverconnect->ConnectionFailed(this); 705 } else if (newstate == CS_CONNECTED || newstate == CS_WAITFORLOGIN) { 706 if (serverconnect) { 707 serverconnect->ConnectionEstablished(this); 708 } 709 } 710} 711 712 713void CServerSocket::SendPacket(CPacket* packet, bool delpacket, bool controlpacket, uint32 actualPayloadSize) 714{ 715 m_dwLastTransmission = GetTickCount(); 716 CEMSocket::SendPacket(packet, delpacket, controlpacket, actualPayloadSize); 717} 718 719 720void CServerSocket::OnHostnameResolved(uint32 ip) { 721 722 m_IsSolving = false; 723 if (ip) { 724 if (theApp->ipfilter->IsFiltered(ip, true)) { 725 AddLogLineC(CFormat( _("Server IP %s (%s) is filtered. Not connecting.") ) 726 % Uint32toStringIP(ip) % cur_server->GetAddress() ); 727 OnConnect(wxSOCKET_INVADDR); 728 } else { 729 amuleIPV4Address addr; 730 addr.Hostname(ip); 731 uint16 nPort = 0; 732 wxString useObfuscation; 733 if ( !m_bNoCrypt && thePrefs::IsServerCryptLayerTCPRequested() && cur_server->GetObfuscationPortTCP() != 0 && cur_server->SupportsObfuscationTCP()){ 734 nPort = cur_server->GetObfuscationPortTCP(); 735 useObfuscation = _("using protocol obfuscation."); 736 SetConnectionEncryption(true, NULL, true); 737 } else { 738 nPort = cur_server->GetConnPort(); 739 SetConnectionEncryption(false, NULL, true); 740 } 741 742 addr.Service(nPort); 743 744 AddLogLineN(CFormat( _("Connecting to %s (%s - %s:%i) %s") ) 745 % cur_server->GetListName() 746 % cur_server->GetAddress() 747 % cur_server->GetFullIP() 748 % nPort 749 % useObfuscation 750 ); 751 752 AddDebugLogLineN(logServer, CFormat(wxT("Server %s(%s) Port %i")) 753 % cur_server->GetAddress() % Uint32toStringIP(ip) % cur_server->GetConnPort()); 754 Connect(addr, false); 755 } 756 } else { 757 AddLogLineC(CFormat( _("Could not solve dns for server %s: Unable to connect!") ) 758 % cur_server->GetAddress() ); 759 OnConnect(wxSOCKET_NOHOST); 760 } 761 762} 763uint32 CServerSocket::GetServerIP() const 764{ 765 return cur_server ? cur_server->GetIP() : 0; 766} 767// File_checked_for_headers 768