Fix a few comments to indicate the current code state
[amule.git] / src / ServerSocket.cpp
blob6a4c0dfdbd33107848a4d648a5809e3fa6229581
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.
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.
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_*
51 #ifdef ASIO_SOCKETS
52 # include <boost/system/error_code.hpp>
53 using namespace boost::system;
54 #endif
58 //------------------------------------------------------------------------------
59 // CServerSocketHandler
60 //------------------------------------------------------------------------------
62 class CServerSocketHandler: public wxEvtHandler
64 public:
65 CServerSocketHandler() {};
67 public:
68 private:
69 void ServerSocketHandler(wxSocketEvent& event);
70 DECLARE_EVENT_TABLE()
74 BEGIN_EVENT_TABLE(CServerSocketHandler, wxEvtHandler)
75 EVT_SOCKET(ID_SERVERSOCKET_EVENT, CServerSocketHandler::ServerSocketHandler)
76 END_EVENT_TABLE()
78 void CServerSocketHandler::ServerSocketHandler(wxSocketEvent& event)
80 CServerSocket *socket = dynamic_cast<CServerSocket *>(event.GetSocket());
81 wxASSERT(socket);
82 if (!socket) {
83 return;
86 if (socket->IsDestroying()) {
87 return;
90 switch(event.GetSocketEvent()) {
91 case wxSOCKET_CONNECTION:
92 socket->OnConnect(wxSOCKET_NOERROR);
93 break;
94 case wxSOCKET_LOST:
95 socket->OnError(socket->LastError());
96 break;
97 case wxSOCKET_INPUT:
98 socket->OnReceive(wxSOCKET_NOERROR);
99 break;
100 case wxSOCKET_OUTPUT:
101 socket->OnSend(wxSOCKET_NOERROR);
102 break;
103 default:
104 wxFAIL;
105 break;
112 // There can be only one. :)
114 static CServerSocketHandler g_serverSocketHandler;
117 //------------------------------------------------------------------------------
118 // CServerSocket
119 //------------------------------------------------------------------------------
121 CServerSocket::CServerSocket(CServerConnect* in_serverconnect, const CProxyData *ProxyData)
123 CEMSocket(ProxyData)
125 serverconnect = in_serverconnect;
126 connectionstate = 0;
127 cur_server = 0;
128 info.Clear();
129 m_bIsDeleting = false;
131 SetEventHandler(g_serverSocketHandler, ID_SERVERSOCKET_EVENT);
133 SetNotify(
134 wxSOCKET_CONNECTION_FLAG |
135 wxSOCKET_INPUT_FLAG |
136 wxSOCKET_OUTPUT_FLAG |
137 wxSOCKET_LOST_FLAG);
138 Notify(true);
140 m_dwLastTransmission = 0;
141 m_IsSolving = false;
142 m_bNoCrypt = false;
145 CServerSocket::~CServerSocket()
147 // remove event handler...
148 SetNotify(0);
149 Notify(FALSE);
151 if (cur_server) {
152 delete cur_server;
154 cur_server = NULL;
158 void CServerSocket::OnConnect(int nErrorCode)
160 switch (nErrorCode) {
161 #ifdef ASIO_SOCKETS
162 case errc::success:
163 #else
164 case wxSOCKET_NOERROR:
165 #endif
166 if (cur_server->HasDynIP()) {
167 uint32 server_ip = GetPeerInt();
168 cur_server->SetID(server_ip);
169 // GetServerByAddress may return NULL, so we must test!
170 // This was the reason why amule would crash when trying to
171 // connect in wxWidgets 2.5.2
172 CServer *pServer = theApp->serverlist->GetServerByAddress(
173 cur_server->GetAddress(), cur_server->GetPort());
174 if (pServer) {
175 pServer->SetID(server_ip);
176 } else {
177 AddDebugLogLineN(logServer, wxT("theApp->serverlist->GetServerByAddress() returned NULL"));
178 return;
181 SetConnectionState(CS_WAITFORLOGIN);
182 break;
184 #ifdef ASIO_SOCKETS
185 case errc::address_in_use:
186 case errc::address_not_available:
187 case errc::bad_address:
188 case errc::connection_refused:
189 case errc::host_unreachable:
190 case errc::invalid_argument:
191 case errc::timed_out:
192 #else
193 case wxSOCKET_INVADDR:
194 case wxSOCKET_NOHOST:
195 case wxSOCKET_INVPORT:
196 case wxSOCKET_TIMEDOUT:
197 #endif
198 m_bIsDeleting = true;
199 SetConnectionState(CS_SERVERDEAD);
200 serverconnect->DestroySocket(this);
201 return;
203 default:
204 m_bIsDeleting = true;
205 SetConnectionState(CS_FATALERROR);
206 serverconnect->DestroySocket(this);
207 return;
213 void CServerSocket::OnReceive(int nErrorCode)
215 if (connectionstate != CS_CONNECTED && !serverconnect->IsConnecting()) {
216 serverconnect->DestroySocket(this);
217 return;
219 CEMSocket::OnReceive(nErrorCode);
220 m_dwLastTransmission = GetTickCount();
223 bool CServerSocket::ProcessPacket(const byte* packet, uint32 size, int8 opcode)
225 try {
226 AddDebugLogLineN( logServer, wxT("Processing Server Packet: ") );
228 switch(opcode) {
229 case OP_SERVERMESSAGE: {
230 /* Kry import of lugdunum 16.40 new features */
231 AddDebugLogLineN( logServer, wxT("Server: OP_SERVERMESSAGE") );
233 theStats::AddDownOverheadServer(size);
234 char* buffer = new char[size-1];
235 memcpy(buffer,&packet[2],size-2);
236 buffer[size-2] = 0;
238 wxString strMessages(char2unicode(buffer));
240 delete[] buffer;
242 // 16.40 servers do not send separate OP_SERVERMESSAGE packets for each line;
243 // instead of this they are sending all text lines with one OP_SERVERMESSAGE packet.
245 wxStringTokenizer token(strMessages,wxT("\r\n"),wxTOKEN_DEFAULT );
247 while (token.HasMoreTokens()) {
248 wxString message = token.GetNextToken();
250 bool bOutputMessage = true;
251 if (message.StartsWith(wxT("server version"))) {
252 wxString strVer = message.Mid(15,64); // truncate string to avoid misuse by servers in showing ads
253 strVer.Trim();
254 CServer* eserver = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
255 if (eserver) {
256 eserver->SetVersion(strVer);
257 Notify_ServerRefresh(eserver);
259 } else if (message.StartsWith(wxT("ERROR"))) {
260 CServer* pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
261 wxString servername;
262 if (pServer) {
263 servername = pServer->GetListName();
264 } else {
265 servername = _("Server");
267 AddLogLineN(CFormat( _("ERROR: %s (%s) - %s") )
268 % servername
269 % Uint32_16toStringIP_Port(cur_server->GetIP(), cur_server->GetPort())
270 % message.Mid(5,message.Len()).Trim(wxT(" :")));
271 bOutputMessage = false;
273 } else if (message.StartsWith(wxT("WARNING"))) {
275 CServer* pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
276 wxString servername;
277 if (pServer) {
278 servername = pServer->GetListName();
279 } else {
280 servername = _("Server");
282 AddLogLineN(CFormat( _("WARNING: %s (%s) - %s") )
283 % servername
284 % Uint32_16toStringIP_Port(cur_server->GetIP(), cur_server->GetPort())
285 % message.Mid(5,message.Len()).Trim(wxT(" :")));
287 bOutputMessage = false;
290 if (message.Find(wxT("[emDynIP: ")) != (-1) && message.Find(wxT("]")) != (-1) && message.Find(wxT("[emDynIP: ")) < message.Find(wxT("]"))){
291 wxString dynip = message.Mid(message.Find(wxT("[emDynIP: "))+10,message.Find(wxT("]")) - (message.Find(wxT("[emDynIP: "))+10));
292 dynip.Trim(wxT(" "));
293 if ( dynip.Length() && dynip.Length() < 51){
294 CServer* eserver = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
295 if (eserver){
296 eserver->SetDynIP(dynip);
297 cur_server->SetDynIP(dynip);
298 Notify_ServerRefresh(eserver);
303 if (bOutputMessage) {
304 theApp->AddServerMessageLine(message);
307 break;
309 case OP_IDCHANGE: {
310 AddDebugLogLineN(logServer, wxT("Server: OP_IDCHANGE"));
312 theStats::AddDownOverheadServer(size);
314 if (size < 4 /* uint32 (ID)*/) {
315 throw wxString(wxT("Corrupt or invalid loginanswer from server received"));
318 CMemFile data(packet, size);
320 uint32 new_id = data.ReadUInt32();
322 // save TCP flags in 'cur_server'
323 wxASSERT(cur_server);
324 CServer* pServer = NULL;
325 if (cur_server) {
326 uint32 ConnPort = 0;
327 uint32 rport = cur_server->GetConnPort();
328 pServer = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(), rport);
329 if (size >= 4+4 /* uint32 (ID) + uint32 (TCP flags)*/) {
330 cur_server->SetTCPFlags(data.ReadUInt32());
331 if (size >= 4+4+4 /* uint32 (ID) + uint32 (TCP flags) + uint32 (aux port) */) {
332 // aux port login : we should use the 'standard' port of this server to advertize to other clients
333 ConnPort = data.ReadUInt32();
334 cur_server->SetPort(ConnPort);
335 if (cur_server->GetAuxPortsList().IsEmpty()) {
336 cur_server->SetAuxPortsList(CFormat(wxT("%u")) % rport);
339 } else {
340 cur_server->SetTCPFlags(0);
342 // copy TCP flags into the server in the server list
343 if (pServer) {
344 pServer->SetTCPFlags(cur_server->GetTCPFlags());
345 if (ConnPort) {
346 pServer->SetPort(ConnPort);
347 if (pServer->GetAuxPortsList().IsEmpty()) {
348 pServer->SetAuxPortsList(CFormat(wxT("%u")) % pServer->GetConnPort());
350 Notify_ServerRefresh(pServer);
351 Notify_ServerUpdateED2KInfo();
356 uint32 dwServerReportedIP = 0;
357 if (size >= 4 + 4 + 4 + 4 + 4 /* All of the above + reported ip + obfuscation port */) {
358 dwServerReportedIP = data.ReadUInt32();
359 if (::IsLowID(dwServerReportedIP)){
360 wxFAIL;
361 dwServerReportedIP = 0;
363 wxASSERT( dwServerReportedIP == new_id || ::IsLowID(new_id) );
364 uint32 dwObfuscationTCPPort = data.ReadUInt32();
365 if (dwObfuscationTCPPort != 0) {
366 if (cur_server != NULL) {
367 cur_server->SetObfuscationPortTCP(dwObfuscationTCPPort);
369 if (pServer != NULL) {
370 pServer->SetObfuscationPortTCP(dwObfuscationTCPPort);
375 if (new_id == 0) {
376 uint8 state = thePrefs::GetSmartIdState();
377 if ( state > 0 ) {
378 state++;
379 if(state > 3) {
380 thePrefs::SetSmartIdState(0);
381 } else {
382 thePrefs::SetSmartIdState(state);
385 break;
387 if(thePrefs::GetSmartIdCheck()) {
388 if (!IsLowID(new_id)) {
389 thePrefs::SetSmartIdState(1);
390 } else {
391 uint8 state = thePrefs::GetSmartIdState();
392 if ( state > 0 ) {
393 state++;
394 if(state > 3) {
395 thePrefs::SetSmartIdState(0);
396 } else {
397 thePrefs::SetSmartIdState(state);
399 break;
404 // we need to know our client when sending our shared files (done indirectly on SetConnectionState)
406 serverconnect->SetClientID(new_id);
408 if (::IsLowID(new_id) && dwServerReportedIP != 0) {
409 theApp->SetPublicIP(dwServerReportedIP);
412 if (connectionstate != CS_CONNECTED) {
413 AddDebugLogLineN(logServer, wxT("Connected"));
415 SetConnectionState(CS_CONNECTED);
416 theApp->OnlineSig(); // Added By Bouc7
419 theApp->ShowConnectionState();
421 AddLogLineN(CFormat(_("New clientid is %u")) % new_id);
422 if (::IsLowID(new_id)) {
423 AddLogLineC(_("WARNING: You have received Low-ID!"));
424 AddLogLineN(_("\tMost likely this is because you're behind a firewall or router."));
425 AddLogLineN(_("\tFor more information, please refer to http://wiki.amule.org"));
428 theApp->downloadqueue->ResetLocalServerRequests();
429 break;
431 case OP_SEARCHRESULT: {
432 AddDebugLogLineN(logServer, wxT("Server: OP_SEARCHRESULT"));
434 theStats::AddDownOverheadServer(size);
435 CServer* cur_srv = (serverconnect) ?
436 serverconnect->GetCurrentServer() : NULL;
437 theApp->searchlist->ProcessSearchAnswer(
438 packet,
439 size,
440 true /*(cur_srv && cur_srv->GetUnicodeSupport())*/,
441 cur_srv ? cur_srv->GetIP() : 0,
442 cur_srv ? cur_srv->GetPort() : 0);
443 theApp->searchlist->LocalSearchEnd();
444 break;
446 case OP_FOUNDSOURCES_OBFU:
447 case OP_FOUNDSOURCES: {
448 AddDebugLogLineN(logServer, CFormat(wxT("ServerMsg - OP_FoundSources; sources = %u")) % packet[16]);
449 theStats::AddDownOverheadServer(size);
450 CMemFile sources(packet,size);
451 CMD4Hash fileid = sources.ReadHash();
452 if (CPartFile* file = theApp->downloadqueue->GetFileByID(fileid)) {
453 file->AddSources(sources, cur_server->GetIP(), cur_server->GetPort(), SF_LOCAL_SERVER, (opcode == OP_FOUNDSOURCES_OBFU));
454 } else {
455 AddDebugLogLineN(logServer, wxT("Sources received for unknown file: ") + fileid.Encode());
457 break;
459 case OP_SERVERSTATUS: {
460 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERSTATUS"));
461 // FIXME some statuspackets have a different size -> why? structur?
462 if (size < 8) {
463 throw wxString(wxT("Invalid server status packet"));
465 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort());
466 if (update) {
467 CMemFile data(packet, size);
468 update->SetUserCount(data.ReadUInt32());
469 update->SetFileCount(data.ReadUInt32());
470 Notify_ServerRefresh( update );
471 theApp->ShowUserCount();
473 break;
475 // Cleaned.
476 case OP_SERVERIDENT: {
477 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERIDENT"));
479 theStats::AddDownOverheadServer(size);
480 if (size<38) {
481 AddLogLineN(_("Unknown server info received! - too short"));
482 // throw wxString(wxT("Unknown server info received!"));
483 break;
485 CServer* update = theApp->serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
486 if (update) {
487 CMemFile data(packet,size);
488 CMD4Hash hash = data.ReadHash();
489 if (RawPeekUInt32(hash.GetHash()) == 0x2A2A2A2A){ // No endian problem here
490 const wxString& rstrVersion = update->GetVersion();
491 if (!rstrVersion.IsEmpty()) {
492 update->SetVersion(wxT("eFarm ") + rstrVersion);
493 } else {
494 update->SetVersion(wxT("eFarm"));
497 // Unused
498 /*uint32 nServerIP = */data.ReadUInt32();
499 /*uint16 nServerPort = */data.ReadUInt16();
501 uint32 nTags = data.ReadUInt32();
502 for (uint32 i = 0; i < nTags; i++){
503 CTag tag(data, update->GetUnicodeSupport());
504 if (tag.GetNameID() == ST_SERVERNAME){
505 update->SetListName(tag.GetStr());
506 } else if (tag.GetNameID() == ST_DESCRIPTION){
507 update->SetDescription(tag.GetStr());
508 } // No more known tags from server
511 theApp->ShowConnectionState();
512 Notify_ServerRefresh(update);
514 break;
516 // tecxx 1609 2002 - add server's serverlist to own serverlist
517 case OP_SERVERLIST: {
518 AddDebugLogLineN(logServer, wxT("Server: OP_SERVERLIST"));
520 CMemFile* servers = new CMemFile(packet,size);
521 uint8 count = servers->ReadUInt8();
522 if (((int32)(count*6 + 1) > size)) {
523 count = 0;
525 int addcount = 0;
526 while(count) {
527 uint32 ip = servers->ReadUInt32();
528 uint16 port = servers->ReadUInt16();
529 CServer* srv = new CServer(
530 port , // Port
531 Uint32toStringIP(ip)); // Ip
532 srv->SetListName(srv->GetFullIP());
533 if (!theApp->AddServer(srv)) {
534 delete srv;
535 } else {
536 addcount++;
538 count--;
540 delete servers;
541 if (addcount) {
542 AddLogLineN(CFormat(wxPLURAL("Received %d new server", "Received %d new servers", addcount)) % addcount);
544 theApp->serverlist->SaveServerMet();
545 AddLogLineN(_("Saving of server-list completed."));
546 break;
548 case OP_CALLBACKREQUESTED: {
549 AddDebugLogLineN(logServer, wxT("Server: OP_CALLBACKREQUESTED"));
551 theStats::AddDownOverheadServer(size);
552 if (size >= 6) {
553 CMemFile data(packet,size);
554 uint32 dwIP = data.ReadUInt32();
555 uint16 nPort = data.ReadUInt16();
557 uint8 byCryptOptions = 0;
558 CMD4Hash achUserHash;
559 if (size >= 23){
560 byCryptOptions = data.ReadUInt8();;
561 achUserHash = data.ReadHash();
564 CUpDownClient* client = theApp->clientlist->FindClientByIP(dwIP,nPort);
566 if (!client) {
567 client = new CUpDownClient(nPort,dwIP,0,0,0, true, true);
568 theApp->clientlist->AddClient(client);
570 if (size >= 23 && client->HasValidHash()){
571 if (client->GetUserHash() != achUserHash){
572 AddDebugLogLineN(logServer, wxT("Reported Userhash from OP_CALLBACKREQUESTED differs with our stored hash"));
573 // disable crypt support since we dont know which hash is true
574 client->SetCryptLayerRequest(false);
575 client->SetCryptLayerSupport(false);
576 client->SetCryptLayerRequires(false);
577 } else {
578 client->SetConnectOptions(byCryptOptions, true, false);
580 } else if (size >= 23) {
581 client->SetUserHash(achUserHash);
582 client->SetConnectOptions(byCryptOptions, true, false);
585 client->TryToConnect();
587 break;
589 case OP_CALLBACK_FAIL: {
590 AddDebugLogLineN(logServer, wxT("Server: OP_CALLBACK_FAIL"));
591 break;
593 case OP_REJECT: {
594 AddDebugLogLineN(logServer, wxT("Server: OP_REJECT"));
595 AddLogLineN(_("Server rejected last command"));
596 break;
598 default:
599 AddDebugLogLineN(logPacketErrors, CFormat(wxT("Unknown server packet with OPcode %x")) % opcode);
601 return true;
602 } catch (const CInvalidPacket& e) {
603 AddLogLineN(CFormat( _("Bogus packet received from server: %s") ) % e.what());
604 } catch (const CEOFException& e) {
605 AddLogLineN(CFormat( _("Bogus packet received from server: %s") ) % e.what());
606 } catch (const wxString& error) {
607 AddLogLineN(CFormat( _("Unhandled error while processing packet from server: %s") ) % error);
610 // Don't disconnect because of wrong sources.
611 if (opcode==OP_SEARCHRESULT || opcode==OP_FOUNDSOURCES) {
612 return true;
615 SetConnectionState(CS_DISCONNECTED);
616 return false;
619 void CServerSocket::ConnectToServer(CServer* server, bool bNoCrypt)
621 AddDebugLogLineN(logServer, wxT("Trying to connect"));
623 if (cur_server){
624 wxFAIL;
625 delete cur_server;
626 cur_server = NULL;
629 cur_server = new CServer(server);
631 m_bNoCrypt = bNoCrypt;
633 SetConnectionState(CS_CONNECTING);
635 info = cur_server->GetListName();
637 // This must be used if we want to reverse-check the addr of the server
638 if (cur_server->HasDynIP() || !cur_server->GetIP()) {
639 m_IsSolving = true;
640 // Send it to solving thread.
641 CAsyncDNS* dns = new CAsyncDNS(server->GetAddress(), DNS_SERVER_CONNECT, theApp, this);
643 if ( dns->Create() == wxTHREAD_NO_ERROR ) {
644 if ( dns->Run() != wxTHREAD_NO_ERROR ) {
645 dns->Delete();
646 AddLogLineN(CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress());
648 } else {
649 dns->Delete();
650 AddLogLineN(CFormat( _("Cannot create DNS solving thread for connecting to %s") ) % cur_server->GetAddress());
652 } else {
653 // Nothing to solve, we already have the IP
654 OnHostnameResolved(cur_server->GetIP());
659 void CServerSocket::OnError(int DEBUG_ONLY(nErrorCode))
661 AddDebugLogLineN(logServer, CFormat(wxT("Error in serversocket: %s(%s:%i): %u"))
662 % cur_server->GetListName() % cur_server->GetFullIP() % cur_server->GetPort() % nErrorCode);
663 SetConnectionState(CS_DISCONNECTED);
667 bool CServerSocket::PacketReceived(CPacket* packet)
669 AddDebugLogLineN(logServer, CFormat(wxT("Server: Packet Received: Prot %x, Opcode %x, Length %u")) % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize());
671 if (packet->GetProtocol() == OP_PACKEDPROT) {
672 if (!packet->UnPackPacket(250000)){
673 AddDebugLogLineN(logZLib, CFormat(wxT("Failed to decompress server TCP packet: protocol=0x%02x opcode=0x%02x size=%u"))
674 % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize());
675 theStats::AddDownOverheadServer(packet->GetPacketSize());
676 return true;
679 packet->SetProtocol(OP_EDONKEYPROT);
682 if (packet->GetProtocol() == OP_EDONKEYPROT) {
683 ProcessPacket(packet->GetDataBuffer(), packet->GetPacketSize(), packet->GetOpCode());
684 } else {
685 AddDebugLogLineN(logServer, CFormat(wxT("Received server TCP packet with unknown protocol: protocol=0x%02x opcode=0x%02x size=%u"))
686 % packet->GetProtocol() % packet->GetOpCode() % packet->GetPacketSize());
687 theStats::AddDownOverheadServer(packet->GetPacketSize());
690 return true;
694 void CServerSocket::OnClose(int WXUNUSED(nErrorCode))
696 CEMSocket::OnClose(0);
698 switch (connectionstate) {
699 case CS_WAITFORLOGIN: SetConnectionState(CS_SERVERFULL); break;
700 case CS_CONNECTED: SetConnectionState(CS_DISCONNECTED); break;
701 default: SetConnectionState(CS_NOTCONNECTED);
704 serverconnect->DestroySocket(this);
707 void CServerSocket::SetConnectionState(sint8 newstate)
709 connectionstate = newstate;
710 if (newstate < CS_CONNECTING) {
711 serverconnect->ConnectionFailed(this);
712 } else if (newstate == CS_CONNECTED || newstate == CS_WAITFORLOGIN) {
713 if (serverconnect) {
714 serverconnect->ConnectionEstablished(this);
720 void CServerSocket::SendPacket(CPacket* packet, bool delpacket, bool controlpacket, uint32 actualPayloadSize)
722 m_dwLastTransmission = GetTickCount();
723 CEMSocket::SendPacket(packet, delpacket, controlpacket, actualPayloadSize);
727 void CServerSocket::OnHostnameResolved(uint32 ip) {
729 m_IsSolving = false;
730 if (ip) {
731 if (theApp->ipfilter->IsFiltered(ip, true)) {
732 AddLogLineC(CFormat( _("Server IP %s (%s) is filtered. Not connecting.") )
733 % Uint32toStringIP(ip) % cur_server->GetAddress() );
734 #ifdef ASIO_SOCKETS
735 OnConnect(errc::invalid_argument);
736 #else
737 OnConnect(wxSOCKET_INVADDR);
738 #endif
739 } else {
740 amuleIPV4Address addr;
741 addr.Hostname(ip);
742 uint16 nPort = 0;
743 wxString useObfuscation;
744 if ( !m_bNoCrypt && thePrefs::IsServerCryptLayerTCPRequested() && cur_server->GetObfuscationPortTCP() != 0 && cur_server->SupportsObfuscationTCP()){
745 nPort = cur_server->GetObfuscationPortTCP();
746 useObfuscation = _("using protocol obfuscation.");
747 SetConnectionEncryption(true, NULL, true);
748 } else {
749 nPort = cur_server->GetConnPort();
750 SetConnectionEncryption(false, NULL, true);
753 addr.Service(nPort);
755 AddLogLineN(CFormat( _("Connecting to %s (%s - %s:%i) %s") )
756 % cur_server->GetListName()
757 % cur_server->GetAddress()
758 % cur_server->GetFullIP()
759 % nPort
760 % useObfuscation
763 AddDebugLogLineN(logServer, CFormat(wxT("Server %s(%s) Port %i"))
764 % cur_server->GetAddress() % Uint32toStringIP(ip) % cur_server->GetConnPort());
765 Connect(addr, false);
767 } else {
768 AddLogLineC(CFormat( _("Could not solve dns for server %s: Unable to connect!") )
769 % cur_server->GetAddress() );
770 #ifdef ASIO_SOCKETS
771 OnConnect(errc::host_unreachable);
772 #else
773 OnConnect(wxSOCKET_NOHOST);
774 #endif
778 uint32 CServerSocket::GetServerIP() const
780 return cur_server ? cur_server->GetIP() : 0;
782 // File_checked_for_headers