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 "ServerConnect.h"	// Interface declarations.
27 
28 #include <protocol/Protocols.h>
29 #include <protocol/ed2k/ClientSoftware.h> // Sometimes we reply with TCP packets.
30 #include <tags/ClientTags.h>
31 #include <common/ClientVersion.h>
32 #include <common/EventIDs.h>
33 
34 #include "SearchList.h"		// Needed for CSearchList
35 #include "ServerUDPSocket.h"	// Needed for CServerUDPSocket
36 #include "SharedFileList.h"	// Needed for CSharedFileList
37 #include "Packet.h"		// Needed for CTag
38 #include "MemFile.h"		// Needed for CMemFile
39 #include "ServerSocket.h"	// Needed for CServerSocket
40 #include "ListenSocket.h"	// Needed for CListenSocket
41 #include "Server.h"		// Needed for CServer
42 #include "amule.h"		// Needed for theApp
43 #include "ServerList.h"		// Needed for CServerList
44 #include "Preferences.h"	// Needed for CPreferences
45 #include "Statistics.h"		// Needed for theStats
46 #include "Logger.h"
47 #include "GuiEvents.h"		// Needed for Notify_*
48 #include "IPFilter.h"		// Needed for theApp->ipfilter->IsReady()
49 #include <common/Format.h>
50 
51 
52 //#define DEBUG_CLIENT_PROTOCOL
53 
54 
TryAnotherConnectionrequest()55 void CServerConnect::TryAnotherConnectionrequest()
56 {
57 	if (m_recurseTryAnotherConnectionrequest) {
58 		return;
59 	}
60 	if ( connectionattemps.size() < (unsigned)(( thePrefs::IsSafeServerConnectEnabled()) ? 1 : 2) ) {
61 
62 		CServer*  next_server = used_list->GetNextServer(m_bTryObfuscated);
63 
64 		if ( thePrefs::AutoConnectStaticOnly() ) {
65 			while (next_server && !next_server->IsStaticMember()) {
66 				next_server = used_list->GetNextServer(m_bTryObfuscated);
67 			}
68 		}
69 
70 		if (!next_server) {
71 			if ( connectionattemps.empty() ) {
72 				m_recurseTryAnotherConnectionrequest = true;
73 				if (m_bTryObfuscated && !thePrefs::IsClientCryptLayerRequired()){
74 					AddLogLineC(_("Failed to connect to all obfuscated servers listed. Making another pass without obfuscation."));
75 					// try all servers on the non-obfuscated port next
76 					m_bTryObfuscated = false;
77 					ConnectToAnyServer( false, true);
78 				} else {
79 					AddLogLineC(_("Failed to connect to all servers listed. Making another pass."));
80 					ConnectToAnyServer( false );
81 				}
82 				m_recurseTryAnotherConnectionrequest = false;
83 			}
84 			return;
85 		}
86 
87 		ConnectToServer(next_server, true, !m_bTryObfuscated);
88 	}
89 }
90 
ConnectToAnyServer(bool prioSort,bool bNoCrypt)91 void CServerConnect::ConnectToAnyServer(bool prioSort, bool bNoCrypt)
92 {
93 	if (!thePrefs::GetNetworkED2K()){
94 		AddLogLineC(_("eD2k network disabled on preferences, not connecting."));
95 		return;
96 	}
97 	if (!theApp->ipfilter->IsReady()) {
98 		// do it later when ipfilter is up
99 		theApp->ipfilter->ConnectToAnyServerWhenReady();
100 		return;
101 	}
102 
103 	StopConnectionTry();
104 	Disconnect();
105 	connecting = true;
106 	singleconnecting = false;
107 	m_bTryObfuscated = thePrefs::IsServerCryptLayerTCPRequested() && !bNoCrypt;
108 
109 	// Barry - Only auto-connect to static server option
110 	if (thePrefs::AutoConnectStaticOnly()) {
111 		bool anystatic = false;
112 		CServer *next_server;
113 		used_list->ResetServerPos();
114 		while ((next_server = used_list->GetNextServer(false)) != NULL) {
115 			if (next_server->IsStaticMember()) {
116 				anystatic = true;
117 				break;
118 			}
119 		}
120 		if (!anystatic) {
121 			connecting = false;
122 			AddLogLineC(_("No valid servers to which to connect found in server list"));
123 			return;
124 		}
125 	}
126 
127 	if ( thePrefs::Score() && prioSort ) {
128 		used_list->Sort();
129 	}
130 
131 	used_list->ResetServerPos();
132 
133 	if (used_list->GetServerCount()==0 ) {
134 		connecting = false;
135 		AddLogLineC(_("No valid servers to which to connect found in server list"));
136 		return;
137 	}
138 
139 	theApp->listensocket->Process();
140 
141 	TryAnotherConnectionrequest();
142 }
143 
144 
ConnectToServer(CServer * server,bool multiconnect,bool bNoCrypt)145 void CServerConnect::ConnectToServer(CServer* server, bool multiconnect, bool bNoCrypt)
146 {
147 	if (!thePrefs::GetNetworkED2K()){
148 		AddLogLineC(_("eD2k network disabled on preferences, not connecting."));
149 		return;
150 	}
151 
152 	if (!multiconnect) {
153 		StopConnectionTry();
154 		Disconnect();
155 	}
156 	connecting = true;
157 	singleconnecting = !multiconnect;
158 
159 	CServerSocket* newsocket = new CServerSocket(this, thePrefs::GetProxyData());
160 	m_lstOpenSockets.push_back(newsocket);
161 	newsocket->ConnectToServer(server, bNoCrypt);
162 
163 	connectionattemps[GetTickCount()] = newsocket;
164 }
165 
166 
StopConnectionTry()167 void CServerConnect::StopConnectionTry()
168 {
169 	connectionattemps.clear();
170 	connecting = false;
171 	singleconnecting = false;
172 
173 	if (m_idRetryTimer.IsRunning())
174 	{
175 	  m_idRetryTimer.Stop();
176 	}
177 
178 	// close all currenty opened sockets except the one which is connected to our current server
179 	for(SocketsList::iterator it = m_lstOpenSockets.begin(); it != m_lstOpenSockets.end(); ) {
180 		CServerSocket *pSck = *it++;
181 		if (pSck == connectedsocket)		// don't destroy socket which is connected to server
182 			continue;
183 		if (pSck->m_bIsDeleting == false)	// don't destroy socket if it is going to destroy itself later on
184 			DestroySocket(pSck);
185 	}
186 }
187 
ConnectionEstablished(CServerSocket * sender)188 void CServerConnect::ConnectionEstablished(CServerSocket* sender)
189 {
190 	if (connecting == false)
191 	{
192 		// we are already connected to another server
193 		DestroySocket(sender);
194 		return;
195 	}
196 
197 	if (sender->GetConnectionState() == CS_WAITFORLOGIN) {
198 		AddLogLineN(CFormat( _("Connected to %s (%s:%i)") )
199 			% sender->cur_server->GetListName()
200 			% sender->cur_server->GetFullIP()
201 			% sender->cur_server->GetPort() );
202 
203 		//send loginpacket
204 		CServer* update = theApp->serverlist->GetServerByAddress( sender->cur_server->GetAddress(), sender->cur_server->GetPort() );
205 		if (update){
206 			update->ResetFailedCount();
207 			Notify_ServerRefresh( update );
208 		}
209 
210 		CMemFile data(256);
211 		data.WriteHash(thePrefs::GetUserHash());
212 		// Why pass an ID, if we are loggin in?
213 		data.WriteUInt32(GetClientID());
214 		data.WriteUInt16(thePrefs::GetPort());
215 		data.WriteUInt32(4); // tagcount
216 
217 		// Kry - Server doesn't support VBT tags afaik.
218 		// Not to mention we don't know its flags yet
219 
220 		CTagString tagname(CT_NAME,thePrefs::GetUserNick());
221 		tagname.WriteTagToFile(&data);
222 
223 		CTagInt32 tagversion(CT_VERSION,EDONKEYVERSION);
224 		tagversion.WriteTagToFile(&data);
225 
226 		uint32 dwCryptFlags = 0;
227 
228 		if (thePrefs::IsClientCryptLayerSupported()) {
229 			dwCryptFlags |= SRVCAP_SUPPORTCRYPT;
230 		}
231 
232 		if (thePrefs::IsClientCryptLayerRequested()) {
233 			dwCryptFlags |= SRVCAP_REQUESTCRYPT;
234 		}
235 
236 		if (thePrefs::IsClientCryptLayerRequired()) {
237 			dwCryptFlags |= SRVCAP_REQUIRECRYPT;
238 		}
239 
240 		// FLAGS for server connection
241 		CTagInt32 tagflags(CT_SERVER_FLAGS, CAPABLE_ZLIB
242 								| CAPABLE_AUXPORT
243 								| CAPABLE_NEWTAGS
244 								| CAPABLE_UNICODE
245 								| CAPABLE_LARGEFILES
246 								| dwCryptFlags
247 											);
248 
249 		tagflags.WriteTagToFile(&data);
250 
251 		// eMule Version (14-Mar-2004: requested by lugdunummaster (need for LowID clients which have no chance
252 		// to send an Hello packet to the server during the callback test))
253 		CTagInt32 tagMuleVersion(CT_EMULE_VERSION,
254 			(SO_AMULE	<< 24) |
255 			make_full_ed2k_version(VERSION_MJR, VERSION_MIN, VERSION_UPDATE)
256 			 );
257 		tagMuleVersion.WriteTagToFile(&data);
258 
259 		CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_LOGINREQUEST);
260 		#ifdef DEBUG_CLIENT_PROTOCOL
261 		AddLogLineC(wxT("Client: OP_LOGINREQUEST"));
262 		AddLogLineC(wxString(wxT("        Hash     : ")) << thePrefs::GetUserHash().Encode());
263 		AddLogLineC(wxString(wxT("        ClientID : ")) << GetClientID());
264 		AddLogLineC(wxString(wxT("        Port     : ")) << thePrefs::GetPort());
265 		AddLogLineC(wxString(wxT("        User Nick: ")) << thePrefs::GetUserNick());
266 		AddLogLineC(wxString(wxT("        Edonkey  : ")) << EDONKEYVERSION);
267 		#endif
268 		theStats::AddUpOverheadServer(packet->GetPacketSize());
269 		SendPacket(packet, true, sender);
270 	} else if (sender->GetConnectionState() == CS_CONNECTED){
271 		theStats::AddReconnect();
272 		theStats::GetServerConnectTimer()->ResetTimer();
273 		connected = true;
274 		AddLogLineC(CFormat( _("Connection established on: %s") ) % sender->cur_server->GetListName());
275 		connectedsocket = sender;
276 
277 		StopConnectionTry();
278 
279 		CServer* update = theApp->serverlist->GetServerByAddress(connectedsocket->cur_server->GetAddress(),sender->cur_server->GetPort());
280 		if ( update ) {
281 			Notify_ServerHighlight(update, true);
282 		}
283 
284 		theApp->sharedfiles->ClearED2KPublishInfo();
285 
286 		Notify_ServerRemoveDead();
287 
288 		// tecxx 1609 2002 - serverlist update
289 		if (thePrefs::AddServersFromServer()) {
290 			CPacket* packet = new CPacket(OP_GETSERVERLIST, 0, OP_EDONKEYPROT);
291 			theStats::AddUpOverheadServer(packet->GetPacketSize());
292 			SendPacket(packet, true);
293 			#ifdef DEBUG_CLIENT_PROTOCOL
294 			AddLogLineC(wxT("Client: OP_GETSERVERLIST"));
295 			#endif
296 		}
297 	}
298 
299 	theApp->ShowConnectionState();
300 }
301 
302 
SendPacket(CPacket * packet,bool delpacket,CServerSocket * to)303 bool CServerConnect::SendPacket(CPacket* packet,bool delpacket, CServerSocket* to)
304 {
305 	if (!to) {
306 		if (connected) {
307 			connectedsocket->SendPacket(packet, delpacket, true);
308 			return true;
309 		} else {
310 			if ( delpacket ) {
311 				delete packet;
312 			}
313 
314 			return false;
315 		}
316 	} else {
317 		to->SendPacket(packet, delpacket, true);
318 		return true;
319 	}
320 }
321 
322 
SendUDPPacket(CPacket * packet,CServer * host,bool delpacket,bool rawpacket,uint16 port_offset)323 bool CServerConnect::SendUDPPacket(CPacket* packet, CServer* host, bool delpacket, bool rawpacket, uint16 port_offset)
324 {
325 	if (connected) {
326 		serverudpsocket->SendPacket(packet, host, delpacket, rawpacket, port_offset);
327 	} else if (delpacket) {
328 		delete packet;
329 	}
330 
331 	return true;
332 }
333 
334 
ConnectionFailed(CServerSocket * sender)335 void CServerConnect::ConnectionFailed(CServerSocket* sender)
336 {
337 	if (connecting == false && sender != connectedsocket)
338 	{
339 		// just return, cleanup is done by the socket itself
340 		return;
341 	}
342 	//messages
343 	CServer* pServer = theApp->serverlist->GetServerByAddress(sender->cur_server->GetAddress(), sender->cur_server->GetPort());
344 	switch (sender->GetConnectionState()){
345 		case CS_FATALERROR:
346 			AddLogLineC(_("Fatal Error while trying to connect. Internet connection might be down"));
347 			break;
348 		case CS_DISCONNECTED:
349 			theApp->sharedfiles->ClearED2KPublishInfo();
350 			AddLogLineN(CFormat( _("Lost connection to %s (%s:%i)") )
351 				% sender->cur_server->GetListName()
352 				% sender->cur_server->GetFullIP()
353 				% sender->cur_server->GetPort() );
354 
355 			if (pServer){
356 				Notify_ServerHighlight(pServer, false);
357 			}
358 			break;
359 		case CS_SERVERDEAD:
360 			AddLogLineN(CFormat( _("%s (%s:%i) appears to be dead.") )
361 				% sender->cur_server->GetListName()
362 				% sender->cur_server->GetFullIP()
363 				% sender->cur_server->GetPort() );
364 
365 			if (pServer) {
366 				pServer->AddFailedCount();
367 				Notify_ServerRefresh( pServer );
368 			}
369 			break;
370 		case CS_ERROR:
371 			break;
372 		case CS_SERVERFULL:
373 			AddLogLineN(CFormat( _("%s (%s:%i) appears to be full.") )
374 				% sender->cur_server->GetListName()
375 				% sender->cur_server->GetFullIP()
376 				% sender->cur_server->GetPort() );
377 
378 			break;
379 		case CS_NOTCONNECTED:;
380 			break;
381 	}
382 
383 	// IMPORTANT: mark this socket not to be deleted in StopConnectionTry(),
384 	// because it will delete itself after this function!
385 	sender->m_bIsDeleting = true;
386 
387 	switch (sender->GetConnectionState()) {
388 		case CS_FATALERROR:{
389 			bool autoretry= !singleconnecting;
390 			StopConnectionTry();
391 			if ((thePrefs::Reconnect()) && (autoretry) && (!m_idRetryTimer.IsRunning())) {
392 				AddLogLineN(CFormat(wxPLURAL("Automatic connection to server will retry in %d second", "Automatic connection to server will retry in %d seconds", CS_RETRYCONNECTTIME)) % CS_RETRYCONNECTTIME);
393 				m_idRetryTimer.Start(1000*CS_RETRYCONNECTTIME);
394 			}
395 			break;
396 		}
397 		case CS_DISCONNECTED:{
398 			theApp->sharedfiles->ClearED2KPublishInfo();
399 			connected = false;
400 			Notify_ServerHighlight(sender->cur_server,false);
401 			if (connectedsocket)  {
402 				connectedsocket->Close();
403 			}
404 			connectedsocket = NULL;
405 			theApp->searchlist->StopSearch(true);
406 			Notify_SearchCancel();
407 			theStats::GetServerConnectTimer()->StopTimer();
408 			if (thePrefs::Reconnect() && !connecting){
409 				ConnectToAnyServer();
410 			}
411 
412 			AddLogLineC(_("Connection lost") );
413 			break;
414 		}
415 		case CS_ERROR:
416 		case CS_NOTCONNECTED:{
417 			if (!connecting)
418 				break;
419 			AddLogLineN(CFormat( _("Connecting to %s (%s:%i) failed.") )
420 				% sender->info
421 				% sender->cur_server->GetFullIP()
422 				% sender->cur_server->GetPort() );
423 		}
424 		/* fall through */
425 		case CS_SERVERDEAD:
426 		case CS_SERVERFULL:{
427 			if (!connecting) {
428 				break;
429 			}
430 			if (singleconnecting) {
431 				if (pServer && sender->IsServerCryptEnabledConnection() && !thePrefs::IsClientCryptLayerRequired()){
432 					// try reconnecting without obfuscation
433 					ConnectToServer(pServer, false, true);
434 					break;
435 				}
436 
437 				StopConnectionTry();
438 				break;
439 			}
440 
441 			ServerSocketMap::iterator it = connectionattemps.begin();
442 			while ( it != connectionattemps.end() ){
443 				if ( it->second == sender ) {
444 					connectionattemps.erase( it );
445 					break;
446 				}
447 				++it;
448 			}
449 			TryAnotherConnectionrequest();
450 		}
451 	}
452 	theApp->ShowConnectionState();
453 }
454 
CheckForTimeout()455 void CServerConnect::CheckForTimeout()
456 {
457 	uint32 dwCurTick = GetTickCount();
458 
459 	ServerSocketMap::iterator it = connectionattemps.begin();
460 	while ( it != connectionattemps.end() ){
461 		if ( !it->second ) {
462 			AddLogLineN(_("ERROR: Socket invalid at timeout check"));
463 			connectionattemps.erase( it );
464 			return;
465 		}
466 
467 		if ( dwCurTick - it->first > CONSERVTIMEOUT) {
468 			uint32 key = it->first;
469 			CServerSocket* value = it->second;
470 			++it;
471 			if (!value->IsSolving()) {
472 				AddLogLineN(CFormat( _("Connection attempt to %s (%s:%i) timed out.") )
473 					% value->info
474 					% value->cur_server->GetFullIP()
475 					% value->cur_server->GetPort() );
476 
477 				connectionattemps.erase( key );
478 
479 				TryAnotherConnectionrequest();
480 				DestroySocket( value );
481 			}
482 		} else {
483 			++it;
484 		}
485 	}
486 }
487 
488 
Disconnect()489 bool CServerConnect::Disconnect()
490 {
491 	if (connected && connectedsocket) {
492 		theApp->sharedfiles->ClearED2KPublishInfo();
493 
494 		connected = false;
495 
496 		CServer* update = theApp->serverlist->GetServerByAddress(
497 			connectedsocket->cur_server->GetAddress(),
498 			connectedsocket->cur_server->GetPort());
499 		Notify_ServerHighlight(update, false);
500 		theApp->SetPublicIP(0);
501 		DestroySocket(connectedsocket);
502 		connectedsocket = NULL;
503 		theApp->ShowConnectionState();
504 		theStats::GetServerConnectTimer()->StopTimer();
505 		return true;
506 	} else {
507 		return false;
508 	}
509 }
510 
511 
CServerConnect(CServerList * in_serverlist,amuleIPV4Address & address)512 CServerConnect::CServerConnect(CServerList* in_serverlist, amuleIPV4Address &address)
513 : m_idRetryTimer(theApp,ID_SERVER_RETRY_TIMER_EVENT)
514 {
515 	connectedsocket = NULL;
516 	used_list = in_serverlist;
517 	max_simcons = (thePrefs::IsSafeServerConnectEnabled()) ? 1 : 2;
518 	connecting = false;
519 	connected = false;
520 	clientid = 0;
521 	singleconnecting = false;
522 	m_recurseTryAnotherConnectionrequest = false;
523 	m_bTryObfuscated = thePrefs::IsServerCryptLayerTCPRequested();
524 
525 	// initalize socket for udp packets
526 	if (thePrefs::GetNetworkED2K()) {
527 		serverudpsocket = new CServerUDPSocket(address, thePrefs::GetProxyData());
528 	} else {
529 		serverudpsocket = NULL;
530 	}
531 }
532 
533 
~CServerConnect()534 CServerConnect::~CServerConnect()
535 {
536 	m_idRetryTimer.Stop();
537 	// stop all connections
538 	StopConnectionTry();
539 	// close connected socket, if any
540 	DestroySocket(connectedsocket);
541 	connectedsocket = NULL;
542 	// close udp socket
543 	delete serverudpsocket;
544 }
545 
546 
GetCurrentServer()547 CServer* CServerConnect::GetCurrentServer()
548 {
549 	if (IsConnected() && connectedsocket) {
550 		return connectedsocket->cur_server;
551 	}
552 	return NULL;
553 }
554 
555 
SetClientID(uint32 newid)556 void CServerConnect::SetClientID(uint32 newid)
557 {
558 	clientid = newid;
559 
560 	if (!::IsLowID(newid)) {
561 		theApp->SetPublicIP(newid);
562 	}
563 }
564 
565 
DestroySocket(CServerSocket * pSck)566 void CServerConnect::DestroySocket(CServerSocket* pSck)
567 {
568 	if (pSck == NULL) {
569 		return;
570 	}
571 	m_lstOpenSockets.remove(pSck);
572 	pSck->Destroy();
573 }
574 
575 
IsLocalServer(uint32 dwIP,uint16 nPort)576 bool CServerConnect::IsLocalServer(uint32 dwIP, uint16 nPort)
577 {
578 	if (IsConnected()){
579 		if (connectedsocket->cur_server->GetIP() == dwIP && connectedsocket->cur_server->GetPort() == nPort)
580 			return true;
581 	}
582 	return false;
583 }
584 
585 
KeepConnectionAlive()586 void CServerConnect::KeepConnectionAlive()
587 {
588 	uint32 dwServerKeepAliveTimeout = thePrefs::GetServerKeepAliveTimeout();
589 	if (dwServerKeepAliveTimeout && connected && connectedsocket &&
590 	connectedsocket->connectionstate == CS_CONNECTED &&
591 	GetTickCount() - connectedsocket->GetLastTransmission() >= dwServerKeepAliveTimeout) {
592 		// "Ping" the server if the TCP connection was not used for the specified interval with
593 		// an empty publish files packet -> recommended by lugdunummaster himself!
594 
595 		CMemFile files(4);
596 		files.WriteUInt32(0); //nFiles
597 
598 		CPacket* packet = new CPacket(files, OP_EDONKEYPROT, OP_OFFERFILES);
599 		#ifdef DEBUG_CLIENT_PROTOCOL
600 		AddLogLineC(wxT("Client: OP_OFFERFILES"));
601 		#endif
602 		// compress packet
603 		//   - this kind of data is highly compressable (N * (1 MD4 and at least 3 string meta data tags and 1 integer meta data tag))
604 		//   - the min. amount of data needed for one published file is ~100 bytes
605 		//   - this function is called once when connecting to a server and when a file becomes shareable - so, it's called rarely.
606 		//   - if the compressed size is still >= the original size, we send the uncompressed packet
607 		// therefor we always try to compress the packet
608 		theStats::AddUpOverheadServer(packet->GetPacketSize());
609 		connectedsocket->SendPacket(packet,true);
610 
611 		AddDebugLogLineN(logServer, wxT("Refreshing server connection"));
612 	}
613 }
614 
615 // true if the IP is one of a server which we currently try to connect to
AwaitingTestFromIP(uint32 dwIP)616 bool CServerConnect::AwaitingTestFromIP(uint32 dwIP)
617 {
618 	ServerSocketMap::iterator it = connectionattemps.begin();
619 
620 	while (it != connectionattemps.end()) {
621 		const CServerSocket* serversocket = it->second;
622 		if (serversocket && (serversocket->GetConnectionState() == CS_WAITFORLOGIN) &&
623 			(serversocket->GetServerIP() == dwIP)) {
624 			return true;
625 		}
626 		++it;
627 	}
628 
629 	return false;
630 }
631 
632 
IsConnectedObfuscated() const633 bool CServerConnect::IsConnectedObfuscated() const
634 {
635 	return connectedsocket != NULL && connectedsocket->IsObfusicating();
636 }
637 
638 
OnServerHostnameResolved(void * socket,uint32 ip)639 void CServerConnect::OnServerHostnameResolved(void* socket, uint32 ip)
640 {
641 	// The socket object might have been deleted while we waited for the hostname
642 	// to be resolved, so we check if it's still among the open sockets.
643 	SocketsList::iterator it = std::find(m_lstOpenSockets.begin(), m_lstOpenSockets.end(), socket);
644 	if (it != m_lstOpenSockets.end()) {
645 		(*it)->OnHostnameResolved(ip);
646 	} else {
647 		AddLogLineNS(_("Received late result of DNS lookup, discarding."));
648 	}
649 }
650 
651 
652 // File_checked_for_headers
653