1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10 
11 
12 // Common networking routines to help us
13 // Created 18/12/02
14 // Jason Boettcher
15 
16 #include <memory.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <errno.h>
20 
21 #include <curl/curl.h>
22 
23 #include "ThreadPool.h"
24 #ifndef WIN32
25 #include <signal.h>
26 #endif
27 
28 #include "LieroX.h"
29 #include "Debug.h"
30 #include "Options.h"
31 #include "Error.h"
32 #include "Networking.h"
33 #include "StringUtils.h"
34 #include "SmartPointer.h"
35 #include "Timer.h"
36 #include "ThreadVar.h"
37 #include "MathLib.h"
38 #include "InputEvents.h"
39 #include "TaskManager.h"
40 #include "ReadWriteLock.h"
41 #include "Mutex.h"
42 
43 
44 #ifdef _MSC_VER
45 #pragma warning(disable: 4786)
46 #endif
47 
48 #include <map>
49 
50 #include <nl.h>
51 #include <nlinternal.h>
52 // workaraound for bad named makros by nl.h
53 // macros are bad, esp the names (reserved/used by CBytestream)
54 // TODO: they seem to not work correctly!
55 // all use of it in CBytestream was removed
nl_writeShort(char * x,int & y,NLushort z)56 inline void nl_writeShort(char* x, int& y, NLushort z)		{ writeShort(x, y, z); }
nl_writeLong(char * x,int & y,NLulong z)57 inline void nl_writeLong(char* x, int& y, NLulong z)		{ writeLong(x, y, z); }
nl_writeFloat(char * x,int & y,NLfloat z)58 inline void nl_writeFloat(char* x, int& y, NLfloat z)		{ writeFloat(x, y, z); }
nl_writeDouble(char * x,int & y,NLdouble z)59 inline void nl_writeDouble(char* x, int& y, NLdouble z)		{ writeDouble(x, y, z); }
nl_readShort(char * x,int & y,NLushort z)60 inline void nl_readShort(char* x, int& y, NLushort z)		{ readShort(x, y, z); }
nl_readLong(char * x,int & y,NLulong z)61 inline void nl_readLong(char* x, int& y, NLulong z)			{ readLong(x, y, z); }
nl_readFloat(char * x,int & y,NLfloat z)62 inline void nl_readFloat(char* x, int& y, NLfloat z)		{ readFloat(x, y, z); }
nl_readDouble(char * x,int & y,NLdouble z)63 inline void nl_readDouble(char* x, int& y, NLdouble z)		{ readDouble(x, y, z); }
64 #undef writeByte
65 #undef writeShort
66 #undef writeFloat
67 #undef writeString
68 #undef readByte
69 #undef readShort
70 #undef readFloat
71 #undef readString
72 
73 
74 #if defined WIN32 || defined WIN64 || defined (_WIN32_WCE)
75 
76 #include "wsock.h"
77 
78 #elif defined Macintosh
79 
80 #include <Types.h>
81 #include <stdio.h>
82 #include <fcntl.h>
83 #include <sys/ioctl.h>
84 #include <sys/types.h>
85 #include <sys/socket.h>
86 #include <string.h>
87 #include <sys/time.h>
88 #include <LowMem.h>
89 #define closesocket close
90 #define INVALID_SOCKET -1
91 #define SOCKET_ERROR -1
92 #define SOCKET int
93 #define sockerrno errno
94 
95 /* define INADDR_NONE if not already */
96 #ifndef INADDR_NONE
97 #define INADDR_NONE ((unsigned long) -1)
98 #endif
99 
100 #else
101 
102  /* Unix-style systems */
103 #ifdef SOLARIS
104 #include <sys/filio.h> /* for FIONBIO */
105 #endif
106 
107 #include <unistd.h>
108 #include <sys/types.h>
109 #include <sys/time.h>
110 #include <sys/socket.h>
111 #include <netinet/in.h>
112 #include <netinet/tcp.h>
113 #include <arpa/inet.h>
114 #include <netdb.h>
115 #include <sys/ioctl.h>
116 #define closesocket close
117 #define INVALID_SOCKET -1
118 #define SOCKET_ERROR -1
119 #define SOCKET int
120 #define sockerrno errno
121 
122  /* define INADDR_NONE if not already */
123 #ifndef INADDR_NONE
124 #define INADDR_NONE ((unsigned long) -1)
125 #endif
126 
127 /* SGI do not include socklen_t */
128 #if defined __sgi
129 typedef int socklen_t;
130 #endif
131 
132 #endif /* WINDOWS_APP*/
133 
134 
135 
136 class NetAddrIniter {
137 public:
operator ()(SmartPointer<NLaddress,NetAddrIniter> * addr)138 	void operator()(SmartPointer<NLaddress, NetAddrIniter>* addr) {
139 		NLaddress* addrPtr = new NLaddress;
140 		memset(addrPtr, 0, sizeof(NLaddress));
141 		*addr = addrPtr;
142 	}
143 };
144 
AreNetworkAddrEqual(const NetworkAddr & addr1,const NetworkAddr & addr2)145 bool AreNetworkAddrEqual(const NetworkAddr& addr1, const NetworkAddr& addr2)
146 {
147 	return AreNetAddrEqual(addr1, addr2);
148 };
149 
150 class NetAddrInternal
151 {
152 	public:
NetAddrInternal()153 	NetAddrInternal() {};
NetAddrInternal(const NetAddrInternal & other)154 	NetAddrInternal(const NetAddrInternal & other)
155 	{
156 		*this = other;
157 	};
158 
operator =(const NetAddrInternal & other)159 	const NetAddrInternal & operator= (const NetAddrInternal & other)
160 	{
161 		*NetAddrSmartPtr.get() = *other.NetAddrSmartPtr.get();
162 		return *this;
163 	}
164 
operator =(const NLaddress & addr)165 	const NetAddrInternal & operator= (const NLaddress & addr)
166 	{
167 		*NetAddrSmartPtr.get() = addr;
168 		return *this;
169 	}
170 
NetAddrInternal(const NLaddress & addr)171 	NetAddrInternal(const NLaddress & addr)
172 	{
173 		*this = addr;
174 	};
175 
176 	typedef SmartPointer<NLaddress, NetAddrIniter> Ptr_t;
177 
getPtr() const178 	const Ptr_t & getPtr() const
179 	{
180 		return NetAddrSmartPtr;
181 	}
182 
183 	private:
184 	Ptr_t NetAddrSmartPtr;
185 };
186 
187 DECLARE_INTERNDATA_CLASS( NetworkAddr, NetAddrInternal );
188 
getNLaddr(NetworkAddr & addr)189 static NLaddress* getNLaddr(NetworkAddr& addr) {
190 	return NetworkAddrData(addr).getPtr().get();
191 }
192 
getNLaddr(const NetworkAddr & addr)193 static const NLaddress* getNLaddr(const NetworkAddr& addr) {
194 	return NetworkAddrData(addr).getPtr().get();
195 }
196 
197 
198 // ------------------------------------------------------------------------
199 
200 
201 #ifndef WIN32
sigpipe_handler(int i)202 static void sigpipe_handler(int i) {
203 	warnings << "got SIGPIPE, ignoring..." << endl;
204 	signal(SIGPIPE, sigpipe_handler);
205 }
206 #endif
207 
208 
209 /*
210  *
211  * HawkNL Network wrapper
212  *
213  */
214 
215 
216 bool bNetworkInited = false;
217 ReadWriteLock nlSystemUseChangeLock;
218 
219 
220 typedef std::map<std::string, std::pair< NLaddress, AbsTime > > dnsCacheT; // Second parameter is expiration time of DNS record
221 ThreadVar<dnsCacheT>* dnsCache4 = NULL;
222 ThreadVar<dnsCacheT>* dnsCache6 = NULL;
223 
AddToDnsCache4(const std::string & name,const NetworkAddr & addr,TimeDiff expireTime=TimeDiff (600.0f))224 static void AddToDnsCache4(const std::string& name, const NetworkAddr& addr, TimeDiff expireTime = TimeDiff(600.0f)) {
225 	ScopedReadLock lock(nlSystemUseChangeLock);
226 	if(dnsCache4 == NULL) return;
227 	ThreadVar<dnsCacheT>::Writer dns( *dnsCache4 );
228 	dns.get()[name] = std::make_pair( *getNLaddr(addr), GetTime() + expireTime );
229 }
230 
AddToDnsCache6(const std::string & name,const NetworkAddr & addr,TimeDiff expireTime=TimeDiff (600.0f))231 static void AddToDnsCache6(const std::string& name, const NetworkAddr& addr, TimeDiff expireTime = TimeDiff(600.0f)) {
232 	ScopedReadLock lock(nlSystemUseChangeLock);
233 	if(dnsCache6 == NULL) return;
234 	ThreadVar<dnsCacheT>::Writer dns6( *dnsCache6 );
235 	dns6.get()[name] = std::make_pair( *getNLaddr(addr), GetTime() + expireTime );
236 }
237 
GetFromDnsCache(const std::string & name,NetworkAddr & addr4,NetworkAddr & addr6)238 bool GetFromDnsCache(const std::string& name, NetworkAddr& addr4, NetworkAddr& addr6) {
239 
240 	getNLaddr(addr4)->valid = NL_FALSE;
241 	getNLaddr(addr6)->valid = NL_FALSE;
242 
243 	if (IsNetAddrV6(name) && StringToNetAddr(name, addr6)) {
244 		return true;
245 	}
246 	if (StringToNetAddr(name, addr4)) {
247 		return true;
248 	}
249 
250 	ScopedReadLock lock(nlSystemUseChangeLock);
251 	if(dnsCache4 == NULL) return false;
252 	if(dnsCache6 == NULL) return false;
253 	bool v4 = false, v6 = false;
254 	ThreadVar<dnsCacheT>::Writer dns( *dnsCache4 );
255 	dnsCacheT::iterator it = dns.get().find(name);
256 	if(it != dns.get().end()) {
257 		if( it->second.second < tLX->currentTime )
258 		{
259 			dns.get().erase(it);
260 		}
261 		else
262 		{
263 			*getNLaddr(addr4) = it->second.first;
264 			v4 = true;
265 		}
266 	}
267 	ThreadVar<dnsCacheT>::Writer dns6( *dnsCache6 );
268 	it = dns6.get().find(name);
269 	if(it != dns6.get().end()) {
270 		if( it->second.second < tLX->currentTime )
271 		{
272 			dns6.get().erase(it);
273 		}
274 		else
275 		{
276 			*getNLaddr(addr6) = it->second.first;
277 			v6 = true;
278 		}
279 	}
280 	return v4 && v6; // Cache needs both address families to be present to consider an entry valid
281 }
282 
283 
284 
285 /////////////////////
286 // Initializes network
InitNetworkSystem()287 bool InitNetworkSystem() {
288 	curl_global_init(CURL_GLOBAL_ALL);
289 	nlSystemUseChangeLock.startWriteAccess();
290 	bNetworkInited = false;
291 
292     if(!nlInit()) {
293     	SystemError("nlInit failed");
294 		nlSystemUseChangeLock.endWriteAccess();
295     	return false;
296     }
297 
298     if(!nlSelectNetwork(NL_IP)) {
299         SystemError("could not select IP-based network");
300 		nlSystemUseChangeLock.endWriteAccess();
301 		return false;
302     }
303 
304 	bNetworkInited = true;
305 
306 	dnsCache4 = new ThreadVar<dnsCacheT>();
307 	dnsCache6 = new ThreadVar<dnsCacheT>();
308 
309 #if !defined(WIN32) && !defined(__ANDROID__)
310 	//sigignore(SIGPIPE);
311 	signal(SIGPIPE, sigpipe_handler);
312 #endif
313 
314 	nlSystemUseChangeLock.endWriteAccess();
315 	return true;
316 }
317 
318 //////////////////
319 // Shutdowns the network system
QuitNetworkSystem()320 bool QuitNetworkSystem() {
321 	nlSystemUseChangeLock.startWriteAccess();
322 	nlShutdown();
323 	bNetworkInited = false;
324 	delete dnsCache4; dnsCache4 = NULL;
325 	delete dnsCache6; dnsCache6 = NULL;
326 	nlSystemUseChangeLock.endWriteAccess();
327 	curl_global_cleanup();
328 	return true;
329 }
330 
331 
332 /*
333 Sadly, HawkNL lacks some support for specific things. For example we cannot get the real socket nr.
334 
335 Atm., we are doing these:
336 
337 nlUpdateState
338 nlPrepareClose
339 
340 */
341 
342 // ---------------------------------------------------
343 // ----------- for state checking -------------------
344 
345 // WARNING: both these function assume that we selected the IP-network driver in HawkNL
346 
347 // modified sock_Write of sock.c from HawkNL
348 // returns true if socket is connected and data could be send
nlUpdateState(NLsocket socket)349 static bool nlUpdateState(NLsocket socket)
350 {
351 	if(nlIsValidSocket(socket) != NL_TRUE) return false;
352 
353 	struct Unlocker {
354 		NLsocket socket;
355 		~Unlocker() {
356 			nlUnlockSocket(socket, NL_BOTH);
357 		}
358 		Unlocker(NLsocket s) : socket(s) {}
359 	};
360 
361 	if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
362 	{
363 		return false;
364 	}
365 
366 	Unlocker unlocker(socket);
367 
368 	nl_socket_t *sock = nlSockets[socket];
369 	NLint       count = 0;
370 
371 	if((sock->type == NL_RELIABLE) || (sock->type == NL_RELIABLE_PACKETS)) /* TCP */
372 	{
373 		if(sock->connecting == NL_TRUE)
374 		{
375 			fd_set          fdset;
376 			struct timeval  t = {0,0};
377 			int             serrval = -1;
378 			socklen_t       serrsize = (socklen_t)sizeof(serrval);
379 
380 
381 			FD_ZERO(&fdset);
382 			FD_SET((SOCKET)sock->realsocket, &fdset);
383 			if(select(sock->realsocket + 1, NULL, &fdset, NULL, &t) == 1)
384 			{
385 				/* Check the socket status */
386 				(void)getsockopt( sock->realsocket, SOL_SOCKET, SO_ERROR, (char *)&serrval, &serrsize );
387 				if(serrval != 0)
388 				{
389 					if(serrval == ECONNREFUSED)
390 					{
391 						nlSetError(NL_CON_REFUSED);
392 					}
393 					else if(serrval == EINPROGRESS || serrval == EWOULDBLOCK)
394 					{
395 						nlSetError(NL_CON_PENDING);
396 					}
397 					return false;
398 				}
399 				/* the connect has completed */
400 				sock->connected = NL_TRUE;
401 				sock->connecting = NL_FALSE;
402 			}
403 			else
404 			{
405 				/* check for a failed connect */
406 				FD_ZERO(&fdset);
407 				FD_SET((SOCKET)sock->realsocket, &fdset);
408 				if(select(sock->realsocket + 1, NULL, NULL, &fdset, &t) == 1)
409 				{
410 					nlSetError(NL_CON_REFUSED);
411 				}
412 				else
413 				{
414 					nlSetError(NL_CON_PENDING);
415 				}
416 				return false;
417 			}
418 		}
419 		/* check for reliable packets */
420 		if(sock->type == NL_RELIABLE_PACKETS)
421 		{
422 			return true;
423 		}
424 		return true;
425 	}
426 	else /* unconnected UDP */
427 	{
428 		/* check for a non-blocking connection pending */
429 		if(sock->connecting == NL_TRUE)
430 		{
431 			nlSetError(NL_CON_PENDING);
432 			return false;
433 		}
434 		/* check for a connection error */
435 		if(sock->conerror == NL_TRUE)
436 		{
437 			nlSetError(NL_CON_REFUSED);
438 			return false;
439 		}
440 		if(sock->type == NL_BROADCAST)
441 		{
442 			memcpy(&((struct sockaddr_in6 *)&sock->addressin)->sin6_addr, &in6addr_any, sizeof(in6addr_any));
443 		}
444 		if(sock->type == NL_UDP_MULTICAST)
445 		{
446 			return true;
447 		}
448 		else if(sock->connected == NL_TRUE)
449 		{
450 			return true;
451 		}
452 		else
453 		{
454 			return true;
455 		}
456 	}
457 	if(count == SOCKET_ERROR)
458 	{
459 		return false;
460 	}
461 	return false;
462 }
463 
464 
nlPrepareClose(NLsocket socket)465 static void nlPrepareClose(NLsocket socket) {
466 	if(nlIsValidSocket(socket) != NL_TRUE) return;
467 
468 	struct Unlocker {
469 		NLsocket socket;
470 		~Unlocker() {
471 			nlUnlockSocket(socket, NL_BOTH);
472 		}
473 		Unlocker(NLsocket s) : socket(s) {}
474 	};
475 
476 	if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
477 	{
478 		return;
479 	}
480 
481 	Unlocker unlocker(socket);
482 
483 	// code copied&modified from sock_Close
484 	// The advantage we have here is that we don't lock the whole socket array.
485 	// nlClose is doing this, so if we would hang in nlClose, we block the
486 	// *whole* HawkNL system (or at least actions like opening new sockets etc.)!
487 
488 	nl_socket_t     *sock = nlSockets[socket];
489 
490 	if(sock->type == NL_UDP_MULTICAST)
491 	{
492 		/* leave the multicast group */
493 	}
494 	if(sock->type == NL_RELIABLE_PACKETS)
495 	{
496 		/* check for unsent data */
497 		if(sock->sendlen > 0)
498 		{
499 			int tries = 200;
500 
501 			/* 200 * 50 ms = up to a 10 second delay to allow data to be sent */
502 			while(tries-- > 0 && sock->sendlen > 0)
503 			{
504 				SDL_Delay(50);
505 			}
506 		}
507 
508 		// oh just fuck it
509 		sock->sendlen = 0;
510 	}
511 	if((sock->type == NL_RELIABLE_PACKETS || sock->type == NL_RELIABLE) && sock->listen == NL_FALSE)
512 	{
513 		struct linger l = {1, 10};
514 
515 		(void)setsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_LINGER, (const char *)&l, (int)sizeof(l));
516 	}
517 	(void)closesocket((SOCKET)sock->realsocket);
518 }
519 
520 
521 
522 
523 
524 struct NetworkSocket::EventHandler {
525 	struct SharedData {
526 		Mutex mutex;
527 		bool quitSignal;
528 		NetworkSocket* sock;
529 		NLint nlGroup;
530 
SharedDataNetworkSocket::EventHandler::SharedData531 		SharedData(NetworkSocket* _s) : quitSignal(false), sock(_s) {
532 			nlGroup = nlGroupCreate();
533 			addSocketToGroup();
534 		}
535 
536 		void addSocketToGroup();
537 
~SharedDataNetworkSocket::EventHandler::SharedData538 		~SharedData() { nlGroupDestroy(nlGroup); nlGroup = NL_INVALID; }
539 	};
540 	SmartPointer<SharedData> sharedData;
541 
542 	EventHandler(NetworkSocket* sock);
543 
quitNetworkSocket::EventHandler544 	void quit() {
545 		if(sharedData.get()) {
546 			Mutex::ScopedLock lock(sharedData->mutex);
547 			sharedData->quitSignal = true;
548 			sharedData->sock = NULL;
549 		}
550 	}
551 
~EventHandlerNetworkSocket::EventHandler552 	~EventHandler() {
553 		// just to be sure
554 		quit();
555 		sharedData = NULL;
556 	}
557 };
558 
559 struct NetworkSocket::InternSocket {
560 	NLsocket sock;
561 	SmartPointer<EventHandler> eventHandler;
562 
InternSocketNetworkSocket::InternSocket563 	InternSocket() : sock(NL_INVALID) {}
~InternSocketNetworkSocket::InternSocket564 	~InternSocket() {
565 		// just a double check - there really shouldn't be a case where this could be true
566 		if(eventHandler.get()) {
567 			errors << "NetworkSocket::~InternSocket: event handler was not unset" << endl;
568 			eventHandler->quit();
569 			eventHandler = NULL;
570 		}
571 	}
572 };
573 
addSocketToGroup()574 void NetworkSocket::EventHandler::SharedData::addSocketToGroup() {
575 	nlGroupAddSocket(nlGroup, sock->m_socket->sock);
576 }
577 
EventHandler(NetworkSocket * sock)578 NetworkSocket::EventHandler::EventHandler(NetworkSocket* sock) {
579 	if(!sock) {
580 		errors << "NetworkSocket::EventHandler: socket == NULL" << endl;
581 		return;
582 	}
583 
584 	if(!sock->isOpen()) {
585 		errors << "NetworkSocket::EventHandler: socket is closed" << endl;
586 		return;
587 	}
588 
589 	struct EventHandlerThread : Action {
590 		SmartPointer<SharedData> sharedData;
591 		uint pollType; // NL_READ_STATUS or NL_ERROR_STATUS
592 
593 		EventHandlerThread(const SmartPointer<SharedData>& _data, uint _pollType) :
594 		sharedData(_data), pollType(_pollType) {}
595 
596 		bool pushNewDataEvent() {
597 			Mutex::ScopedLock lock(sharedData->mutex);
598 			if(sharedData->sock) {
599 				sharedData->sock->OnNewData.pushToMainQueue(EventData(sharedData->sock));
600 				return true;
601 			}
602 			return false;
603 		}
604 
605 		bool pushErrorEvent() {
606 			Mutex::ScopedLock lock(sharedData->mutex);
607 			if(sharedData->sock) {
608 				sharedData->sock->OnError.pushToMainQueue(EventData(sharedData->sock));
609 				return true;
610 			}
611 			return false;
612 		}
613 
614 		int handle() {
615 			const int maxFPS = tLXOptions ? tLXOptions->nMaxFPS : 100;
616 			TimeDiff max_frame_time = TimeDiff(MAX(0.01f, (maxFPS > 0) ? 1.0f/(float)maxFPS : 0.0f));
617 			AbsTime lastTime = GetTime();
618 
619 			while(!sharedData->quitSignal) {
620 				NLsocket s;
621 				NLint ret = nlPollGroup(sharedData->nlGroup, pollType, &s, /* amount of sockets */ 1, /* timeout */ max_frame_time.milliseconds());
622 				// if no error, ret is amount of sockets which triggered the event
623 
624 				if(ret > 0) {
625 					switch(pollType) {
626 						case NL_READ_STATUS: if(!pushNewDataEvent()) return -1; break;
627 						case NL_ERROR_STATUS: if(!pushErrorEvent()) return -1; break;
628 					}
629 				}
630 
631 				AbsTime curTime = GetTime();
632 				if(curTime - lastTime < max_frame_time) {
633 					SDL_Delay( (Uint32)( ( max_frame_time - (curTime - lastTime) ).milliseconds() ) );
634 				}
635 				lastTime = curTime;
636 			}
637 
638 			return 0;
639 		}
640 	};
641 
642 	sharedData = new SharedData(sock);
643 	threadPool->start(new EventHandlerThread(sharedData, NL_READ_STATUS), "socket " + itoa(sock->m_socket->sock) + " read event checker", true);
644 	threadPool->start(new EventHandlerThread(sharedData, NL_ERROR_STATUS), "socket " + itoa(sock->m_socket->sock) + " error event checker", true);
645 }
646 
NetworkSocket()647 NetworkSocket::NetworkSocket() : m_type(NST_INVALID), m_state(NSS_NONE), m_withEvents(false), m_socket(NULL) {
648 	m_socket = new InternSocket();
649 }
650 
~NetworkSocket()651 NetworkSocket::~NetworkSocket() {
652 	Clear();
653 	delete m_socket;
654 	m_socket = NULL;
655 }
656 
setWithEvents(bool v)657 void NetworkSocket::setWithEvents( bool v )
658 {
659 	if( v == m_withEvents ) return;
660 	m_withEvents = v;
661 	checkEventHandling();
662 }
663 
checkEventHandling()664 void NetworkSocket::checkEventHandling() {
665 	if(isOpen() && m_withEvents) {
666 		// we must have an event handler
667 		if(m_socket->eventHandler.get() == NULL) {
668 			m_socket->eventHandler = new EventHandler(this);
669 		}
670 	}
671 	else {
672 		// we must not have an event handler
673 		if(m_socket->eventHandler.get()) {
674 			m_socket->eventHandler->quit();
675 			m_socket->eventHandler = NULL;
676 		}
677 	}
678 }
679 
debugString() const680 std::string NetworkSocket::debugString() const {
681 	if(!isOpen()) return "Closed";
682 	std::string ret = TypeStr(m_type) + "/" + StateStr(m_state);
683 	{
684 		std::string localStr = "INVALIDLOCAL";
685 		NetworkAddr addr;
686 		if(nlGetLocalAddr(m_socket->sock, getNLaddr(addr)) != NL_FALSE)
687 			NetAddrToString(addr, localStr);
688 		else {
689 			localStr = "ERRORLOCALADDR(" + GetLastErrorStr() + ")";
690 			ResetSocketError();
691 		}
692 		ret += " " + localStr;
693 	}
694 	if(m_state == NSS_CONNECTED) {
695 		ret += " connected to ";
696 		std::string remoteStr = "INVALIDREMOTE";
697 		NetworkAddr addr;
698 		if(nlGetRemoteAddr(m_socket->sock, getNLaddr(addr)) != NL_FALSE)
699 			NetAddrToString(remoteAddress(), remoteStr);
700 		else {
701 			remoteStr = "ERRORREMOTEADDR(" + GetLastErrorStr() + ")";
702 			ResetSocketError();
703 		}
704 		ret += remoteStr;
705 	}
706 	return ret;
707 }
708 
OpenReliable(Port port)709 bool NetworkSocket::OpenReliable(Port port) {
710 	if(isOpen()) {
711 		warnings << "NetworkSocket " << debugString() << ": OpenReliable: socket is already opened, reopening now" << endl;
712 		Close();
713 	}
714 
715 	NLsocket ret = nlOpen(port, NL_RELIABLE);
716 	if (ret == NL_INVALID)  {
717 #ifdef DEBUG
718 		errors << "OpenReliableSocket: " << GetLastErrorStr() << endl;
719 #endif
720 		ResetSocketError();
721 		return false;
722 	}
723 	m_socket->sock = ret;
724 	m_type = NST_TCP;
725 	m_state = NSS_NONE;
726 	checkEventHandling();
727 	return true;
728 }
729 
OpenUnreliable(Port port)730 bool NetworkSocket::OpenUnreliable(Port port) {
731 	if(isOpen()) {
732 		warnings << "NetworkSocket " << debugString() << ": OpenReliable: socket is already opened, reopening now" << endl;
733 		Close();
734 	}
735 
736 	NLsocket ret = nlOpen(port, NL_UNRELIABLE);
737 	if (ret == NL_INVALID)  {
738 #ifdef DEBUG
739 		errors << "OpenUnreliableSocket: " << GetLastErrorStr() << endl;
740 #endif
741 		ResetSocketError();
742 		return false;
743 	}
744 	m_socket->sock = ret;
745 	m_type = NST_UDP;
746 	m_state = NSS_NONE;
747 	checkEventHandling();
748 	return true;
749 }
750 
OpenBroadcast(Port port)751 bool NetworkSocket::OpenBroadcast(Port port) {
752 	if(isOpen()) {
753 		warnings << "NetworkSocket " << debugString() << ": OpenBroadcast: socket is already opened, reopening now" << endl;
754 		Close();
755 	}
756 
757 	NLsocket ret = nlOpen(port, NL_BROADCAST);
758 	if (ret == NL_INVALID)  {
759 #ifdef DEBUG
760 		errors << "OpenBroadcastSocket: " << GetLastErrorStr() << endl;
761 #endif
762 		ResetSocketError();
763 		return false;
764 	}
765 	m_socket->sock = ret;
766 	m_type = NST_UDPBROADCAST;
767 	m_state = NSS_NONE;
768 	checkEventHandling();
769 	return true;
770 }
771 
Connect(const NetworkAddr & addr)772 bool NetworkSocket::Connect(const NetworkAddr& addr) {
773 	if(!isOpen()) {
774 		errors << "NetworkSocket::Connect: socket is closed" << endl;
775 		return false;
776 	}
777 
778 	if(m_type != NST_TCP) {
779 		errors << "NetworkSocket::Connect " << debugString() << ": connect only works with TCP" << endl;
780 		return false;
781 	}
782 
783 	if(nlConnect(m_socket->sock, getNLaddr(addr)) == NL_FALSE) {
784 #ifdef DEBUG
785 		errors << "Connect: " << GetLastErrorStr() << endl;
786 #endif
787 		ResetSocketError();
788 		return false;
789 	}
790 
791 	checkEventHandling();
792 	return true;
793 }
794 
Listen()795 bool NetworkSocket::Listen() {
796 	if(!isOpen()) {
797 		errors << "NetworkSocket::Listen: socket is closed" << endl;
798 		return false;
799 	}
800 
801 	if(nlListen(m_socket->sock) == NL_FALSE) {
802 #ifdef DEBUG
803 		errors << "Listen: " << GetLastErrorStr() << endl;
804 #endif
805 		ResetSocketError();
806 		return false;
807 	}
808 
809 	checkEventHandling();
810 	return true;
811 }
812 
Close()813 void NetworkSocket::Close() {
814 	if(!isOpen()) {
815 		warnings << "NetworkSocket::Close: cannot close already closed socket" << endl;
816 		return;
817 	}
818 
819 	struct CloseSocketWorker : Task {
820 		NLsocket sock;
821 		int handle() {
822 			nlSystemUseChangeLock.startReadAccess();
823 			int ret = -1;
824 			if(bNetworkInited) { // only do that if we have the network system still up
825 				// this should already close the socket but not lock other parts in HawkNL
826 				nlPrepareClose(sock);
827 				// hopefully this does not block anymore
828 				ret = (nlClose(sock) != NL_FALSE) ? 0 : -1;
829 			}
830 			nlSystemUseChangeLock.endReadAccess();
831 			return ret;
832 		}
833 	};
834 	CloseSocketWorker* worker = new CloseSocketWorker();
835 	worker->name = "close socket";
836 	worker->sock = m_socket->sock;
837 	taskManager->start(worker);
838 
839 	m_socket->sock = NL_INVALID;
840 	m_type = NST_INVALID;
841 	m_state = NSS_NONE;
842 
843 	checkEventHandling();
844 }
845 
Write(const void * buffer,int nbytes)846 int NetworkSocket::Write(const void* buffer, int nbytes) {
847 	if(!isOpen()) {
848 		errors << "NetworkSocket::Write: cannot write on closed socket" << endl;
849 		return NL_INVALID;
850 	}
851 
852 	ResetSocketError();
853 	NLint ret = nlWrite(m_socket->sock, buffer, nbytes);
854 
855 	// Error checking
856 	if (ret == NL_INVALID)  {
857 #ifdef DEBUG
858 		std::string errStr = GetLastErrorStr(); // cache errStr that debugString will not overwrite it
859 		warnings << "WriteSocket " << debugString() << ": " << errStr << endl;
860 #endif // DEBUG
861 		return NL_INVALID;
862 	}
863 
864 	/*if (ret == 0) {  // HINT: this is not an error, it is one of the ways to find out if a socket is writeable
865 		errors << "WriteSocket: Could not send the packet, network buffers are full." << endl;
866 	}*/
867 
868 	return ret;
869 }
870 
871 
Read(void * buffer,int nbytes)872 int NetworkSocket::Read(void* buffer, int nbytes) {
873 	if(!isOpen()) {
874 		errors << "NetworkSocket::Read: cannot read on closed socket" << endl;
875 		return NL_INVALID;
876 	}
877 
878 	ResetSocketError();
879 	NLint ret = nlRead(m_socket->sock, buffer, nbytes);
880 
881 	// Error checking
882 	if (ret == NL_INVALID)  {
883 		// messageend-error is just that there is no data; we can ignore that
884 		if (!IsMessageEndSocketErrorNr(GetSocketErrorNr())) {
885 #ifdef DEBUG
886 			std::string errStr = GetLastErrorStr(); // cache errStr that debugString will not overwrite it
887 			errors << "ReadSocket " << debugString() << ": " << errStr << endl;
888 #endif // DEBUG
889 
890 			// Is this perhaps the solution for the Bad file descriptor error?
891 			//Close();
892 		}
893 		return NL_INVALID;
894 	}
895 
896 	return ret;
897 }
898 
899 
900 
901 
902 
isReady() const903 bool NetworkSocket::isReady() const {
904 	return isOpen() && nlUpdateState(m_socket->sock);
905 }
906 
907 
908 // TODO: Remove the following functions because they are blocking.
909 
910 /////////////////////
911 // Wait until the socket is writable
912 // TODO: remove this function, don't use it!
WaitForSocketWrite(int timeout)913 void NetworkSocket::WaitForSocketWrite(int timeout)
914 {
915 	if(!isOpen()) {
916 		errors << "WaitForSocketWrite: socket closed" << endl;
917 		return;
918 	}
919 
920 	NLint group = nlGroupCreate();
921 	nlGroupAddSocket(group, m_socket->sock);
922 	NLsocket s;
923 	nlPollGroup(group, NL_WRITE_STATUS, &s, 1, (NLint)timeout);
924 	nlGroupDestroy(group);
925 }
926 
927 //////////////////////
928 // Wait until the socket contains some data to read
929 // TODO: remove this function, don't use it!
WaitForSocketRead(int timeout)930 void NetworkSocket::WaitForSocketRead(int timeout)
931 {
932 	if(!isOpen()) {
933 		errors << "WaitForSocketRead: socket closed" << endl;
934 		return;
935 	}
936 
937 	NLint group = nlGroupCreate();
938 	nlGroupAddSocket(group, m_socket->sock);
939 	NLsocket s;
940 	nlPollGroup(group, NL_READ_STATUS, &s, 1, (NLint)timeout);
941 	nlGroupDestroy(group);
942 }
943 
944 /////////////////////
945 // Wait until the socket contains some data or is writeable
946 // TODO: remove this function, don't use it!
WaitForSocketReadOrWrite(int timeout)947 void NetworkSocket::WaitForSocketReadOrWrite(int timeout)
948 {
949 	if(!isOpen()) {
950 		errors << "WaitForSocketReadOrWrite: socket closed" << endl;
951 		return;
952 	}
953 
954 	NLint group = nlGroupCreate();
955 	nlGroupAddSocket(group, m_socket->sock);
956 	NLsocket s;
957 
958 	if (timeout < 0)  {
959 		// Infinite timeout
960 		while (true)  {
961 			if (nlPollGroup(group, NL_READ_STATUS, &s, 1, 0))
962 				break;
963 			if (nlPollGroup(group, NL_WRITE_STATUS, &s, 1, 0))
964 				break;
965 			SDL_Delay(2);
966 		}
967 	} else if (timeout > 0)  {
968 		// Blocking, with a timeout
969 		Uint32 start = SDL_GetTicks();
970 		while (SDL_GetTicks() - start <= (Uint32)timeout)  {
971 			if (nlPollGroup(group, NL_READ_STATUS, &s, 1, 0))
972 				break;
973 			if (nlPollGroup(group, NL_WRITE_STATUS, &s, 1, 0))
974 				break;
975 			SDL_Delay(2);
976 		}
977 	}
978 
979 	nlGroupDestroy(group);
980 }
981 
localAddress() const982 NetworkAddr NetworkSocket::localAddress() const {
983 	NetworkAddr addr;
984 
985 	if(!isOpen()) {
986 		errors << "NetworkSocket::localAddress: socket is closed" << endl;
987 		return addr;
988 	}
989 
990 	if(nlGetLocalAddr(m_socket->sock, getNLaddr(addr)) == NL_FALSE) {
991 		errors << "NetworkSocket::localAddress: cannot get local address (" << debugString() << "): " << GetLastErrorStr() << endl;
992 		ResetSocketError();
993 		return addr;
994 	}
995 
996 	return addr;
997 }
998 
remoteAddress() const999 NetworkAddr NetworkSocket::remoteAddress() const {
1000 	NetworkAddr addr;
1001 
1002 	if(!isOpen()) {
1003 		errors << "NetworkSocket::remoteAddress: socket is closed" << endl;
1004 		return addr;
1005 	}
1006 
1007 	if(nlGetRemoteAddr(m_socket->sock, getNLaddr(addr)) == NL_FALSE) {
1008 		errors << "NetworkSocket::remoteAddress: cannot get remote address" << "(" << debugString() << "): " << GetLastErrorStr() << endl;
1009 		ResetSocketError();
1010 		return addr;
1011 	}
1012 
1013 	return addr;
1014 }
1015 
setRemoteAddress(const NetworkAddr & addr)1016 bool NetworkSocket::setRemoteAddress(const NetworkAddr& addr) {
1017 	if(!isOpen()) {
1018 		errors << "NetworkSocket::setRemoteAddress: socket is closed" << endl;
1019 		return false;
1020 	}
1021 
1022 	if(getNLaddr(addr) == NULL) {
1023 		errors << "NetworkSocket::setRemoteAddress " << debugString() << ": given address is invalid" << endl;
1024 		return false;
1025 	}
1026 	if( GetNetAddrPort(addr) == 0 )
1027 	{
1028 		errors << "NetworkSocket::setRemoteAddress " << debugString() << ": port is set to 0" << endl;
1029 	}
1030 
1031 	if(nlSetRemoteAddr(m_socket->sock, getNLaddr(addr)) == NL_FALSE) {
1032 		std::string addrStr = "INVALIDADDR";
1033 		NetAddrToString(addr, addrStr);
1034 		errors << "NetworkSocket::setRemoteAddress " << debugString() << ": failed to set destination " << addrStr << ": " << GetLastErrorStr() << endl;
1035 		ResetSocketError();
1036 		return false;
1037 	}
1038 
1039 	return true;
1040 }
1041 
GetSocketErrorNr()1042 int GetSocketErrorNr() {
1043 	return nlGetError();
1044 }
1045 
GetSocketErrorStr(int errnr)1046 std::string GetSocketErrorStr(int errnr) {
1047 	return GetLastErrorStr();
1048 }
1049 
GetLastErrorStr()1050 std::string GetLastErrorStr()  {
1051 	if (nlGetError() != NL_SYSTEM_ERROR)
1052 		return std::string(nlGetErrorStr(nlGetError()));
1053 	else
1054 		return std::string(nlGetSystemErrorStr(nlGetSystemError()));
1055 }
1056 
IsMessageEndSocketErrorNr(int errnr)1057 bool IsMessageEndSocketErrorNr(int errnr) {
1058 	return (errnr == NL_MESSAGE_END);
1059 }
1060 
ResetSocketError()1061 void ResetSocketError()  {
1062 	if (!bNetworkInited)
1063 		return;
1064 
1065 	nlSetError(NL_NO_ERROR);
1066 }
1067 
1068 
1069 
1070 
IsNetAddrValid(const NetworkAddr & addr)1071 bool IsNetAddrValid(const NetworkAddr& addr) {
1072 	if(getNLaddr(addr))
1073 		return (getNLaddr(addr)->valid != NL_FALSE);
1074 	else
1075 		return false;
1076 }
1077 
SetNetAddrValid(NetworkAddr & addr,bool valid)1078 bool SetNetAddrValid(NetworkAddr& addr, bool valid) {
1079 	if(!getNLaddr(addr)) return false;
1080 	getNLaddr(addr)->valid = valid ? NL_TRUE : NL_FALSE;
1081 	return true;
1082 }
1083 
ResetNetAddr(NetworkAddr & addr)1084 void ResetNetAddr(NetworkAddr& addr) {
1085 	if(!getNLaddr(addr)) return;
1086 	// TODO: is this the best way?
1087 	memset(getNLaddr(addr), 0, sizeof(NLaddress));
1088 	SetNetAddrValid(addr, false);
1089 }
1090 
IsNetAddrV6(const std::string & s)1091 bool IsNetAddrV6(const std::string& s)
1092 {
1093 	// Any IPv6 address will be in a format [XXXX:XXXX:...:XXXX]:XXXX or [XXXX:XXXX:...:XXXX]
1094 	return s.size() > 0 && s[0] == '[';
1095 }
1096 
IsNetAddrV6(const NetworkAddr & addr)1097 bool IsNetAddrV6(const NetworkAddr& addr)
1098 {
1099 	std::string s;
1100 	NetAddrToString(addr, s);
1101 	return IsNetAddrV6(s);
1102 }
1103 
isStringValidIP(const std::string & str)1104 static bool isStringValidIP(const std::string& str) {
1105 	NetworkAddr addr;
1106 	return (nlStringToAddr(str.c_str(), getNLaddr(addr)) == NL_TRUE);
1107 }
1108 
1109 // accepts "%i.%i.%i.%i[:%l]" as input
StringToNetAddr(const std::string & string,NetworkAddr & addr,std::string * errorStr)1110 bool StringToNetAddr(const std::string& string, NetworkAddr& addr, std::string* errorStr) {
1111 	if(getNLaddr(addr) == NULL) return false;
1112 
1113 	if(!isStringValidIP(string)) {
1114 		SetNetAddrValid(addr, false);
1115 		return false;
1116 	}
1117 
1118 	if(nlStringToAddr(string.c_str(), getNLaddr(addr)) == NL_FALSE) {
1119 		errors << "StringToNetAddr: cannot use " << string << " as address: " << GetLastErrorStr() << endl;
1120 		if(errorStr) *errorStr = GetLastErrorStr();
1121 		ResetSocketError();
1122 		return false;
1123 	}
1124 
1125 	return true;
1126 }
1127 
NetAddrToString(const NetworkAddr & addr,std::string & string)1128 bool NetAddrToString(const NetworkAddr& addr, std::string& string) {
1129 	// TODO: safty here for buffer
1130 	char buf[256];
1131 	NLchar* res = nlAddrToString(getNLaddr(addr), buf);
1132 	if(res) {
1133 		fix_markend(buf);
1134 		string = buf;
1135 		return true;
1136 	} else {
1137 		string = "";
1138 		return false;
1139 	}
1140 }
1141 
StringToNetAddr(const std::string & string)1142 NetworkAddr StringToNetAddr(const std::string& string) {
1143 	NetworkAddr ret;
1144 	ResetNetAddr(ret);
1145 	StringToNetAddr(string, ret);
1146 	return ret;
1147 };
1148 
NetAddrToString(const NetworkAddr & addr)1149 std::string NetAddrToString(const NetworkAddr& addr) {
1150 	std::string ret;
1151 	NetAddrToString(addr, ret);
1152 	return ret;
1153 };
1154 
GetNetAddrPort(const NetworkAddr & addr)1155 unsigned short GetNetAddrPort(const NetworkAddr& addr) {
1156 	if(getNLaddr(addr) == NULL)
1157 		return 0;
1158 	else
1159 		return nlGetPortFromAddr(getNLaddr(addr));
1160 }
1161 
SetNetAddrPort(NetworkAddr & addr,unsigned short port,std::string * errorStr)1162 bool SetNetAddrPort(NetworkAddr& addr, unsigned short port, std::string* errorStr) {
1163 	if(getNLaddr(addr) == NULL)
1164 		return false;
1165 	else {
1166 		if(nlSetAddrPort(getNLaddr(addr), port) == NL_FALSE) {
1167 			errors << "SetNetAddrPort: cannot set port " << port << ": " << GetLastErrorStr() << endl;
1168 			if(errorStr) *errorStr = GetLastErrorStr();
1169 			ResetSocketError();
1170 			return false;
1171 		}
1172 		return true;
1173 	}
1174 }
1175 
AreNetAddrEqual(const NetworkAddr & addr1,const NetworkAddr & addr2)1176 bool AreNetAddrEqual(const NetworkAddr& addr1, const NetworkAddr& addr2) {
1177 	if(getNLaddr(addr1) == getNLaddr(addr2))
1178 		return true;
1179 	else
1180 		return nlAddrCompare(getNLaddr(addr1), getNLaddr(addr2)) != NL_FALSE;
1181 }
1182 
1183 
1184 
1185 
1186 Event<> onDnsReady;
1187 
1188 // copied from HawkNL sock.c and modified to not use nlStringToNetAddr
GetAddrFromNameAsync_Internal(const NLchar * name,NLaddress * address4,NLaddress * address6)1189 static bool GetAddrFromNameAsync_Internal(const NLchar* name, NLaddress* address4, NLaddress* address6) {
1190     NLushort    port = 0;
1191     char        *pos;
1192     int         status;
1193     NLbyte      temp[NL_MAX_STRING_LENGTH];
1194 	struct      addrinfo hints;
1195 	struct      addrinfo *result, *rp;
1196 
1197 	address4->valid = NL_FALSE;
1198 	address6->valid = NL_FALSE;
1199 #ifdef _UNICODE
1200     /* convert from wide char string to multibyte char string */
1201     (void)wcstombs(temp, (const NLchar *)name, NL_MAX_STRING_LENGTH);
1202 #else
1203     strncpy(temp, name, NL_MAX_STRING_LENGTH);
1204 #endif
1205     temp[NL_MAX_STRING_LENGTH - 1] = (NLbyte)'\0';
1206     pos = strrchr(temp, ':');
1207     if(pos != NULL)
1208     {
1209         pos[0] = (NLbyte)'\0';
1210         (void)sscanf(pos+1, "%hu", &port);
1211     }
1212 
1213     memset(&hints, 0, sizeof(struct addrinfo));
1214     hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
1215     hints.ai_socktype = 0;
1216     hints.ai_flags = 0;    /* For wildcard IP address */
1217     hints.ai_protocol = 0;          /* Any protocol */
1218     hints.ai_canonname = NULL;
1219     hints.ai_addr = NULL;
1220     hints.ai_next = NULL;
1221 
1222     status = getaddrinfo(temp, NULL, &hints, &result);
1223     if(status != 0 || result == NULL)
1224     {
1225         nlSetError(NL_SYSTEM_ERROR);
1226         return false;
1227     }
1228 
1229     for (rp = result; rp != NULL; rp = rp->ai_next)
1230     {
1231         if(rp->ai_family == AF_INET && !address4->valid)
1232         {
1233             ((struct sockaddr_in6 *)address4)->sin6_family = AF_INET6;
1234             ((struct sockaddr_in6 *)address4)->sin6_port = htons(port);
1235             struct in_addr v4addr;
1236             v4addr = ((struct sockaddr_in *)rp->ai_addr)->sin_addr;
1237             char addr6[32] = "::ffff:";
1238             strcat(addr6, inet_ntoa(v4addr));
1239             inet_pton(AF_INET6, addr6, &((struct sockaddr_in6 *)address4)->sin6_addr);
1240             address4->valid = NL_TRUE;
1241         }
1242         if(rp->ai_family == AF_INET6 && !address6->valid)
1243         {
1244             ((struct sockaddr_in6 *)address6)->sin6_family = AF_INET6;
1245             ((struct sockaddr_in6 *)address6)->sin6_port = htons(port);
1246             memcpy(&((struct sockaddr_in6 *)address6)->sin6_addr, &((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1247             address6->valid = NL_TRUE;
1248         }
1249     }
1250 
1251     freeaddrinfo(result);
1252 
1253     return address4->valid || address6->valid;
1254 }
1255 
1256 static std::set<std::string> PendingDnsQueries;
1257 static Mutex PendingDnsQueriesMutex;
1258 
GetNetAddrFromNameAsync(const std::string & name)1259 bool GetNetAddrFromNameAsync(const std::string& name)
1260 {
1261 	// We don't use nlGetAddrFromNameAsync here because we have to use SmartPointers
1262 	// The problem is, if you call this and then delete the memory of the network address
1263 	// while the thread isn't ready, it will write after to deleted memory.
1264 
1265 	NetworkAddr addr4, addr6;
1266 
1267 	if(name == "") {
1268 		return false;
1269 	}
1270 	if (StringToNetAddr(name, addr4)) {
1271 		return true;
1272 	}
1273 
1274 	ResetSocketError(); // Clear the bad address error
1275 
1276 	if(GetFromDnsCache(name, addr4, addr6)) {
1277 		return true;
1278 	}
1279 
1280 	{
1281 		Mutex::ScopedLock l(PendingDnsQueriesMutex);
1282 		if(PendingDnsQueries.find(name) != PendingDnsQueries.end())
1283 			return true;
1284 		PendingDnsQueries.insert(name);
1285 	}
1286 
1287 	struct GetAddrFromNameAsync_Executer : Task {
1288 		std::string addr_name;
1289 		NetworkAddr address4, address6;
1290 
1291 		int handle() {
1292 			getNLaddr(address4)->valid = NL_FALSE;
1293 			getNLaddr(address6)->valid = NL_FALSE;
1294 			if(GetAddrFromNameAsync_Internal(addr_name.c_str(), getNLaddr(address4), getNLaddr(address6))) {
1295 				// TODO: we use default DNS record expire time of 1 hour, we should include some DNS client to make it in correct way
1296 				// Cache both valid and invalid addersses, one server may have IPv4 but no IPv6 address
1297 				notes << "DNS: resolved " << addr_name << " to " << NetAddrToString(address4) << " IPv6 " << NetAddrToString(address6) << endl;
1298 				AddToDnsCache4(addr_name, address4);
1299 				AddToDnsCache6(addr_name, address6);
1300 			}
1301 
1302 			// TODO: handle failures here? there should be, but we only have the valid field
1303 			// For now, we leave it at false, so the timeout handling will just occur.
1304 
1305 			// push a net event
1306 			onDnsReady.pushToMainQueue(EventData());
1307 
1308 			Mutex::ScopedLock l(PendingDnsQueriesMutex);
1309 			PendingDnsQueries.erase(addr_name);
1310 
1311 			return 0;
1312 		}
1313 	};
1314 	GetAddrFromNameAsync_Executer* data = new GetAddrFromNameAsync_Executer();
1315 	if(data == NULL) return false;
1316 	data->name = "GetNetAddrFromNameAsync for " + name;
1317 	data->addr_name = name;
1318 
1319 	taskManager->start(data, false);
1320     return true;
1321 }
1322 
1323 
isDataAvailable()1324 bool NetworkSocket::isDataAvailable() {
1325 	NLint group = nlGroupCreate();
1326 	nlGroupAddSocket( group, m_socket->sock );
1327 	NLsocket sock_out[2];
1328 	int ret = nlPollGroup( group, NL_READ_STATUS, sock_out, 1, 0 );
1329 	nlGroupDestroy(group);
1330 	return ret > 0;
1331 }
1332 
1333 // In some cases, e.g. if the network is not connected, some IPs are
1334 // not available. Most likely, without any network, you just have
1335 // 127.* in the routing table.
IsNetAddrAvailable(const NetworkAddr & addr)1336 bool IsNetAddrAvailable(const NetworkAddr& addr) {
1337 	// TODO: implement...
1338 	return true;
1339 }
1340 
1341 
reapplyRemoteAddress()1342 void NetworkSocket::reapplyRemoteAddress() {
1343 	if(m_type == NST_UDP || m_type == NST_UDPBROADCAST)
1344 		// TODO: comment this, why we need that in some cases
1345 		setRemoteAddress(remoteAddress());
1346 	else
1347 		errors << "NetworkSocket::reapplyRemoteAddress cannot be done as " << TypeStr(m_type) << endl;
1348 }
1349 
1350