Upstream tarball 20080414
[amule.git] / src / ServerSocket.cpp
blob546f68ee9b0889673bd2929ddb8136deadcae434
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002 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.
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.
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
26 #include "ServerSocket.h" // Interface declarations
28 #include <protocol/Protocols.h>
29 #include <common/EventIDs.h>
30 #include <tags/ServerTags.h>
32 #include <wx/tokenzr.h>
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_*
54 //------------------------------------------------------------------------------
55 // CServerSocketHandler
56 //------------------------------------------------------------------------------
58 //------------------------------------------------------------------------------
59 // CServerSocketHandler
60 //------------------------------------------------------------------------------
63 class CServerSocketHandler: public wxEvtHandler
65 public:
66 CServerSocketHandler() {};
68 public:
69 private:
70 void ServerSocketHandler(wxSocketEvent& event);
71 DECLARE_EVENT_TABLE()
75 BEGIN_EVENT_TABLE(CServerSocketHandler, wxEvtHandler)
76 EVT_SOCKET(ID_SERVERSOCKET_EVENT, CServerSocketHandler::ServerSocketHandler)
77 END_EVENT_TABLE()
79 void CServerSocketHandler::ServerSocketHandler(wxSocketEvent& event)
81 CServerSocket *socket = dynamic_cast<CServerSocket *>(event.GetSocket());
82 wxASSERT(socket);
83 if (!socket) {
84 return;
87 if (socket->OnDestroy()) {
88 return;
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 wxASSERT(0);
106 break;
113 // There can be only one. :)
115 static CServerSocketHandler g_serverSocketHandler;
118 //------------------------------------------------------------------------------
119 // CServerSocket
120 //------------------------------------------------------------------------------
122 CServerSocket::CServerSocket(CServerConnect* in_serverconnect, const CProxyData *ProxyData)
124 CEMSocket(ProxyData)
126 serverconnect = in_serverconnect;
127 connectionstate = 0;
128 cur_server = 0;
129 info.Clear();
130 m_bIsDeleting = false;
132 SetEventHandler(g_serverSocketHandler, ID_SERVERSOCKET_EVENT);
134 SetNotify(
135 wxSOCKET_CONNECTION_FLAG |
136 wxSOCKET_INPUT_FLAG |
137 wxSOCKET_OUTPUT_FLAG |
138 wxSOCKET_LOST_FLAG);
139 Notify(true);
141 m_dwLastTransmission = 0;
142 m_IsSolving = false;
143 m_bNoCrypt = false;
146 CServerSocket::~CServerSocket()
148 // remove event handler...
149 SetNotify(0);
150 Notify(FALSE);
152 if (cur_server) {
153 delete cur_server;
155 cur_server = NULL;
159 void CServerSocket::OnConnect(wxSocketError nErrorCode)
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 AddLogLineM(false,_("theApp->serverlist->GetServerByAddress() returned NULL"));
177 return;
180 SetConnectionState(CS_WAITFORLOGIN);
181 break;
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;
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;
205 void CServerSocket::OnReceive(wxSocketError nErrorCode)
207 if (connectionstate != CS_CONNECTED && !serverconnect->IsConnecting()) {
208 serverconnect->DestroySocket(this);
209 return;
211 CEMSocket::OnReceive((int)nErrorCode);
212 m_dwLastTransmission = GetTickCount();
215 bool CServerSocket::ProcessPacket(const byte* packet, uint32 size, int8 opcode)
217 try {
218 AddDebugLogLineM( false, logServer, wxT("Processing Server Packet: ") );
220 switch(opcode) {
221 case OP_SERVERMESSAGE: {
222 /* Kry import of lugdunum 16.40 new features */
223 AddDebugLogLineM( false, logServer, wxT("Server: OP_SERVERMESSAGE") );
225 theStats::AddDownOverheadServer(size);
226 char* buffer = new char[size-1];
227 memcpy(buffer,&packet[2],size-2);
228 buffer[size-2] = 0;
230 wxString strMessages(char2unicode(buffer));
232 delete[] buffer;
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.
237 wxStringTokenizer token(strMessages,wxT("\r\n"),wxTOKEN_DEFAULT );
239 while (token.HasMoreTokens()) {
240 wxString message = token.GetNextToken();
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);
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");
259 AddLogLineM(false, 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;
265 } else if (message.StartsWith(wxT("WARNING"))) {
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");
274 AddLogLineM(false, 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(" :")));
279 bOutputMessage = false;
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);
295 if (bOutputMessage) {
296 theApp->AddServerMessageLine(message);
299 break;
301 case OP_IDCHANGE: {
302 AddDebugLogLineM(false,logServer,wxT("Server: OP_IDCHANGE"));
304 theStats::AddDownOverheadServer(size);
306 if (size < 4 /* uint32 (ID)*/) {
307 throw wxString(wxT("Corrupt or invalid loginanswer from server received"));
310 CMemFile data(packet, size);
312 uint32 new_id = data.ReadUInt32();
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(wxString::Format(wxT("%u"), rport));
329 // } else {
330 // cur_server->SetAuxPortsList(wxString::Format(wxT("%u"), rport) + wxT(",") + cur_server->GetAuxPortsList());
333 } else {
334 cur_server->SetTCPFlags(0);
336 // copy TCP flags into the server in the server list
337 if (pServer) {
338 pServer->SetTCPFlags(cur_server->GetTCPFlags());
339 if (ConnPort) {
340 pServer->SetPort(ConnPort);
341 if (pServer->GetAuxPortsList().IsEmpty()) {
342 pServer->SetAuxPortsList(wxString::Format(wxT("%u"), pServer->GetConnPort()));
343 // } else {
344 // pServer->SetAuxPortsList(wxString::Format(wxT("%u"), pServer->GetConnPort()) + wxT(",") + pServer->GetAuxPortsList());
346 Notify_ServerRefresh(pServer);
347 Notify_ServerUpdateED2KInfo();
352 uint32 dwServerReportedIP = 0;
353 uint32 dwObfuscationTCPPort = 0;
354 if (size >= 4 + 4 + 4 + 4 + 4 /* All of the above + reported ip + obfuscation port */) {
355 dwServerReportedIP = data.ReadUInt32();
356 if (::IsLowID(dwServerReportedIP)){
357 wxASSERT( false );
358 dwServerReportedIP = 0;
360 wxASSERT( dwServerReportedIP == new_id || ::IsLowID(new_id) );
361 dwObfuscationTCPPort = data.ReadUInt32();
362 if (cur_server != NULL && dwObfuscationTCPPort != 0) {
363 cur_server->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort);
366 if (pServer != NULL && dwObfuscationTCPPort != 0) {
367 pServer->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort);
371 if (new_id == 0) {
372 uint8 state = thePrefs::GetSmartIdState();
373 if ( state > 0 ) {
374 state++;
375 if(state > 3) {
376 thePrefs::SetSmartIdState(0);
377 } else {
378 thePrefs::SetSmartIdState(state);
381 break;
383 if(thePrefs::GetSmartIdCheck()) {
384 if (!IsLowID(new_id)) {
385 thePrefs::SetSmartIdState(1);
386 } else {
387 uint8 state = thePrefs::GetSmartIdState();
388 if ( state > 0 ) {
389 state++;
390 if(state > 3) {
391 thePrefs::SetSmartIdState(0);
392 } else {
393 thePrefs::SetSmartIdState(state);
395 break;
400 // we need to know our client when sending our shared files (done indirectly on SetConnectionState)
402 serverconnect->SetClientID(new_id);
404 if (::IsLowID(new_id) && dwServerReportedIP != 0) {
405 theApp->SetPublicIP(dwServerReportedIP);
408 if (connectionstate != CS_CONNECTED) {
409 AddDebugLogLineM(true,logServer,wxT("Connected"));
411 SetConnectionState(CS_CONNECTED);
412 theApp->OnlineSig(); // Added By Bouc7
415 theApp->ShowConnectionState();
417 AddLogLineM(false, wxString::Format(_("New clientid is %u"),new_id));
418 if (::IsLowID(new_id)) {
419 AddLogLineM(true, _("WARNING: You have received Low-ID!"));
420 AddLogLineM(false, _("\tMost likely this is because you're behind a firewall or router."));
421 AddLogLineM(false, _("\tFor more information, please refer to http://wiki.amule.org"));
424 theApp->downloadqueue->ResetLocalServerRequests();
425 break;
427 case OP_SEARCHRESULT: {
428 AddDebugLogLineM(false,logServer,wxT("Server: OP_SEARCHRESULT"));
430 theStats::AddDownOverheadServer(size);
431 CServer* cur_srv = (serverconnect) ?
432 serverconnect->GetCurrentServer() : NULL;
433 theApp->searchlist->ProcessSearchAnswer(
434 packet,
435 size,
436 true /*(cur_srv && cur_srv->GetUnicodeSupport())*/,
437 cur_srv ? cur_srv->GetIP() : 0,
438 cur_srv ? cur_srv->GetPort() : 0);
439 theApp->searchlist->LocalSearchEnd();
440 break;
442 case OP_FOUNDSOURCES_OBFU:
443 case OP_FOUNDSOURCES: {
444 AddDebugLogLineM(false,logServer,wxString::Format(wxT("ServerMsg - OP_FoundSources; sources = %u"), (uint32)(byte)packet[16]));
445 theStats::AddDownOverheadServer(size);
446 CMemFile sources(packet,size);
447 CMD4Hash fileid = sources.ReadHash();
448 if (CPartFile* file = theApp->downloadqueue->GetFileByID(fileid)) {
449 file->AddSources(sources, cur_server->GetIP(), cur_server->GetPort(), SF_LOCAL_SERVER, (opcode == OP_FOUNDSOURCES_OBFU));
450 } else {
451 AddDebugLogLineM(true, logServer, wxT("Sources received for unknown file: ") + fileid.Encode());
453 break;
455 case OP_SERVERSTATUS: {
456 AddDebugLogLineM(false,logServer,wxT("Server: OP_SERVERSTATUS"));
457 // FIXME some statuspackets have a different size -> why? structur?
458 if (size < 8) {
459 throw wxString(wxT("Invalid server status packet"));
460 break;
462 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort());
463 if (update) {
464 CMemFile data(packet, size);
465 update->SetUserCount(data.ReadUInt32());
466 update->SetFileCount(data.ReadUInt32());
467 Notify_ServerRefresh( update );
468 theApp->ShowUserCount();
470 break;
472 // Cleaned.
473 case OP_SERVERIDENT: {
474 AddDebugLogLineM(false,logServer,wxT("Server: OP_SERVERIDENT"));
476 theStats::AddDownOverheadServer(size);
477 if (size<38) {
478 AddLogLineM(false, _("Unknown server info received! - too short"));
479 // throw wxString(wxT("Unknown server info received!"));
480 break;
482 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
483 if (update) {
484 CMemFile data(packet,size);
485 CMD4Hash hash = data.ReadHash();
486 if (RawPeekUInt32(hash.GetHash()) == 0x2A2A2A2A){ // No endian problem here
487 const wxString& rstrVersion = update->GetVersion();
488 if (!rstrVersion.IsEmpty()) {
489 update->SetVersion(wxT("eFarm ") + rstrVersion);
490 } else {
491 update->SetVersion(wxT("eFarm"));
494 // Unused
495 /*uint32 nServerIP = */data.ReadUInt32();
496 /*uint16 nServerPort = */data.ReadUInt16();
498 uint32 nTags = data.ReadUInt32();
499 for (uint32 i = 0; i < nTags; i++){
500 CTag tag(data, update->GetUnicodeSupport());
501 if (tag.GetNameID() == ST_SERVERNAME){
502 update->SetListName(tag.GetStr());
503 } else if (tag.GetNameID() == ST_DESCRIPTION){
504 update->SetDescription(tag.GetStr());
505 } // No more known tags from server
508 theApp->ShowConnectionState();
509 Notify_ServerRefresh(update);
511 break;
513 // tecxx 1609 2002 - add server's serverlist to own serverlist
514 case OP_SERVERLIST: {
515 AddDebugLogLineM(false,logServer,wxT("Server: OP_SERVERLIST"));
517 CMemFile* servers = new CMemFile(packet,size);
518 uint8 count = servers->ReadUInt8();
519 if (((int32)(count*6 + 1) > size)) {
520 count = 0;
522 int addcount = 0;
523 while(count) {
524 uint32 ip = servers->ReadUInt32();
525 uint16 port = servers->ReadUInt16();
526 CServer* srv = new CServer(
527 port , // Port
528 Uint32toStringIP(ip)); // Ip
529 srv->SetListName(srv->GetFullIP());
530 if (!theApp->AddServer(srv)) {
531 delete srv;
532 } else {
533 addcount++;
535 count--;
537 delete servers;
538 if (addcount) {
539 AddLogLineM(false, wxString::Format(wxPLURAL("Received %d new server", "Received %d new servers", addcount), addcount));
541 theApp->serverlist->SaveServerMet();
542 AddLogLineM(false, _("Saving of server-list completed."));
543 break;
545 case OP_CALLBACKREQUESTED: {
546 AddDebugLogLineM(false,logServer,wxT("Server: OP_CALLBACKREQUESTED"));
548 theStats::AddDownOverheadServer(size);
549 if (size == 6) {
550 CMemFile data(packet,size);
551 uint32 dwIP = data.ReadUInt32();
552 uint16 nPort = data.ReadUInt16();
554 uint8 byCryptOptions = 0;
555 CMD4Hash achUserHash;
556 if (size >= 23){
557 byCryptOptions = data.ReadUInt8();;
558 achUserHash = data.ReadHash();
561 CUpDownClient* client = theApp->clientlist->FindClientByIP(dwIP,nPort);
562 if (size >= 23 && client->HasValidHash()){
563 if (client->GetUserHash() != achUserHash){
564 AddDebugLogLineM(false, logServer, wxT("Reported Userhash from OP_CALLBACKREQUESTED differs with our stored hash"));
565 // disable crypt support since we dont know which hash is true
566 client->SetCryptLayerRequest(false);
567 client->SetCryptLayerSupport(false);
568 client->SetCryptLayerRequires(false);
569 } else {
570 client->SetCryptLayerSupport((byCryptOptions & 0x01) != 0);
571 client->SetCryptLayerRequest((byCryptOptions & 0x02) != 0);
572 client->SetCryptLayerRequires((byCryptOptions & 0x04) != 0);
574 } else if (size >= 23) {
575 client->SetUserHash(achUserHash);
576 client->SetCryptLayerSupport((byCryptOptions & 0x01) != 0);
577 client->SetCryptLayerRequest((byCryptOptions & 0x02) != 0);
578 client->SetCryptLayerRequires((byCryptOptions & 0x04) != 0);
581 if (client) {
582 client->TryToConnect();
583 } else {
584 client = new CUpDownClient(nPort,dwIP,0,0,0, true, true);
585 theApp->clientlist->AddClient(client);
586 client->TryToConnect();
589 break;
591 case OP_CALLBACK_FAIL: {
592 AddDebugLogLineM(false,logServer,wxT("Server: OP_CALLBACK_FAIL"));
593 break;
595 case OP_REJECT: {
596 AddDebugLogLineM(false,logServer,wxT("Server: OP_REJECT"));
597 AddLogLineM(false, _("Server rejected last command"));
598 break;
600 default:
601 AddDebugLogLineM( false, logPacketErrors,
602 wxString::Format( wxT("Unknown server packet with OPcode %x"), opcode )
605 return true;
606 } catch (const CInvalidPacket& e) {
607 AddLogLineM(false,CFormat( _("Bogus packet received from server: %s") ) % e.what());
608 } catch (const CEOFException& e) {
609 AddLogLineM(false,CFormat( _("Bogus packet received from server: %s") ) % e.what());
610 } catch (const wxString& error) {
611 AddLogLineM(false,CFormat( _("Unhandled error while processing packet from server: %s") ) % error);
614 // Don't disconnect because of wrong sources.
615 if (opcode==OP_SEARCHRESULT || opcode==OP_FOUNDSOURCES) {
616 return true;
619 SetConnectionState(CS_DISCONNECTED);
620 return false;
623 void CServerSocket::ConnectToServer(CServer* server, bool bNoCrypt)
625 AddDebugLogLineM(true,logServer,wxT("Trying to connect"));
627 if (cur_server){
628 wxASSERT(0);
629 delete cur_server;
630 cur_server = NULL;
633 cur_server = new CServer(server);
635 m_bNoCrypt = bNoCrypt;
637 SetConnectionState(CS_CONNECTING);
639 info = cur_server->GetListName();
641 // This must be used if we want to reverse-check the addr of the server
642 if (cur_server->HasDynIP() || !cur_server->GetIP()) {
643 m_IsSolving = true;
644 // Send it to solving thread.
645 CAsyncDNS* dns = new CAsyncDNS(server->GetAddress(), DNS_SERVER_CONNECT, theApp, this);
647 if ( dns->Create() == wxTHREAD_NO_ERROR ) {
648 if ( dns->Run() != wxTHREAD_NO_ERROR ) {
649 dns->Delete();
650 AddLogLineM(false, CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress());
652 } else {
653 dns->Delete();
654 AddLogLineM(false, CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress());
656 } else {
657 // Nothing to solve, we already have the IP
658 OnHostnameResolved(cur_server->GetIP());
663 void CServerSocket::OnError(wxSocketError nErrorCode)
665 AddDebugLogLineM(false, logServer, wxT("Error in serversocket: ") + cur_server->GetListName() + wxT("(") + cur_server->GetFullIP() + wxString::Format(wxT(":%i): %u"),cur_server->GetPort(), (int)nErrorCode));
666 SetConnectionState(CS_DISCONNECTED);
670 bool CServerSocket::PacketReceived(CPacket* packet)
672 AddDebugLogLineM(false, logServer, wxString::Format(wxT("Server: Packet Received: Prot %x, Opcode %x, Length %u"), packet->GetProtocol(), packet->GetOpCode(), packet->GetPacketSize()));
674 if (packet->GetProtocol() == OP_PACKEDPROT) {
675 if (!packet->UnPackPacket(250000)){
676 AddDebugLogLineM(false, logZLib, wxString::Format(wxT("Failed to decompress server TCP packet: protocol=0x%02x opcode=0x%02x size=%u"), packet ? packet->GetProtocol() : 0, packet ? packet->GetOpCode() : 0, packet ? packet->GetPacketSize() : 0));
677 theStats::AddDownOverheadServer(packet->GetPacketSize());
678 return true;
681 packet->SetProtocol(OP_EDONKEYPROT);
684 if (packet->GetProtocol() == OP_EDONKEYPROT) {
685 ProcessPacket(packet->GetDataBuffer(), packet->GetPacketSize(), packet->GetOpCode());
686 } else {
687 AddDebugLogLineM(false, logServer, wxString::Format(wxT("Received server TCP packet with unknown protocol: protocol=0x%02x opcode=0x%02x size=%u"), packet ? packet->GetProtocol() : 0, packet ? packet->GetOpCode() : 0, packet ? packet->GetPacketSize() : 0));
688 theStats::AddDownOverheadServer(packet->GetPacketSize());
691 return true;
695 void CServerSocket::OnClose(wxSocketError WXUNUSED(nErrorCode))
697 CEMSocket::OnClose(0);
699 switch (connectionstate) {
700 case CS_WAITFORLOGIN: SetConnectionState(CS_SERVERFULL); break;
701 case CS_CONNECTED: SetConnectionState(CS_DISCONNECTED); break;
702 default: SetConnectionState(CS_NOTCONNECTED);
705 serverconnect->DestroySocket(this);
708 void CServerSocket::SetConnectionState(sint8 newstate)
710 connectionstate = newstate;
711 if (newstate < CS_CONNECTING) {
712 serverconnect->ConnectionFailed(this);
713 } else if (newstate == CS_CONNECTED || newstate == CS_WAITFORLOGIN) {
714 if (serverconnect) {
715 serverconnect->ConnectionEstablished(this);
721 void CServerSocket::SendPacket(CPacket* packet, bool delpacket, bool controlpacket, uint32 actualPayloadSize)
723 m_dwLastTransmission = GetTickCount();
724 CEMSocket::SendPacket(packet, delpacket, controlpacket, actualPayloadSize);
728 void CServerSocket::OnHostnameResolved(uint32 ip) {
730 m_IsSolving = false;
731 if (ip) {
732 if (theApp->ipfilter->IsFiltered(ip, true)) {
733 AddLogLineM(true, CFormat( _("Server IP %s (%s) is filtered. Not connecting.") )
734 % Uint32toStringIP(ip) % cur_server->GetAddress() );
735 OnConnect(wxSOCKET_INVADDR);
736 } else {
737 amuleIPV4Address addr;
738 addr.Hostname(ip);
739 uint16 nPort = 0;
740 wxString useObfuscation;
741 if ( !m_bNoCrypt && thePrefs::IsServerCryptLayerTCPRequested() && cur_server->GetObfuscationPortTCP() != 0 && cur_server->SupportsObfuscationTCP()){
742 nPort = cur_server->GetObfuscationPortTCP();
743 useObfuscation = _("using protocol obfuscation.");
744 SetConnectionEncryption(true, NULL, true);
745 } else {
746 nPort = cur_server->GetConnPort();
747 SetConnectionEncryption(false, NULL, true);
750 addr.Service(nPort);
752 AddLogLineM(false, CFormat( _("Connecting to %s (%s - %s:%i) %s") )
753 % cur_server->GetListName()
754 % cur_server->GetAddress()
755 % cur_server->GetFullIP()
756 % nPort
757 % useObfuscation
760 AddDebugLogLineM(false, logServer, wxT("Server ") + cur_server->GetAddress() + wxT("(") + Uint32toStringIP(ip) + wxT(")") + wxString::Format(wxT(" Port %i"), cur_server->GetConnPort()));
761 Connect(addr, false);
763 } else {
764 AddLogLineM(true, CFormat( _("Could not solve dns for server %s: Unable to connect!") )
765 % cur_server->GetAddress() );
766 OnConnect(wxSOCKET_NOHOST);
770 uint32 CServerSocket::GetServerIP() const
772 return cur_server ? cur_server->GetIP() : 0;
774 // File_checked_for_headers