1 //This file is part of Glest Shared Library (www.glest.org)
2 //Copyright (C) 2005 Matthias Braun <matze@braunis.de>
3 
4 //You can redistribute this code and/or modify it under
5 //the terms of the GNU General Public License as published by the Free Software
6 //Foundation; either version 2 of the License, or (at your option) any later
7 //version.
8 
9 #include "socket.h"
10 
11 #include <cstring>
12 #include <cstdio>
13 #include <cstdlib>
14 #include <stdexcept>
15 
16 #if defined(HAVE_SYS_IOCTL_H) || defined(__linux__)
17   #define BSD_COMP /* needed for FIONREAD on Solaris2 */
18   #include <sys/ioctl.h>
19 #endif
20 #if defined(HAVE_SYS_FILIO_H) /* needed for FIONREAD on Solaris 2.5 */
21   #include <sys/filio.h>
22 #endif
23 
24 #include "conversion.h"
25 #include "util.h"
26 #include "platform_util.h"
27 #include <algorithm>
28 
29 #ifdef WIN32
30 
31   #include <windows.h>
32   #include <winsock2.h>
33   #include <winsock.h>
34   #include <iphlpapi.h>
35   #include <strstream>
36   #include <strsafe.h>
37 
38 #define MSG_NOSIGNAL 0
39 #define MSG_DONTWAIT 0
40 
41 #else
42 
43   #include <unistd.h>
44   #include <stdlib.h>
45   #include <sys/socket.h>
46   #include <netdb.h>
47   #include <netinet/in.h>
48   #include <net/if.h>
49   #include <netinet/tcp.h>
50 #endif
51 
52 
53 #include <string.h>
54 #include <sys/stat.h>
55 #include <time.h>
56 
57 #include "miniwget.h"
58 #include "miniupnpc.h"
59 #include "upnpcommands.h"
60 
61 #include "leak_dumper.h"
62 
63 using namespace std;
64 using namespace Shared::Util;
65 
66 namespace Shared{ namespace Platform{
67 
68 bool Socket::disableNagle = false;
69 int Socket::DEFAULT_SOCKET_SENDBUF_SIZE = -1;
70 int Socket::DEFAULT_SOCKET_RECVBUF_SIZE = -1;
71 string Socket::host_name = "";
72 std::vector<string> Socket::intfTypes;
73 
74 int Socket::broadcast_portno    = 61357;
75 int ServerSocket::ftpServerPort = 61358;
76 int ServerSocket::maxPlayerCount = -1;
77 int ServerSocket::externalPort  = Socket::broadcast_portno;
78 BroadCastClientSocketThread *ClientSocket::broadCastClientThread = NULL;
79 SDL_Thread *ServerSocket::upnpdiscoverThread = NULL;
80 bool ServerSocket::cancelUpnpdiscoverThread = false;
81 Mutex ServerSocket::mutexUpnpdiscoverThread;
82 //
83 // UPnP - Start
84 //
85 static struct UPNPUrls urls;
86 static struct IGDdatas data;
87 // local ip address
88 static char lanaddr[16]         = "";
89 bool UPNP_Tools::isUPNP         = true;
90 bool UPNP_Tools::enabledUPNP    = false;
91 Mutex UPNP_Tools::mutexUPNP;
92 // UPnP - End
93 
94 #ifdef WIN32
95 
96     #define socklen_t 	int
97 	#define MAXHOSTNAME 254
98 
99 //#define PLATFORM_SOCKET_TRY_AGAIN WSAEWOULDBLOCK
100 //#define PLATFORM_SOCKET_INPROGRESS WSAEINPROGRESS
101 //#define PLATFORM_SOCKET_INTERRUPTED WSAEWOULDBLOCK
102 	typedef SSIZE_T ssize_t;
103 
104 	//// Constants /////////////////////////////////////////////////////////
105 	const int kBufferSize = 1024;
106 
107 	//// Statics ///////////////////////////////////////////////////////////
108 	// List of Winsock error constants mapped to an interpretation string.
109 	// Note that this list must remain sorted by the error constants'
110 	// values, because we do a binary search on the list when looking up
111 	// items.
112 
113 	static class ErrorEntry
114 	{
115 	public:
116 		int nID;
117 		const char* pcMessage;
118 
ErrorEntry(int id,const char * pc=0)119 		ErrorEntry(int id, const char* pc = 0) : nID(id), pcMessage(pc)
120 		{
121 		}
122 
operator <(const ErrorEntry & rhs)123 		bool operator<(const ErrorEntry& rhs)
124 		{
125 			return nID < rhs.nID;
126 		}
127 
128 	} gaErrorList[] =
129 	  {
130 		ErrorEntry(0,                  "No error"),
131 		ErrorEntry(WSAEINTR,           "Interrupted system call"),
132 		ErrorEntry(WSAEBADF,           "Bad file number"),
133 		ErrorEntry(WSAEACCES,          "Permission denied"),
134 		ErrorEntry(WSAEFAULT,          "Bad address"),
135 		ErrorEntry(WSAEINVAL,          "Invalid argument"),
136 		ErrorEntry(WSAEMFILE,          "Too many open sockets"),
137 		ErrorEntry(WSAEWOULDBLOCK,     "Operation would block"),
138 		ErrorEntry(WSAEINPROGRESS,     "Operation now in progress"),
139 		ErrorEntry(WSAEALREADY,        "Operation already in progress"),
140 		ErrorEntry(WSAENOTSOCK,        "Socket operation on non-socket"),
141 		ErrorEntry(WSAEDESTADDRREQ,    "Destination address required"),
142 		ErrorEntry(WSAEMSGSIZE,        "Message too long"),
143 		ErrorEntry(WSAEPROTOTYPE,      "Protocol wrong type for socket"),
144 		ErrorEntry(WSAENOPROTOOPT,     "Bad protocol option"),
145 		ErrorEntry(WSAEPROTONOSUPPORT, "Protocol not supported"),
146 		ErrorEntry(WSAESOCKTNOSUPPORT, "Socket type not supported"),
147 		ErrorEntry(WSAEOPNOTSUPP,      "Operation not supported on socket"),
148 		ErrorEntry(WSAEPFNOSUPPORT,    "Protocol family not supported"),
149 		ErrorEntry(WSAEAFNOSUPPORT,    "Address family not supported"),
150 		ErrorEntry(WSAEADDRINUSE,      "Address already in use"),
151 		ErrorEntry(WSAEADDRNOTAVAIL,   "Can't assign requested address"),
152 		ErrorEntry(WSAENETDOWN,        "Network is down"),
153 		ErrorEntry(WSAENETUNREACH,     "Network is unreachable"),
154 		ErrorEntry(WSAENETRESET,       "Net connection reset"),
155 		ErrorEntry(WSAECONNABORTED,    "Software caused connection abort"),
156 		ErrorEntry(WSAECONNRESET,      "Connection reset by peer"),
157 		ErrorEntry(WSAENOBUFS,         "No buffer space available"),
158 		ErrorEntry(WSAEISCONN,         "Socket is already connected"),
159 		ErrorEntry(WSAENOTCONN,        "Socket is not connected"),
160 		ErrorEntry(WSAESHUTDOWN,       "Can't send after socket shutdown"),
161 		ErrorEntry(WSAETOOMANYREFS,    "Too many references, can't splice"),
162 		ErrorEntry(WSAETIMEDOUT,       "Connection timed out"),
163 		ErrorEntry(WSAECONNREFUSED,    "Connection refused"),
164 		ErrorEntry(WSAELOOP,           "Too many levels of symbolic links"),
165 		ErrorEntry(WSAENAMETOOLONG,    "File name too long"),
166 		ErrorEntry(WSAEHOSTDOWN,       "Host is down"),
167 		ErrorEntry(WSAEHOSTUNREACH,    "No route to host"),
168 		ErrorEntry(WSAENOTEMPTY,       "Directory not empty"),
169 		ErrorEntry(WSAEPROCLIM,        "Too many processes"),
170 		ErrorEntry(WSAEUSERS,          "Too many users"),
171 		ErrorEntry(WSAEDQUOT,          "Disc quota exceeded"),
172 		ErrorEntry(WSAESTALE,          "Stale NFS file handle"),
173 		ErrorEntry(WSAEREMOTE,         "Too many levels of remote in path"),
174 		ErrorEntry(WSASYSNOTREADY,     "Network system is unavailable"),
175 		ErrorEntry(WSAVERNOTSUPPORTED, "Winsock version out of range"),
176 		ErrorEntry(WSANOTINITIALISED,  "WSAStartup not yet called"),
177 		ErrorEntry(WSAEDISCON,         "Graceful shutdown in progress"),
178 		ErrorEntry(WSAHOST_NOT_FOUND,  "Host not found"),
179 		ErrorEntry(WSANO_DATA,         "No host data of that type was found")
180 	};
181 
operator <(const ErrorEntry & rhs1,const ErrorEntry & rhs2)182 	bool operator<(const ErrorEntry& rhs1,const ErrorEntry& rhs2)
183 	{
184 		return rhs1.nID < rhs2.nID;
185 	}
186 
187 	const int kNumMessages = sizeof(gaErrorList) / sizeof(ErrorEntry);
188 
189 	//// WSAGetLastErrorMessage ////////////////////////////////////////////
190 	// A function similar in spirit to Unix's perror() that tacks a canned
191 	// interpretation of the value of WSAGetLastError() onto the end of a
192 	// passed string, separated by a ": ".  Generally, you should implement
193 	// smarter error handling than this, but for default cases and simple
194 	// programs, this function is sufficient.
195 	//
196 	// This function returns a pointer to an internal static buffer, so you
197 	// must copy the data from this function before you call it again.  It
198 	// follows that this function is also not thread-safe.
WSAGetLastErrorMessage(const char * pcMessagePrefix,int nErrorID=0)199 	const char* WSAGetLastErrorMessage(const char* pcMessagePrefix,
200 									   int nErrorID = 0 )
201 	{
202 		// Build basic error string
203 		static char acErrorBuffer[8096];
204 		std::ostrstream outs(acErrorBuffer, 8095);
205 		outs << pcMessagePrefix << ": ";
206 
207 		// Tack appropriate canned message onto end of supplied message
208 		// prefix. Note that we do a binary search here: gaErrorList must be
209 		// sorted by the error constant's value.
210 		ErrorEntry* pEnd = gaErrorList + kNumMessages;
211 		ErrorEntry Target(nErrorID ? nErrorID : WSAGetLastError());
212 		ErrorEntry* it = std::lower_bound(gaErrorList, pEnd, Target);
213 		if ((it != pEnd) && (it->nID == Target.nID))
214 		{
215 			outs << it->pcMessage;
216 		}
217 		else
218 		{
219 			// Didn't find error in list, so make up a generic one
220 			outs << "unknown socket error";
221 		}
222 		outs << " (" << Target.nID << ")";
223 
224 		// Finish error message off and return it.
225 		outs << std::ends;
226 		acErrorBuffer[8095] = '\0';
227 		return acErrorBuffer;
228 	}
229 
230 	// keeps in scope for duration of the application
231 	//SocketManager Socket::wsaManager;
232 
SocketManager()233 	SocketManager::SocketManager() {
234 		WSADATA wsaData;
235 		WORD wVersionRequested = MAKEWORD(2, 0);
236 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("SocketManager calling WSAStartup...\n");
237 		WSAStartup(wVersionRequested, &wsaData);
238 		//dont throw exceptions here, this is a static initializacion
239 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Winsock initialized.\n");
240 	}
241 
~SocketManager()242 	SocketManager::~SocketManager() {
243 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("SocketManager calling WSACleanup...\n");
244 		WSACleanup();
245 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Winsock cleanup complete.\n");
246 	}
247 
248 #else
249 
250 	typedef unsigned int UINT_PTR, *PUINT_PTR;
251 	typedef UINT_PTR        SOCKET;
252 	#define INVALID_SOCKET  (SOCKET)(~0)
253 
254 	//#define PLATFORM_SOCKET_TRY_AGAIN EAGAIN
255 	//#define PLATFORM_SOCKET_INPROGRESS EINPROGRESS
256 	//#define PLATFORM_SOCKET_INTERRUPTED EINTR
257 
258 #endif
259 
getLastSocketError()260 int Socket::getLastSocketError() {
261 #ifndef WIN32
262 	return errno;
263 #else
264 	return WSAGetLastError();
265 #endif
266 }
267 
getLastSocketErrorText(int * errNumber)268 const char * Socket::getLastSocketErrorText(int *errNumber) {
269 	int errId = (errNumber != NULL ? *errNumber : getLastSocketError());
270 #ifndef WIN32
271 	return strerror(errId);
272 #else
273 	return WSAGetLastErrorMessage("",errId);
274 #endif
275 }
276 
getLastSocketErrorFormattedText(int * errNumber)277 string Socket::getLastSocketErrorFormattedText(int *errNumber) {
278 	int errId = (errNumber != NULL ? *errNumber : getLastSocketError());
279 	string msg = "(Error: " + intToStr(errId) + " - [" + string(getLastSocketErrorText(&errId)) +"])";
280 	return msg;
281 }
282 
283 // =====================================================
284 //	class Ip
285 // =====================================================
286 
Ip()287 Ip::Ip(){
288 	bytes[0]= 0;
289 	bytes[1]= 0;
290 	bytes[2]= 0;
291 	bytes[3]= 0;
292 }
293 
Ip(unsigned char byte0,unsigned char byte1,unsigned char byte2,unsigned char byte3)294 Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned char byte3){
295 	bytes[0]= byte0;
296 	bytes[1]= byte1;
297 	bytes[2]= byte2;
298 	bytes[3]= byte3;
299 }
300 
301 
Ip(const string & ipString)302 Ip::Ip(const string& ipString){
303 	size_t offset= 0;
304 	int byteIndex= 0;
305 
306 	for(byteIndex= 0; byteIndex<4; ++byteIndex){
307 		size_t dotPos= ipString.find_first_of('.', offset);
308 
309 		bytes[byteIndex]= atoi(ipString.substr(offset, dotPos-offset).c_str());
310 		offset= dotPos+1;
311 	}
312 }
313 
getString() const314 string Ip::getString() const{
315 	return intToStr(bytes[0]) + "." + intToStr(bytes[1]) + "." + intToStr(bytes[2]) + "." + intToStr(bytes[3]);
316 }
317 
318 // ===============================================
319 //	class Socket
320 // ===============================================
321 
322 #if defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__)
323 # define USE_GETIFADDRS 1
324 # include <ifaddrs.h>
325 #endif
326 
SockAddrToUint32(struct in_addr * a)327 static uint32 SockAddrToUint32(struct in_addr * a) {
328 	uint32 result = 0;
329 
330 	//printf("a [%p]\n",a);
331 	if(a != NULL) {
332 		result = ntohl(a->s_addr);
333 	}
334 
335 	return result;
336 }
337 
SockAddrToUint32(struct sockaddr * a)338 static uint32 SockAddrToUint32(struct sockaddr * a) {
339 	uint32 result = 0;
340 
341 	//printf("a [%p] family = %d\n",a,(a ? a->sa_family : -1));
342 	if(a != NULL && (a->sa_family == AF_INET || a->sa_family == AF_UNSPEC)) {
343 		//result = SockAddrToUint32((((struct sockaddr_in *)a)->sin_addr.s_addr);
344 		result = SockAddrToUint32(&((struct sockaddr_in *)a)->sin_addr);
345 	}
346 
347 	return result;
348 }
349 
350 // convert a numeric IP address into its string representation
Inet_NtoA(uint32 addr,char * ipbuf)351 void Ip::Inet_NtoA(uint32 addr, char * ipbuf)
352 {
353    sprintf(ipbuf, "%d.%d.%d.%d", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF);
354 }
355 
356 #if defined(WIN32)
357 // convert a string represenation of an IP address into its numeric equivalent
Inet_AtoN(const char * buf)358 static uint32 Inet_AtoN(const char * buf)
359 {
360    // net_server inexplicably doesn't have this function; so I'll just fake it
361    uint32 ret = 0;
362    int shift = 24;  // fill out the MSB first
363    bool startQuad = true;
364    while((shift >= 0)&&(*buf))
365    {
366       if (startQuad)
367       {
368          unsigned char quad = (unsigned char) atoi(buf);
369          ret |= (((uint32)quad) << shift);
370          shift -= 8;
371       }
372       startQuad = (*buf == '.');
373       buf++;
374    }
375    return ret;
376 }
377 #endif
378 
379 /*
380 static void PrintNetworkInterfaceInfos()
381 {
382 #if defined(USE_GETIFADDRS)
383    // BSD-style implementation
384    struct ifaddrs * ifap;
385    if (getifaddrs(&ifap) == 0)
386    {
387       struct ifaddrs * p = ifap;
388       while(p)
389       {
390          uint32 ifaAddr  = SockAddrToUint32(p->ifa_addr);
391          uint32 maskAddr = SockAddrToUint32(p->ifa_netmask);
392          uint32 dstAddr  = SockAddrToUint32(p->ifa_dstaddr);
393          if (ifaAddr > 0)
394          {
395             char ifaAddrStr[32];  Ip::Inet_NtoA(ifaAddr,  ifaAddrStr);
396             char maskAddrStr[32]; Ip::Inet_NtoA(maskAddr, maskAddrStr);
397             char dstAddrStr[32];  Ip::Inet_NtoA(dstAddr,  dstAddrStr);
398             printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
399          }
400          p = p->ifa_next;
401       }
402       freeifaddrs(ifap);
403    }
404 #elif defined(WIN32)
405    // Windows XP style implementation
406 
407    // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx
408    // Now get Windows' IPv4 addresses table.  Once again, we gotta call GetIpAddrTable()
409    // multiple times in order to deal with potential race conditions properly.
410    MIB_IPADDRTABLE * ipTable = NULL;
411    {
412       ULONG bufLen = 0;
413       for (int i=0; i<5; i++)
414       {
415          DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false);
416          if (ipRet == ERROR_INSUFFICIENT_BUFFER)
417          {
418             free(ipTable);  // in case we had previously allocated it
419             ipTable = (MIB_IPADDRTABLE *) malloc(bufLen);
420          }
421          else if (ipRet == NO_ERROR) break;
422          else
423          {
424             free(ipTable);
425             ipTable = NULL;
426             break;
427          }
428      }
429    }
430 
431    if (ipTable)
432    {
433       // Try to get the Adapters-info table, so we can given useful names to the IP
434       // addresses we are returning.  Gotta call GetAdaptersInfo() up to 5 times to handle
435       // the potential race condition between the size-query call and the get-data call.
436       // I love a well-designed API :^P
437       IP_ADAPTER_INFO * pAdapterInfo = NULL;
438       {
439          ULONG bufLen = 0;
440          for (int i=0; i<5; i++)
441          {
442             DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen);
443             if (apRet == ERROR_BUFFER_OVERFLOW)
444             {
445                free(pAdapterInfo);  // in case we had previously allocated it
446                pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen);
447             }
448             else if (apRet == ERROR_SUCCESS) break;
449             else
450             {
451                free(pAdapterInfo);
452                pAdapterInfo = NULL;
453                break;
454             }
455          }
456       }
457 
458       for (DWORD i=0; i<ipTable->dwNumEntries; i++)
459       {
460          const MIB_IPADDRROW & row = ipTable->table[i];
461 
462          // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it
463          const char * name = NULL;
464          const char * desc = NULL;
465          if (pAdapterInfo)
466          {
467             IP_ADAPTER_INFO * next = pAdapterInfo;
468             while((next)&&(name==NULL))
469             {
470                IP_ADDR_STRING * ipAddr = &next->IpAddressList;
471                while(ipAddr)
472                {
473                   if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr))
474                   {
475                      name = next->AdapterName;
476                      desc = next->Description;
477                      break;
478                   }
479                   ipAddr = ipAddr->Next;
480                }
481                next = next->Next;
482             }
483          }
484          char buf[128];
485          if (name == NULL)
486          {
487             snprintf(buf, 128,"unnamed-%i", i);
488             name = buf;
489          }
490 
491          uint32 ipAddr  = ntohl(row.dwAddr);
492          uint32 netmask = ntohl(row.dwMask);
493          uint32 baddr   = ipAddr & netmask;
494          if (row.dwBCastAddr) baddr |= ~netmask;
495 
496          char ifaAddrStr[32];  Ip::Inet_NtoA(ipAddr,  ifaAddrStr);
497          char maskAddrStr[32]; Ip::Inet_NtoA(netmask, maskAddrStr);
498          char dstAddrStr[32];  Ip::Inet_NtoA(baddr,   dstAddrStr);
499          printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
500       }
501 
502       free(pAdapterInfo);
503       free(ipTable);
504    }
505 #else
506    // Dunno what we're running on here!
507 #  error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!"
508 #endif
509 }
510 */
511 
getNetworkInterfaceBroadcastAddress(string ipAddress)512 string getNetworkInterfaceBroadcastAddress(string ipAddress)
513 {
514 	string broadCastAddress = "";
515 
516 #if defined(USE_GETIFADDRS)
517    // BSD-style implementation
518 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
519    struct ifaddrs * ifap;
520    if (getifaddrs(&ifap) == 0)
521    {
522 	   if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
523       struct ifaddrs * p = ifap;
524       while(p)
525       {
526          uint32 ifaAddr  = SockAddrToUint32(p->ifa_addr);
527          uint32 maskAddr = SockAddrToUint32(p->ifa_netmask);
528          uint32 dstAddr  = SockAddrToUint32(p->ifa_dstaddr);
529          if (ifaAddr > 0)
530          {
531         	 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
532 
533             char ifaAddrStr[32];  Ip::Inet_NtoA(ifaAddr,  ifaAddrStr);
534             char maskAddrStr[32]; Ip::Inet_NtoA(maskAddr, maskAddrStr);
535             char dstAddrStr[32];  Ip::Inet_NtoA(dstAddr,  dstAddrStr);
536             //printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
537 			if(strcmp(ifaAddrStr,ipAddress.c_str()) == 0) {
538 				broadCastAddress = dstAddrStr;
539 			}
540 
541 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ifaAddrStr [%s], maskAddrStr [%s], dstAddrStr[%s], ipAddress [%s], broadCastAddress [%s]\n",__FILE__,__FUNCTION__,__LINE__,ifaAddrStr,maskAddrStr,dstAddrStr,ipAddress.c_str(),broadCastAddress.c_str());
542          }
543          p = p->ifa_next;
544       }
545       freeifaddrs(ifap);
546    }
547 #elif defined(WIN32)
548    // Windows XP style implementation
549 
550    // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx
551    // Now get Windows' IPv4 addresses table.  Once again, we gotta call GetIpAddrTable()
552    // multiple times in order to deal with potential race conditions properly.
553    PMIB_IPADDRTABLE ipTable = NULL;
554    // Before calling AddIPAddress we use GetIpAddrTable to get
555    // an adapter to which we can add the IP.
556    ipTable = (PMIB_IPADDRTABLE) malloc(sizeof (MIB_IPADDRTABLE));
557    ipTable->dwNumEntries = 0;
558 
559    {
560       ULONG bufLen = 0;
561       for (int i = 0; i < 5; i++) {
562 
563          DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false);
564          if (ipRet == ERROR_INSUFFICIENT_BUFFER) {
565             free(ipTable);  // in case we had previously allocated it
566             ipTable = (MIB_IPADDRTABLE *) malloc(bufLen);
567             ipTable->dwNumEntries = 0;
568          }
569          else if(ipRet == NO_ERROR) {
570         	 break;
571          }
572          else {
573             free(ipTable);
574             ipTable = NULL;
575             break;
576          }
577      }
578    }
579 
580    if (ipTable) {
581       // Try to get the Adapters-info table, so we can given useful names to the IP
582       // addresses we are returning.  Gotta call GetAdaptersInfo() up to 5 times to handle
583       // the potential race condition between the size-query call and the get-data call.
584       // I love a well-designed API :^P
585       IP_ADAPTER_INFO * pAdapterInfo = NULL;
586       {
587          ULONG bufLen = 0;
588          for (int i = 0; i < 5; i++) {
589             DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen);
590             if (apRet == ERROR_BUFFER_OVERFLOW) {
591                free(pAdapterInfo);  // in case we had previously allocated it
592                pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen);
593             }
594             else if(apRet == ERROR_SUCCESS) {
595             	break;
596             }
597             else {
598                free(pAdapterInfo);
599                pAdapterInfo = NULL;
600                break;
601             }
602          }
603       }
604 
605       for (DWORD i = 0; i < ipTable->dwNumEntries; i++) {
606          const MIB_IPADDRROW & row = ipTable->table[i];
607 
608          // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it
609          const char * name = NULL;
610          //const char * desc = NULL;
611          if (pAdapterInfo) {
612             IP_ADAPTER_INFO * next = pAdapterInfo;
613             while((next)&&(name==NULL)) {
614                IP_ADDR_STRING * ipAddr = &next->IpAddressList;
615                while(ipAddr) {
616                   if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) {
617                      name = next->AdapterName;
618                      //desc = next->Description;
619                      break;
620                   }
621                   ipAddr = ipAddr->Next;
622                }
623                next = next->Next;
624             }
625          }
626          if (name == NULL) {
627             name = "";
628          }
629 
630          uint32 ipAddr  = ntohl(row.dwAddr);
631          uint32 netmask = ntohl(row.dwMask);
632          uint32 baddr   = ipAddr & netmask;
633          if (row.dwBCastAddr) {
634         	 baddr |= ~netmask;
635          }
636 
637          char ifaAddrStr[32];
638          Ip::Inet_NtoA(ipAddr,  ifaAddrStr);
639          char maskAddrStr[32];
640          Ip::Inet_NtoA(netmask, maskAddrStr);
641          char dstAddrStr[32];
642          Ip::Inet_NtoA(baddr,   dstAddrStr);
643          //printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
644 		 if(strcmp(ifaAddrStr,ipAddress.c_str()) == 0) {
645 			broadCastAddress = dstAddrStr;
646 		 }
647       }
648 
649       if(pAdapterInfo) free(pAdapterInfo);
650       if(ipTable) free(ipTable);
651    }
652 #else
653    // Dunno what we're running on here!
654 #  error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!"
655 #endif
656 
657 	return broadCastAddress;
658 }
659 
getConnectedIPAddress(string IP)660 uint32 Socket::getConnectedIPAddress(string IP) {
661 	sockaddr_in addr;
662 	memset(&addr, 0, sizeof(addr));
663 
664     addr.sin_family= AF_INET;
665     if(IP == "") {
666         IP = connectedIpAddress;
667     }
668 	addr.sin_addr.s_addr= inet_addr(IP.c_str());
669 	//addr.sin_port= htons(port);
670 
671 	return SockAddrToUint32((struct sockaddr *)&addr);
672 }
673 
getLocalIPAddressList()674 std::vector<std::string> Socket::getLocalIPAddressList() {
675 	std::vector<std::string> ipList;
676 
677 	/* get my host name */
678 	char myhostname[101]="";
679 	gethostname(myhostname,100);
680 
681 	struct hostent* myhostent = gethostbyname(myhostname);
682 	if(myhostent) {
683 		// get all host IP addresses (Except for loopback)
684 		char myhostaddr[101] = "";
685 		//int ipIdx = 0;
686 		//while (myhostent->h_addr_list[ipIdx] != 0) {
687 		for(int ipIdx = 0; myhostent->h_addr_list[ipIdx] != NULL; ++ipIdx) {
688 			Ip::Inet_NtoA(SockAddrToUint32((struct in_addr *)myhostent->h_addr_list[ipIdx]), myhostaddr);
689 
690 		   //printf("ipIdx = %d [%s]\n",ipIdx,myhostaddr);
691 		   if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] myhostaddr = [%s]\n",__FILE__,__FUNCTION__,__LINE__,myhostaddr);
692 
693 		   if(strlen(myhostaddr) > 0 &&
694 			  strncmp(myhostaddr,"127.",4) != 0 &&
695 			  strncmp(myhostaddr,"0.",2) != 0) {
696 			   ipList.push_back(myhostaddr);
697 		   }
698 		   //ipIdx++;
699 		}
700 	}
701 
702 #ifndef WIN32
703 
704 	// Now check all linux network devices
705 	//std::vector<string> intfTypes;
706 	if(Socket::intfTypes.empty()) {
707 		Socket::intfTypes.push_back("lo");
708 		Socket::intfTypes.push_back("eth");
709 		Socket::intfTypes.push_back("wlan");
710 		Socket::intfTypes.push_back("vlan");
711 		Socket::intfTypes.push_back("vboxnet");
712 		Socket::intfTypes.push_back("br-lan");
713 		Socket::intfTypes.push_back("br-gest");
714 		Socket::intfTypes.push_back("enp0s");
715 		Socket::intfTypes.push_back("enp1s");
716 		Socket::intfTypes.push_back("enp2s");
717 		Socket::intfTypes.push_back("enp3s");
718 		Socket::intfTypes.push_back("enp4s");
719 		Socket::intfTypes.push_back("enp5s");
720 		Socket::intfTypes.push_back("enp6s");
721 		Socket::intfTypes.push_back("enp7s");
722 		Socket::intfTypes.push_back("enp8s");
723 		Socket::intfTypes.push_back("enp9s");
724 	}
725 
726 	for(unsigned int intfIdx = 0; intfIdx < Socket::intfTypes.size(); intfIdx++) {
727 		string intfName = Socket::intfTypes[intfIdx];
728 		for(int idx = 0; idx < 10; ++idx) {
729 			PLATFORM_SOCKET fd = socket(AF_INET, SOCK_DGRAM, 0);
730 			//PLATFORM_SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
731 
732 			/* I want to get an IPv4 IP address */
733 			struct ifreq ifr;
734 			struct ifreq ifrA;
735 			ifr.ifr_addr.sa_family = AF_INET;
736 			ifrA.ifr_addr.sa_family = AF_INET;
737 
738 			/* I want IP address attached to "eth0" */
739 			char szBuf[100]="";
740 			snprintf(szBuf,100,"%s%d",intfName.c_str(),idx);
741 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Trying NIC named [%s]\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
742 			//printf("In [%s::%s Line: %d] Trying NIC named [%s]\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
743 
744 			int maxIfNameLength = std::min((int)strlen(szBuf),IFNAMSIZ-1);
745 
746 			strncpy(ifr.ifr_name, szBuf, maxIfNameLength);
747 			ifr.ifr_name[maxIfNameLength] = '\0';
748 			strncpy(ifrA.ifr_name, szBuf, maxIfNameLength);
749 			ifrA.ifr_name[maxIfNameLength] = '\0';
750 
751 			int result_ifaddrr = ioctl(fd, SIOCGIFADDR, &ifr);
752 			ioctl(fd, SIOCGIFFLAGS, &ifrA);
753 			if(fd >= 0) close(fd);
754 
755 			if(result_ifaddrr >= 0) {
756 				struct sockaddr_in *pSockAddr = (struct sockaddr_in *)&ifr.ifr_addr;
757 				if(pSockAddr != NULL) {
758 
759 					char myhostaddr[101] = "";
760 					Ip::Inet_NtoA(SockAddrToUint32(&pSockAddr->sin_addr), myhostaddr);
761 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] szBuf [%s], myhostaddr = [%s], ifr.ifr_flags = %d, ifrA.ifr_flags = %d, ifr.ifr_name [%s]\n",__FILE__,__FUNCTION__,__LINE__,szBuf,myhostaddr,ifr.ifr_flags,ifrA.ifr_flags,ifr.ifr_name);
762 
763 					// Now only include interfaces that are both UP and running
764 					if( (ifrA.ifr_flags & IFF_UP) 		== IFF_UP &&
765 						(ifrA.ifr_flags & IFF_RUNNING) 	== IFF_RUNNING) {
766 						if( strlen(myhostaddr) > 0 &&
767 							strncmp(myhostaddr,"127.",4) != 0  &&
768 							strncmp(myhostaddr,"0.",2) != 0) {
769 							if(std::find(ipList.begin(),ipList.end(),myhostaddr) == ipList.end()) {
770 								ipList.push_back(myhostaddr);
771 							}
772 						}
773 					}
774 				}
775 			}
776 		}
777 	}
778 
779 #endif
780 
781 	return ipList;
782 }
783 
isSocketValid() const784 bool Socket::isSocketValid() const {
785 	return Socket::isSocketValid(&sock);
786 }
787 
isSocketValid(const PLATFORM_SOCKET * validateSocket)788 bool Socket::isSocketValid(const PLATFORM_SOCKET *validateSocket) {
789 #ifdef WIN32
790 	if(validateSocket == NULL || (*validateSocket) == 0) {
791 		return false;
792 	}
793 	else {
794 		return (*validateSocket != INVALID_SOCKET);
795 	}
796 #else
797 	if(validateSocket == NULL) {
798 		return false;
799 	}
800 	else {
801 		return (*validateSocket > 0);
802 	}
803 #endif
804 }
805 
Socket(PLATFORM_SOCKET sock)806 Socket::Socket(PLATFORM_SOCKET sock) {
807 	dataSynchAccessorRead = new Mutex(CODE_AT_LINE);
808 	dataSynchAccessorWrite = new Mutex(CODE_AT_LINE);
809 	inSocketDestructorSynchAccessor = new Mutex(CODE_AT_LINE);
810 	lastSocketError = 0;
811 
812 	MutexSafeWrapper safeMutexSocketDestructorFlag(inSocketDestructorSynchAccessor,CODE_AT_LINE);
813 	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
814 	this->inSocketDestructor = false;
815 	lastThreadedPing = 0;
816 	lastDebugEvent = 0;
817 	//safeMutexSocketDestructorFlag.ReleaseLock();
818 
819 	//this->pingThread = NULL;
820 	//pingThreadAccessor.setOwnerId(CODE_AT_LINE);
821 	dataSynchAccessorRead->setOwnerId(CODE_AT_LINE);
822 	dataSynchAccessorWrite->setOwnerId(CODE_AT_LINE);
823 
824 	this->sock= sock;
825 	this->isSocketBlocking = true;
826 	this->connectedIpAddress = "";
827 }
828 
Socket()829 Socket::Socket() {
830 	dataSynchAccessorRead = new Mutex(CODE_AT_LINE);
831 	dataSynchAccessorWrite = new Mutex(CODE_AT_LINE);
832 	inSocketDestructorSynchAccessor = new Mutex(CODE_AT_LINE);
833 	lastSocketError = 0;
834 	lastDebugEvent = 0;
835 	lastThreadedPing = 0;
836 
837 	MutexSafeWrapper safeMutexSocketDestructorFlag(inSocketDestructorSynchAccessor,CODE_AT_LINE);
838 	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
839 	this->inSocketDestructor = false;
840 	//safeMutexSocketDestructorFlag.ReleaseLock();
841 
842 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
843 
844 	//this->pingThread = NULL;
845 
846 	this->connectedIpAddress = "";
847 
848 	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
849 	if(isSocketValid() == false) {
850 		throwException("Error creating socket");
851 	}
852 
853 	this->isSocketBlocking = true;
854 
855 #ifdef __APPLE__
856     int set = 1;
857     setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
858 #endif
859 
860     /* Disable the Nagle (TCP No Delay) algorithm */
861     if(Socket::disableNagle == true) {
862 		int flag = 1;
863 		int ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
864 		if (ret == -1) {
865 		  printf("Couldn't setsockopt(TCP_NODELAY)\n");
866 		}
867     }
868 
869 	if(Socket::DEFAULT_SOCKET_SENDBUF_SIZE >= 0) {
870 		int bufsize 	 = 0;
871 		socklen_t optlen = sizeof(bufsize);
872 
873 		int ret = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, &optlen);
874 		printf("Original setsockopt(SO_SNDBUF) = [%d] new will be [%d] ret = %d\n",bufsize,Socket::DEFAULT_SOCKET_SENDBUF_SIZE,ret);
875 
876 		ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char *) &Socket::DEFAULT_SOCKET_SENDBUF_SIZE, sizeof( int ) );
877 		if (ret == -1) {
878 		  printf("Couldn't setsockopt(SO_SNDBUF) [%d]\n",Socket::DEFAULT_SOCKET_SENDBUF_SIZE);
879 		}
880 	}
881 
882 	if(Socket::DEFAULT_SOCKET_RECVBUF_SIZE >= 0) {
883 		int bufsize 	 = 0;
884 		socklen_t optlen = sizeof(bufsize);
885 
886 		int ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, &optlen);
887 		printf("Original setsockopt(SO_RCVBUF) = [%d] new will be [%d] ret = %d\n",bufsize,Socket::DEFAULT_SOCKET_RECVBUF_SIZE,ret);
888 
889 		ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &Socket::DEFAULT_SOCKET_RECVBUF_SIZE, sizeof( int ) );
890 		if (ret == -1) {
891 		  printf("Couldn't setsockopt(SO_RCVBUF) [%d]\n",Socket::DEFAULT_SOCKET_RECVBUF_SIZE);
892 		}
893 	}
894 
895 }
896 
getThreadedPingMS(std::string host)897 float Socket::getThreadedPingMS(std::string host) {
898 	float result = -1;
899 /*
900 	if(pingThread == NULL) {
901 		lastThreadedPing = 0;
902 		pingThread = new SimpleTaskThread(this,0,50);
903 		pingThread->setUniqueID(__FILE__ + "_" + __FUNCTION);
904 		pingThread->start();
905 	}
906 
907 	if(pingCache.find(host) == pingCache.end()) {
908 		MutexSafeWrapper safeMutex(&pingThreadAccessor);
909 		safeMutex.ReleaseLock();
910 		result = getAveragePingMS(host, 1);
911 		pingCache[host]=result;
912 	}
913 	else {
914 		MutexSafeWrapper safeMutex(&pingThreadAccessor);
915 		result = pingCache[host];
916 		safeMutex.ReleaseLock();
917 	}
918 */
919 	return result;
920 }
921 
922 /*
923 void Socket::simpleTask(BaseThread *callingThread)  {
924 	// update ping times every x seconds
925 	const int pingFrequencySeconds = 2;
926 	if(difftime(time(NULL),lastThreadedPing) < pingFrequencySeconds) {
927 		return;
928 	}
929 	lastThreadedPing = time(NULL);
930 
931 	//printf("Pinging hosts...\n");
932 
933 	for(std::map<string,double>::iterator iterMap = pingCache.begin();
934 		iterMap != pingCache.end(); iterMap++) {
935 		MutexSafeWrapper safeMutex(&pingThreadAccessor,CODE_AT_LINE);
936 		iterMap->second = getAveragePingMS(iterMap->first, 1);
937 		safeMutex.ReleaseLock();
938 	}
939 }
940 */
941 
~Socket()942 Socket::~Socket() {
943 	MutexSafeWrapper safeMutexSocketDestructorFlag(inSocketDestructorSynchAccessor,CODE_AT_LINE);
944 	if(this->inSocketDestructor == true) {
945 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
946 		return;
947 	}
948 	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
949 	this->inSocketDestructor = true;
950 
951 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
952 
953 	//safeMutexSocketDestructorFlag.ReleaseLock();
954 
955     disconnectSocket();
956 
957     // Allow other callers with a lock on the mutexes to let them go
958 	for(time_t elapsed = time(NULL);
959 		(dataSynchAccessorRead->getRefCount() > 0 ||
960 		 dataSynchAccessorWrite->getRefCount() > 0) &&
961 		 difftime((long int)time(NULL),elapsed) <= 2;) {
962 		printf("Waiting in socket destructor\n");
963 		//sleep(0);
964 	}
965 
966 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
967 
968 	//delete pingThread;
969 	//pingThread = NULL;
970 	safeMutexSocketDestructorFlag.ReleaseLock();
971 
972 	delete dataSynchAccessorRead;
973 	dataSynchAccessorRead = NULL;
974 	delete dataSynchAccessorWrite;
975 	dataSynchAccessorWrite = NULL;
976 	delete inSocketDestructorSynchAccessor;
977 	inSocketDestructorSynchAccessor = NULL;
978 }
979 
disconnectSocket()980 void Socket::disconnectSocket() {
981 	//printf("Socket disconnecting sock = %d\n",sock);
982 
983 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
984 
985     if(isSocketValid() == true) {
986     	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
987 
988         MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
989         MutexSafeWrapper safeMutex1(dataSynchAccessorWrite,CODE_AT_LINE);
990 
991         if(isSocketValid() == true) {
992         ::shutdown(sock,2);
993 #ifndef WIN32
994         ::close(sock);
995         sock = -1;
996 #else
997         ::closesocket(sock);
998         sock = INVALID_SOCKET;
999 #endif
1000         }
1001         safeMutex.ReleaseLock();
1002         safeMutex1.ReleaseLock();
1003     }
1004 
1005     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
1006 }
1007 
1008 // Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
hasDataToRead(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList)1009 bool Socket::hasDataToRead(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList)
1010 {
1011     bool bResult = false;
1012 
1013     if(socketTriggeredList.empty() == false) {
1014         /* Watch stdin (fd 0) to see when it has input. */
1015         fd_set rfds;
1016         FD_ZERO(&rfds);
1017 
1018 		string socketDebugList = "";
1019         PLATFORM_SOCKET imaxsocket = 0;
1020         for(std::map<PLATFORM_SOCKET,bool>::iterator itermap = socketTriggeredList.begin();
1021             itermap != socketTriggeredList.end(); ++itermap) {
1022         	PLATFORM_SOCKET socket = itermap->first;
1023             if(Socket::isSocketValid(&socket) == true) {
1024                 FD_SET(socket, &rfds);
1025                 imaxsocket = max(socket,imaxsocket);
1026 
1027 				if(socketDebugList != "") {
1028 					socketDebugList += ",";
1029 				}
1030 				socketDebugList += intToStr(socket);
1031             }
1032         }
1033 
1034         if(imaxsocket > 0) {
1035             /* Wait up to 0 seconds. */
1036             struct timeval tv;
1037             tv.tv_sec = 0;
1038             tv.tv_usec = 0;
1039 
1040 
1041             int retval = 0;
1042             {
1043             	//MutexSafeWrapper safeMutex(&dataSynchAccessor);
1044             	retval = select((int)imaxsocket + 1, &rfds, NULL, NULL, &tv);
1045             }
1046             if(retval < 0) {
1047 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s, socketDebugList [%s]\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str(),socketDebugList.c_str());
1048 				printf("In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str());
1049             }
1050             else if(retval) {
1051                 bResult = true;
1052 
1053                 for(std::map<PLATFORM_SOCKET,bool>::iterator itermap = socketTriggeredList.begin();
1054                     itermap != socketTriggeredList.end(); ++itermap) {
1055                 	PLATFORM_SOCKET socket = itermap->first;
1056                     if (FD_ISSET(socket, &rfds)) {
1057                         itermap->second = true;
1058                     }
1059                     else {
1060                         itermap->second = false;
1061                     }
1062                 }
1063             }
1064         }
1065     }
1066 
1067     return bResult;
1068 }
1069 
hasDataToRead()1070 bool Socket::hasDataToRead()
1071 {
1072 	MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1073     return Socket::hasDataToRead(sock) ;
1074 }
1075 
hasDataToRead(PLATFORM_SOCKET socket)1076 bool Socket::hasDataToRead(PLATFORM_SOCKET socket)
1077 {
1078     bool bResult = false;
1079 
1080     if(Socket::isSocketValid(&socket) == true)
1081     {
1082         fd_set rfds;
1083         struct timeval tv;
1084 
1085         /* Watch stdin (fd 0) to see when it has input. */
1086         FD_ZERO(&rfds);
1087         FD_SET(socket, &rfds);
1088 
1089         /* Wait up to 0 seconds. */
1090         tv.tv_sec = 0;
1091         tv.tv_usec = 0;
1092 
1093         int retval = 0;
1094         {
1095         	//MutexSafeWrapper safeMutex(&dataSynchAccessor);
1096         	retval = select((int)socket + 1, &rfds, NULL, NULL, &tv);
1097         }
1098         if(retval < 0) {
1099 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str());
1100 			printf("In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str());
1101         }
1102         else if(retval)
1103         {
1104             if (FD_ISSET(socket, &rfds))
1105             {
1106                 bResult = true;
1107             }
1108         }
1109     }
1110 
1111     return bResult;
1112 }
1113 
hasDataToReadWithWait(int waitMicroseconds)1114 bool Socket::hasDataToReadWithWait(int waitMicroseconds) {
1115 	MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1116     return Socket::hasDataToReadWithWait(sock,waitMicroseconds) ;
1117 }
1118 
hasDataToReadWithWait(PLATFORM_SOCKET socket,int waitMicroseconds)1119 bool Socket::hasDataToReadWithWait(PLATFORM_SOCKET socket,int waitMicroseconds) {
1120     bool bResult = false;
1121 
1122     Chrono chono;
1123     chono.start();
1124     if(Socket::isSocketValid(&socket) == true)
1125     {
1126         fd_set rfds;
1127         struct timeval tv;
1128 
1129         /* Watch stdin (fd 0) to see when it has input. */
1130         FD_ZERO(&rfds);
1131         FD_SET(socket, &rfds);
1132 
1133         /* Wait up to 0 seconds. */
1134         tv.tv_sec = 0;
1135         tv.tv_usec = waitMicroseconds;
1136 
1137         int retval = 0;
1138         {
1139         	//MutexSafeWrapper safeMutex(&dataSynchAccessor);
1140         	retval = select((int)socket + 1, &rfds, NULL, NULL, &tv);
1141         }
1142 		if(retval < 0) {
1143 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str());
1144 			printf("In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,retval,getLastSocketErrorFormattedText().c_str());
1145 		}
1146 
1147         if(retval)
1148         {
1149             if (FD_ISSET(socket, &rfds))
1150             {
1151                 bResult = true;
1152             }
1153         }
1154     }
1155 
1156     //printf("hasdata waited [%d] milliseconds [%d], bResult = %d\n",chono.getMillis(),waitMilliseconds,bResult);
1157     return bResult;
1158 }
1159 
getDataToRead(bool wantImmediateReply)1160 int Socket::getDataToRead(bool wantImmediateReply) {
1161 	unsigned long size = 0;
1162 
1163     //fd_set rfds;
1164     //struct timeval tv;
1165     //int retval;
1166 
1167     /* Watch stdin (fd 0) to see when it has input. */
1168     //FD_ZERO(&rfds);
1169     //FD_SET(sock, &rfds);
1170 
1171     /* Wait up to 0 seconds. */
1172     //tv.tv_sec = 0;
1173     //tv.tv_usec = 0;
1174 
1175     //retval = select(sock + 1, &rfds, NULL, NULL, &tv);
1176     //if(retval)
1177     if(isSocketValid() == true)
1178     {
1179     	//int loopCount = 1;
1180     	for(time_t elapsed = time(NULL); difftime((long int)time(NULL),elapsed) < 1;) {
1181 			/* ioctl isn't posix, but the following seems to work on all modern
1182 			 * unixes */
1183 	#ifndef WIN32
1184 			int err = ioctl(sock, FIONREAD, &size);
1185 	#else
1186 			int err= ioctlsocket(sock, FIONREAD, &size);
1187 	#endif
1188 			int lastSocketError = getLastSocketError();
1189 			if(err < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN)
1190 			{
1191 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR PEEKING SOCKET DATA, err = %d %s\n",__FILE__,__FUNCTION__,__LINE__,err,getLastSocketErrorFormattedText().c_str());
1192 				break;
1193 			}
1194 			else if(err == 0)
1195 			{
1196 				if(isConnected() == false) {
1197 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR PEEKING SOCKET DATA, err = %d %s\n",__FILE__,__FUNCTION__,__LINE__,err,getLastSocketErrorFormattedText().c_str());
1198 					break;
1199 				}
1200 			}
1201 
1202 			if(size > 0) {
1203 				break;
1204 			}
1205 			else if(hasDataToRead() == true) {
1206 				//if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING PEEKING SOCKET DATA, (hasDataToRead() == true) err = %d, sock = %d, size = " MG_SIZE_T_SPECIFIER ", loopCount = %d\n",__FILE__,__FUNCTION__,__LINE__,err,sock,size,loopCount);
1207 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING PEEKING SOCKET DATA, (hasDataToRead() == true) err = %d, sock = %d, size = " MG_SIZE_T_SPECIFIER "\n",__FILE__,__FUNCTION__,__LINE__,err,sock,size);
1208 			}
1209 			else {
1210 				//if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING PEEKING SOCKET DATA, err = %d, sock = %d, size = " MG_SIZE_T_SPECIFIER ", loopCount = %d\n",__FILE__,__FUNCTION__,__LINE__,err,sock,size,loopCount);
1211 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING PEEKING SOCKET DATA, err = %d, sock = %d, size = " MG_SIZE_T_SPECIFIER "\n",__FILE__,__FUNCTION__,__LINE__,err,sock,size);
1212 				break;
1213 			}
1214 
1215 			if(wantImmediateReply == true) {
1216 				break;
1217 			}
1218 
1219 			//loopCount++;
1220     	}
1221     }
1222 
1223 	return static_cast<int>(size);
1224 }
1225 
send(const void * data,int dataSize)1226 int Socket::send(const void *data, int dataSize) {
1227 	const int MAX_SEND_WAIT_SECONDS = 3;
1228 
1229 	int bytesSent= 0;
1230 	if(isSocketValid() == true)	{
1231 		errno = 0;
1232 
1233 //    	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1234 //    	if(this->inSocketDestructor == true) {
1235 //    		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1236 //    		return -1;
1237 //    	}
1238 //    	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1239 //    	safeMutexSocketDestructorFlag.ReleaseLock();
1240 
1241 		MutexSafeWrapper safeMutex(dataSynchAccessorWrite,CODE_AT_LINE);
1242 
1243 		if(isSocketValid() == true)	{
1244 #ifdef __APPLE__
1245         bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE);
1246 #else
1247         bytesSent = ::send(sock, (const char *)data, dataSize, MSG_NOSIGNAL | MSG_DONTWAIT);
1248 #endif
1249 		}
1250         safeMutex.ReleaseLock();
1251 	}
1252 
1253 	// TEST errors
1254 	//bytesSent = -1;
1255 	// END TEST
1256 
1257 	int lastSocketError = getLastSocketError();
1258 	if(bytesSent < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1259 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR WRITING SOCKET DATA, err = %d error = %s dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText(&lastSocketError).c_str(),dataSize);
1260 	}
1261 	else if(bytesSent < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN && isConnected() == true) {
1262 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during send, trying again... dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,dataSize);
1263 
1264 		int attemptCount = 0;
1265 	    time_t tStartTimer = time(NULL);
1266 	    while((bytesSent < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN) &&
1267 	    		(difftime((long int)time(NULL),tStartTimer) <= MAX_SEND_WAIT_SECONDS)) {
1268 	    	attemptCount++;
1269 	    	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount);
1270 
1271 	    	MutexSafeWrapper safeMutex(dataSynchAccessorWrite,CODE_AT_LINE);
1272             if(isConnected() == true) {
1273             	struct timeval timeVal;
1274             	timeVal.tv_sec = 1;
1275             	timeVal.tv_usec = 0;
1276             	bool canWrite = isWritable(&timeVal);
1277 
1278             	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p, canWrite = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data,canWrite);
1279 
1280 //	        	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1281 //	        	if(this->inSocketDestructor == true) {
1282 //	        		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1283 //	        		return -1;
1284 //	        	}
1285 //	        	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1286 //	        	safeMutexSocketDestructorFlag.ReleaseLock();
1287 
1288 
1289 #ifdef __APPLE__
1290                 bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE);
1291 #else
1292                 bytesSent = ::send(sock, (const char *)data, dataSize, MSG_NOSIGNAL | MSG_DONTWAIT);
1293 #endif
1294 				lastSocketError = getLastSocketError();
1295                 if(bytesSent < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1296                     break;
1297                 }
1298 
1299                 //safeMutex.ReleaseLock();
1300 
1301                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,__LINE__,bytesSent);
1302 	        }
1303 	        else {
1304                 int iErr = getLastSocketError();
1305 
1306                 safeMutex.ReleaseLock();
1307                 disconnectSocket();
1308 
1309                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, error = %s\n",__FILE__,__FUNCTION__,bytesSent,getLastSocketErrorFormattedText(&iErr).c_str());
1310                 break;
1311 
1312 	        }
1313             if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount);
1314 	    }
1315 	}
1316 
1317 	if(isConnected() == true && bytesSent > 0 && bytesSent < dataSize) {
1318 		lastSocketError = getLastSocketError();
1319 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] need to send more data, trying again getLastSocketError() = %d, bytesSent = %d, dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,lastSocketError,bytesSent,dataSize);
1320 
1321 		int totalBytesSent = bytesSent;
1322 		int attemptCount = 0;
1323 
1324 
1325 	    time_t tStartTimer = time(NULL);
1326 	    while(((bytesSent > 0 && totalBytesSent < dataSize) ||
1327 	    		(bytesSent < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN)) &&
1328 	    		(difftime((long int)time(NULL),tStartTimer) <= MAX_SEND_WAIT_SECONDS)) {
1329 	    	attemptCount++;
1330 	    	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, totalBytesSent = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,totalBytesSent);
1331 
1332 	    	MutexSafeWrapper safeMutex(dataSynchAccessorWrite,CODE_AT_LINE);
1333             if(isConnected() == true) {
1334             	struct timeval timeVal;
1335             	timeVal.tv_sec = 1;
1336             	timeVal.tv_usec = 0;
1337             	bool canWrite = isWritable(&timeVal);
1338 
1339             	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p, canWrite = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data,canWrite);
1340 
1341 //	        	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1342 //	        	if(this->inSocketDestructor == true) {
1343 //	        		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1344 //	        		return -1;
1345 //	        	}
1346 //	        	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1347 //	        	safeMutexSocketDestructorFlag.ReleaseLock();
1348 
1349 
1350 	        	const char *sendBuf = (const char *)data;
1351 #ifdef __APPLE__
1352 			    bytesSent = ::send(sock, &sendBuf[totalBytesSent], dataSize - totalBytesSent, SO_NOSIGPIPE);
1353 #else
1354 			    bytesSent = ::send(sock, &sendBuf[totalBytesSent], dataSize - totalBytesSent, MSG_NOSIGNAL | MSG_DONTWAIT);
1355 #endif
1356 				lastSocketError = getLastSocketError();
1357                 if(bytesSent > 0) {
1358                 	totalBytesSent += bytesSent;
1359                 }
1360 
1361                 if(bytesSent < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1362                     break;
1363                 }
1364 
1365 			    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] retry send returned: %d\n",__FILE__,__FUNCTION__,__LINE__,bytesSent);
1366 	        }
1367 	        else {
1368                 int iErr = getLastSocketError();
1369 
1370                 safeMutex.ReleaseLock();
1371                 disconnectSocket();
1372 
1373                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText(&iErr).c_str());
1374 	            break;
1375 	        }
1376 
1377             if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount);
1378 	    }
1379 
1380 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] bytesSent = %d, totalBytesSent = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,totalBytesSent);
1381 
1382 	    if(bytesSent > 0) {
1383 	    	bytesSent = totalBytesSent;
1384 	    }
1385 	}
1386 
1387 	if(bytesSent <= 0 || isConnected() == false) {
1388 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR WRITING SOCKET DATA, err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText().c_str());
1389 
1390 	    int iErr = getLastSocketError();
1391 	    disconnectSocket();
1392 
1393 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText(&iErr).c_str());
1394 	}
1395 
1396 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,__LINE__,sock,bytesSent);
1397 
1398 	return static_cast<int>(bytesSent);
1399 }
1400 
receive(void * data,int dataSize,bool tryReceiveUntilDataSizeMet)1401 int Socket::receive(void *data, int dataSize, bool tryReceiveUntilDataSizeMet) {
1402 	ssize_t bytesReceived = 0;
1403 
1404 	if(isSocketValid() == true)	{
1405 		MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1406 		if(isSocketValid() == true)	{
1407 			bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
1408 		}
1409 	    safeMutex.ReleaseLock();
1410 	}
1411 
1412 	int lastSocketError = getLastSocketError();
1413 	if(bytesReceived < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1414 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&lastSocketError).c_str());
1415 	}
1416 	else if(bytesReceived < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN)	{
1417 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__,__LINE__);
1418 
1419 		Chrono chronoElapsed(true);
1420 		const int MAX_RECV_WAIT_SECONDS = 3;
1421 	    time_t tStartTimer = time(NULL);
1422 	    while((bytesReceived < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN) &&
1423 	    		(difftime((long int)time(NULL),tStartTimer) <= MAX_RECV_WAIT_SECONDS)) {
1424 	        if(isConnected() == false) {
1425 	        	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] Socket is NOT connected!\n",__FILE__,__FUNCTION__,__LINE__);
1426 
1427 	        	int iErr = getLastSocketError();
1428                 disconnectSocket();
1429 
1430                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while receiving socket data, bytesSent = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&iErr).c_str());
1431 	            break;
1432 	        }
1433 	        //else if(Socket::isReadable(true) == true) {
1434 	        else {
1435 				if(Socket::isReadable(true) == true) {
1436 					MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1437 
1438 					//SafeSocketBlockToggleWrapper safeBlock(this, true);
1439 					errno = 0;
1440 					bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
1441 					lastSocketError = getLastSocketError();
1442 					//safeBlock.Restore();
1443 					safeMutex.ReleaseLock();
1444 
1445 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 EAGAIN during receive, trying again returned: %d, lastSocketError = %d, dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,lastSocketError,(int)dataSize);
1446 					//printf("In [%s::%s Line: %d] #2 EAGAIN during receive, trying again returned: %d, lastSocketError = %d, dataSize = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,lastSocketError,(int)dataSize);
1447 				}
1448 				else {
1449 					//if(chronoElapsed.getMillis() % 3 == 0) {
1450 					//	sleep(1);
1451 					//}
1452 					//else {
1453 					sleep(0);
1454 					//}
1455 				}
1456 	        }
1457 	    }
1458 	}
1459 
1460 	if(bytesReceived <= 0) {
1461 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] bytesReceived = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived);
1462 
1463 	    int iErr = getLastSocketError();
1464 	    disconnectSocket();
1465 
1466 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, error = %s, dataSize = %d, tryReceiveUntilDataSizeMet = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&iErr).c_str(),dataSize,tryReceiveUntilDataSizeMet);
1467 	}
1468 	else if(tryReceiveUntilDataSizeMet == true && bytesReceived < dataSize) {
1469 		int newBufferSize = (dataSize - (int)bytesReceived);
1470 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING, attempting to receive MORE data, bytesReceived = %d, dataSize = %d, newBufferSize = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,dataSize,newBufferSize);
1471 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nIn [%s::%s Line: %d] WARNING, attempting to receive MORE data, bytesReceived = %d, dataSize = %d, newBufferSize = %d\n",__FILE__,__FUNCTION__,__LINE__,(int)bytesReceived,dataSize,newBufferSize);
1472 
1473 		char *dataAsCharPointer = reinterpret_cast<char *>(data);
1474 		int additionalBytes = receive(&dataAsCharPointer[bytesReceived], newBufferSize, tryReceiveUntilDataSizeMet);
1475 
1476 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING, additionalBytes = %d\n",__FILE__,__FUNCTION__,__LINE__,additionalBytes);
1477 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nIn [%s::%s Line: %d] WARNING, additionalBytes = %d\n",__FILE__,__FUNCTION__,__LINE__,additionalBytes);
1478 
1479 		if(additionalBytes > 0) {
1480 			bytesReceived += additionalBytes;
1481 		}
1482 		else {
1483 			//throw megaglest_runtime_error("additionalBytes == " + intToStr(additionalBytes));
1484 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] additionalBytes == %d\n",__FILE__,__FUNCTION__,__LINE__,additionalBytes);
1485 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nIn [%s::%s Line: %d] additionalBytes == %d\n",__FILE__,__FUNCTION__,__LINE__,additionalBytes);
1486 			if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] additionalBytes == %d\n",__FILE__,__FUNCTION__,__LINE__,additionalBytes);
1487 
1488 		    int iErr = getLastSocketError();
1489 		    disconnectSocket();
1490 
1491 		    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, error = %s, dataSize = %d, tryReceiveUntilDataSizeMet = %d\n",__FILE__,__FUNCTION__,__LINE__,bytesReceived,getLastSocketErrorFormattedText(&iErr).c_str(),dataSize,tryReceiveUntilDataSizeMet);
1492 		}
1493 	}
1494 	return static_cast<int>(bytesReceived);
1495 }
1496 
SafeSocketBlockToggleWrapper(Socket * socket,bool toggle)1497 SafeSocketBlockToggleWrapper::SafeSocketBlockToggleWrapper(Socket *socket, bool toggle) {
1498 	this->socket = socket;
1499 
1500 	if(this->socket != NULL) {
1501 		this->originallyBlocked = socket->getBlock();
1502 		this->newBlocked = toggle;
1503 
1504 		if(this->originallyBlocked != this->newBlocked) {
1505 			socket->setBlock(this->newBlocked);
1506 		}
1507 	}
1508 	else {
1509 		this->originallyBlocked = false;
1510 		this->newBlocked = false;
1511 	}
1512 }
1513 
Restore()1514 void SafeSocketBlockToggleWrapper::Restore() {
1515 	if(this->socket != NULL) {
1516 		if(this->originallyBlocked != this->newBlocked) {
1517 			socket->setBlock(this->originallyBlocked);
1518 			this->newBlocked = this->originallyBlocked;
1519 		}
1520 	}
1521 }
1522 
~SafeSocketBlockToggleWrapper()1523 SafeSocketBlockToggleWrapper::~SafeSocketBlockToggleWrapper() {
1524 	Restore();
1525 }
1526 
peek(void * data,int dataSize,bool mustGetData,int * pLastSocketError)1527 int Socket::peek(void *data, int dataSize,bool mustGetData,int *pLastSocketError) {
1528 	Chrono chrono;
1529 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) chrono.start();
1530 
1531     int lastSocketError = 0;
1532 	int err = 0;
1533 	if(isSocketValid() == true) {
1534 		//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1535 
1536 //    	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1537 //    	if(this->inSocketDestructor == true) {
1538 //    		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1539 //    		return -1;
1540 //    	}
1541 //    	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1542 //    	safeMutexSocketDestructorFlag.ReleaseLock();
1543 
1544 		//MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize));
1545 
1546 
1547 		//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1548 		if(isSocketValid() == true)	{
1549 			MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1550 //			Chrono recvTimer(true);
1551 			SafeSocketBlockToggleWrapper safeUnblock(this, false);
1552 			errno = 0;
1553 			err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
1554 			lastSocketError = getLastSocketError();
1555 			if(pLastSocketError != NULL) {
1556 				*pLastSocketError = lastSocketError;
1557 			}
1558 			safeUnblock.Restore();
1559 
1560 //			if(recvTimer.getMillis() > 1000 || (err <= 0 && lastSocketError != 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN)) {
1561 //				printf("#1 PEEK err = %d lastSocketError = %d ms: %lld\n",err,lastSocketError,(long long int)recvTimer.getMillis());
1562 
1563 			//if(err != dataSize) {
1564 			//	printf("#1 PEEK err = %d lastSocketError = %d\n",err,lastSocketError);
1565 			//}
1566 
1567 //			}
1568 			safeMutex.ReleaseLock();
1569 		}
1570 	    //safeMutex.ReleaseLock();
1571 
1572 	    //printf("Peek #1 err = %d\n",err);
1573 
1574 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) if(chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1575 	}
1576 	else {
1577 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] SOCKET appears to be invalid [%d]\n",__FILE__,__FUNCTION__,__LINE__,sock);
1578 	}
1579 	//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1580 
1581 	if(err < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1582 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] ERROR PEEKING SOCKET DATA error while sending socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,err,getLastSocketErrorFormattedText().c_str());
1583 		disconnectSocket();
1584 	}
1585 	else if(err < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN && mustGetData == true) {
1586 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 ERROR EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__,__LINE__);
1587 
1588 		//printf("Peek #2 err = %d\n",err);
1589 
1590 		Chrono chronoElapsed(true);
1591 		const int MAX_PEEK_WAIT_SECONDS = 3;
1592 	    time_t tStartTimer = time(NULL);
1593 	    while((err < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN) &&
1594 	    		isSocketValid() == true &&
1595 	    		(difftime((long int)time(NULL),tStartTimer) <= MAX_PEEK_WAIT_SECONDS)) {
1596 /*
1597 	        if(isConnected() == false) {
1598                 int iErr = getLastSocketError();
1599                 disconnectSocket();
1600 	            break;
1601 	        }
1602 */
1603 	        if(Socket::isReadable(true) == true || chronoElapsed.getMillis() % 100 == 0) {
1604 
1605 //	        	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1606 //	        	if(this->inSocketDestructor == true) {
1607 //	        		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1608 //	        		return -1;
1609 //	        	}
1610 //	        	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1611 //	        	safeMutexSocketDestructorFlag.ReleaseLock();
1612 
1613 	        	//MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize));
1614 	        	MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1615 
1616 //	        	Chrono recvTimer(true);
1617 	        	SafeSocketBlockToggleWrapper safeUnblock(this, false);
1618 	        	errno = 0;
1619                 err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
1620 				lastSocketError = getLastSocketError();
1621 				if(pLastSocketError != NULL) {
1622 					*pLastSocketError = lastSocketError;
1623 				}
1624 				safeUnblock.Restore();
1625 
1626 //                if(recvTimer.getMillis() > 1000 || (err <= 0 && lastSocketError != 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN)) {
1627 //    				printf("#2 PEEK err = %d lastSocketError = %d ms: %lld\n",err,lastSocketError,(long long int)recvTimer.getMillis());
1628 //    			}
1629 
1630 				//printf("Socket peek delayed checking for sock = %d err = %d\n",sock,err);
1631 
1632                 safeMutex.ReleaseLock();
1633 
1634                 if(err == 0 || err == PLATFORM_SOCKET_TRY_AGAIN) {
1635                 	sleep(0);
1636                 }
1637                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) if(chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1638                 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,__LINE__,err);
1639 	        }
1640 	        //else {
1641 	        	//printf("Socket peek delayed [NOT READABLE] checking for sock = %d err = %d\n",sock,err);
1642 	        //}
1643 	    }
1644 
1645 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) if(chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1646 	}
1647 	else if (err == 0) {
1648 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 SOCKET appears to be invalid [%d] lastSocketError [%d] err [%d] mustGetData [%d] dataSize [%d]\n",__FILE__,__FUNCTION__,__LINE__,sock,lastSocketError,err,mustGetData,dataSize);
1649 	}
1650 
1651 	//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1652 
1653 	if(err < 0 || (err == 0 && dataSize != 0) ||
1654 		((err == 0 || err == -1) && dataSize == 0 && lastSocketError != 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN)) {
1655 		//printf("** #1 Socket peek error for sock = %d err = %d lastSocketError = %d\n",sock,err,lastSocketError);
1656 
1657 		int iErr = lastSocketError;
1658 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTING SOCKET for socket [%d], err = %d, dataSize = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,dataSize,getLastSocketErrorFormattedText(&iErr).c_str());
1659 		//printf("Peek #3 err = %d\n",err);
1660 		//lastSocketError = getLastSocketError();
1661 		if(mustGetData == true || lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1662 			printf("** #2 Socket peek error for sock = %d err = %d lastSocketError = %d mustGetData = %d\n",sock,err,lastSocketError,mustGetData);
1663 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTING SOCKET for socket [%d], err = %d, dataSize = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,dataSize,getLastSocketErrorFormattedText(&iErr).c_str());
1664 
1665 			if(err == 0) {
1666 				printf("** LAST CHANCE for disconnection check for sock = %d\n",sock);
1667 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"** LAST CHANCE for disconnection check for sock = %d\n",sock);
1668 
1669 				MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1670 				SafeSocketBlockToggleWrapper safeUnblock(this, false);
1671 				errno = 0;
1672 				int second_err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
1673 				safeUnblock.Restore();
1674 				safeMutex.ReleaseLock();
1675 
1676 				if(second_err == 0 || second_err < 0) {
1677 					printf("** Disconnecting sock = %d\n",sock);
1678 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"** Disconnecting sock = %d\n",sock);
1679 
1680 					disconnectSocket();
1681 				}
1682 			}
1683 			else {
1684 				printf("** Disconnecting sock = %d\n",sock);
1685 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"** Disconnecting sock = %d\n",sock);
1686 
1687 				disconnectSocket();
1688 			}
1689 
1690 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] DISCONNECTED SOCKET error while peeking socket data for socket [%d], err = %d, dataSize = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,dataSize,getLastSocketErrorFormattedText(&iErr).c_str());
1691 		}
1692 	}
1693 
1694 	return static_cast<int>(err);
1695 }
1696 
getBlock()1697 bool Socket::getBlock() {
1698 	bool blocking = true;
1699 
1700 	// don't waste time if the socket is invalid
1701 	if(isSocketValid(&sock) == false) {
1702 		return blocking;
1703 	}
1704 
1705 //#ifndef WIN32
1706 //	int currentFlags = fcntl(sock, F_GETFL);
1707 //	blocking = !((currentFlags & O_NONBLOCK) == O_NONBLOCK);
1708 //#else
1709 	blocking = this->isSocketBlocking;
1710 //#endif
1711 	return blocking;
1712 }
1713 
setBlock(bool block)1714 void Socket::setBlock(bool block){
1715 	setBlock(block,this->sock);
1716 	this->isSocketBlocking = block;
1717 }
1718 
setBlock(bool block,PLATFORM_SOCKET socket)1719 void Socket::setBlock(bool block, PLATFORM_SOCKET socket) {
1720 	// don't waste time if the socket is invalid
1721 	if(isSocketValid(&socket) == false) {
1722 		return;
1723 	}
1724 
1725 #ifndef WIN32
1726 	int currentFlags = fcntl(socket, F_GETFL);
1727 	if(currentFlags < 0) {
1728 		currentFlags = 0;
1729 	}
1730 	if(block == true) {
1731 		currentFlags &= (~O_NONBLOCK);
1732 	}
1733 	else {
1734 		currentFlags |= O_NONBLOCK;
1735 	}
1736 	int err= fcntl(socket, F_SETFL, currentFlags);
1737 #else
1738 	u_long iMode= !block;
1739 	int err= ioctlsocket(socket, FIONBIO, &iMode);
1740 #endif
1741 	if(err < 0) {
1742 		throwException("Error setting I/O mode for socket");
1743 	}
1744 }
1745 
isReadable(bool lockMutex)1746 inline bool Socket::isReadable(bool lockMutex) {
1747     if(isSocketValid() == false) return false;
1748 
1749     struct timeval tv;
1750 	tv.tv_sec= 0;
1751 	tv.tv_usec= 0;
1752 
1753 	fd_set set;
1754 	FD_ZERO(&set);
1755 
1756 	Mutex *lockMutexObj = (lockMutex == true ? dataSynchAccessorRead : NULL);
1757 	MutexSafeWrapper safeMutex(lockMutexObj,CODE_AT_LINE);
1758 	//if(lockMutex == true) {
1759 	//	safeMutex.setMutex(dataSynchAccessorRead,CODE_AT_LINE);
1760 	//}
1761 	FD_SET(sock, &set);
1762 	int i = select((int)sock + 1, &set, NULL, NULL, &tv);
1763 	safeMutex.ReleaseLock();
1764 
1765 	if(i < 0) {
1766 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,i,getLastSocketErrorFormattedText().c_str());
1767 		printf("In [%s::%s] Line: %d, ERROR SELECTING SOCKET DATA retval = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str());
1768 	}
1769 
1770 	bool result = (i == 1);
1771 	//if(result == false) {
1772 	//	SystemFlags::OutputDebug(SystemFlags::debugError,"SOCKET DISCONNECTED In [%s::%s Line: %d] i = %d sock = %d\n",__FILE__,__FUNCTION__,__LINE__,i,sock);
1773 	//}
1774 	return result;
1775 }
1776 
isWritable(struct timeval * timeVal,bool lockMutex)1777 inline bool Socket::isWritable(struct timeval *timeVal, bool lockMutex) {
1778     if(isSocketValid() == false) return false;
1779 
1780 	struct timeval tv;
1781 	if(timeVal != NULL) {
1782 		tv = *timeVal;
1783 	}
1784 	else {
1785 		tv.tv_sec= 0;
1786 		tv.tv_usec= 0;
1787 	}
1788 
1789 	fd_set set;
1790 	FD_ZERO(&set);
1791 
1792 	Mutex *lockMutexObj = (lockMutex == true ? dataSynchAccessorWrite : NULL);
1793 	MutexSafeWrapper safeMutex(lockMutexObj,CODE_AT_LINE);
1794 //	MutexSafeWrapper safeMutex(NULL,CODE_AT_LINE);
1795 //	if(lockMutex == true) {
1796 //		safeMutex.setMutex(dataSynchAccessorWrite,CODE_AT_LINE);
1797 //	}
1798 	FD_SET(sock, &set);
1799 	int i = select((int)sock + 1, NULL, &set, NULL, &tv);
1800 	safeMutex.ReleaseLock();
1801 
1802 	bool result = false;
1803 	if(i < 0 ) {
1804 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str());
1805 
1806 		SystemFlags::OutputDebug(SystemFlags::debugError,"SOCKET DISCONNECTED In [%s::%s Line: %d] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str());
1807 	}
1808 	else if(i == 0) {
1809 		//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] TIMEOUT while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str());
1810 		// Assume we are still connected, write buffer could be very busy
1811 		result = true;
1812 		if(difftime(time(NULL),lastSocketError) > 1) {
1813 			lastSocketError = time(NULL);
1814 			SystemFlags::OutputDebug(SystemFlags::debugError,"SOCKET WRITE TIMEOUT In [%s::%s Line: %d] i = %d sock = %d [%s]\n",__FILE__,__FUNCTION__,__LINE__,i,sock,ipAddress.c_str());
1815 		}
1816 	}
1817 	else {
1818 		result = true;
1819 	}
1820 
1821 	//return (i == 1 && FD_ISSET(sock, &set));
1822 	return result;
1823 }
1824 
isConnected()1825 bool Socket::isConnected() {
1826 	if(isSocketValid() == false) return false;
1827 
1828 //	MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE);
1829 //	if(this->inSocketDestructor == true) {
1830 //		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
1831 //		return false;
1832 //	}
1833 //	inSocketDestructorSynchAccessor->setOwnerId(CODE_AT_LINE);
1834 
1835 	//if the socket is not writable then it is not conencted
1836 	if(isWritable(NULL,true) == false) {
1837 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] ERROR isWritable failed.\n",__FILE__,__FUNCTION__,__LINE__);
1838 		return false;
1839 	}
1840 	//if the socket is readable it is connected if we can read a byte from it
1841 	if(isReadable(true)) {
1842 		char tmp=0;
1843 		int peekDataBytes=1;
1844 		int lastSocketError=0;
1845 
1846 		int err = peek(&tmp, peekDataBytes, false, &lastSocketError);
1847 		//if(err <= 0 && err != PLATFORM_SOCKET_TRY_AGAIN) {
1848 		//if(err <= 0 && lastSocketError != 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) {
1849 		//if((err < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) || (err == 0 && peekDataBytes != 0) ||
1850 		//	((err == 0 || err == -1) && peekDataBytes == 0 && lastSocketError != 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN)) {
1851 		if((err < 0 && lastSocketError != PLATFORM_SOCKET_TRY_AGAIN) || (err == 0 && peekDataBytes != 0)) {
1852 			//printf("IsConnected socket has disconnected sock = %d err = %d lastSocketError = %d\n",sock,err,lastSocketError);
1853 			if(err == 0) {
1854 				printf("IsConnected socket has disconnected sock = %d err = %d lastSocketError = %d\n",sock,err,lastSocketError);
1855 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] ERROR Peek failed, err = %d for socket: %d, error = %s, lastSocketError = %d\n",__FILE__,__FUNCTION__,__LINE__,err,sock,getLastSocketErrorFormattedText().c_str(),lastSocketError);
1856 			}
1857 
1858 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] ERROR Peek failed, err = %d for socket: %d, error = %s, lastSocketError = %d\n",__FILE__,__FUNCTION__,__LINE__,err,sock,getLastSocketErrorFormattedText().c_str(),lastSocketError);
1859 			if(SystemFlags::VERBOSE_MODE_ENABLED) SystemFlags::OutputDebug(SystemFlags::debugError,"SOCKET DISCONNECTED In [%s::%s Line: %d] ERROR Peek failed, err = %d for socket: %d, error = %s, lastSocketError = %d\n",__FILE__,__FUNCTION__,__LINE__,err,sock,getLastSocketErrorFormattedText().c_str(),lastSocketError);
1860 			return false;
1861 		}
1862 		if (isSocketValid() == false) return false;
1863 	}
1864 
1865 	//otherwise the socket is connected
1866 	return true;
1867 }
1868 
getHostName()1869 string Socket::getHostName()  {
1870 	if(Socket::host_name == "") {
1871 		const int strSize= 257;
1872 		char hostname[strSize]="";
1873 		int result = gethostname(hostname, strSize);
1874 		if(result == 0) {
1875 			Socket::host_name = (hostname[0] != '\0' ? hostname : "");
1876 		}
1877 		else {
1878 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] result = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,result,getLastSocketErrorText());
1879 		}
1880 	}
1881 	return Socket::host_name;
1882 }
1883 
getIp()1884 string Socket::getIp() {
1885 	hostent* info= gethostbyname(getHostName().c_str());
1886 	unsigned char* address;
1887 
1888 	if(info==NULL){
1889 		throw megaglest_runtime_error("Error getting host by name");
1890 	}
1891 
1892 	address= reinterpret_cast<unsigned char*>(info->h_addr_list[0]);
1893 
1894 	if(address==NULL){
1895 		throw megaglest_runtime_error("Error getting host ip");
1896 	}
1897 
1898 	return
1899 		intToStr(address[0]) + "." +
1900 		intToStr(address[1]) + "." +
1901 		intToStr(address[2]) + "." +
1902 		intToStr(address[3]);
1903 }
1904 
throwException(string str)1905 void Socket::throwException(string str){
1906 	string msg = str + " " + getLastSocketErrorFormattedText();
1907 	throw megaglest_runtime_error(msg);
1908 }
1909 
1910 // ===============================================
1911 //	class ClientSocket
1912 // ===============================================
1913 
ClientSocket()1914 ClientSocket::ClientSocket() : Socket() {
1915 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1916 
1917 	stopBroadCastClientThread();
1918 
1919 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1920 }
1921 
~ClientSocket()1922 ClientSocket::~ClientSocket() {
1923 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1924 
1925 	stopBroadCastClientThread();
1926 
1927 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1928 }
1929 
stopBroadCastClientThread()1930 void ClientSocket::stopBroadCastClientThread() {
1931 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1932 
1933 	if(broadCastClientThread != NULL) {
1934 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1935 		broadCastClientThread->shutdownAndWait();
1936 		delete broadCastClientThread;
1937 		broadCastClientThread = NULL;
1938 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1939 	}
1940 
1941 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1942 }
1943 
startBroadCastClientThread(DiscoveredServersInterface * cb)1944 void ClientSocket::startBroadCastClientThread(DiscoveredServersInterface *cb) {
1945 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1946 
1947 	ClientSocket::stopBroadCastClientThread();
1948 
1949 	static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
1950 	broadCastClientThread = new BroadCastClientSocketThread(cb);
1951 	broadCastClientThread->setUniqueID(mutexOwnerId);
1952 	broadCastClientThread->start();
1953 
1954 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1955 }
1956 
discoverServers(DiscoveredServersInterface * cb)1957 void ClientSocket::discoverServers(DiscoveredServersInterface *cb) {
1958 	ClientSocket::startBroadCastClientThread(cb);
1959 }
1960 
connect(const Ip & ip,int port)1961 void ClientSocket::connect(const Ip &ip, int port)
1962 {
1963 	sockaddr_in addr;
1964 	memset(&addr, 0, sizeof(addr));
1965 
1966     addr.sin_family= AF_INET;
1967 	addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
1968 	addr.sin_port= htons(port);
1969 
1970 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Connecting to host [%s] on port = %d\n", ip.getString().c_str(),port);
1971 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("Connecting to host [%s] on port = %d\n", ip.getString().c_str(),port);
1972 
1973     connectedIpAddress = "";
1974 	int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
1975 	if(err < 0)	{
1976 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str());
1977 	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str());
1978 
1979 		int lastSocketError = getLastSocketError();
1980         if (lastSocketError == PLATFORM_SOCKET_INPROGRESS ||
1981         	lastSocketError == PLATFORM_SOCKET_TRY_AGAIN) {
1982             fd_set myset;
1983             struct timeval tv;
1984             int valopt=0;
1985             socklen_t lon=0;
1986 
1987             if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__,__LINE__);
1988             if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__,__LINE__);
1989 
1990             do {
1991                tv.tv_sec = 10;
1992                tv.tv_usec = 0;
1993 
1994                FD_ZERO(&myset);
1995                FD_SET(sock, &myset);
1996 
1997                {
1998             	   MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
1999             	   err = select((int)sock + 1, NULL, &myset, NULL, &tv);
2000 				   lastSocketError = getLastSocketError();
2001             	   //safeMutex.ReleaseLock();
2002                }
2003 
2004                if (err < 0 && lastSocketError != PLATFORM_SOCKET_INTERRUPTED) {
2005             	   if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error connecting %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str());
2006             	   if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error connecting %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str());
2007 
2008                   break;
2009                }
2010                else if(err > 0) {
2011                //else if(FD_ISSET(sock, &myset)) {
2012                   // Socket selected for write
2013                   lon = sizeof(valopt);
2014 #ifndef WIN32
2015                   if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
2016 #else
2017                   if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0)
2018 #endif
2019                   {
2020                 	  if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str());
2021                 	  if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error in getsockopt() %s\n",__FILE__,__FUNCTION__,__LINE__,getLastSocketErrorFormattedText().c_str());
2022                      break;
2023                   }
2024                   // Check the value returned...
2025                   if(valopt) {
2026                 	  if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,__LINE__,valopt, strerror(valopt));
2027                 	  if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,__LINE__,valopt, strerror(valopt));
2028                      break;
2029                   }
2030 
2031                   errno = 0;
2032                   if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Apparent recovery for connection sock = %d, err = %d\n",__FILE__,__FUNCTION__,__LINE__,sock,err);
2033                   if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Apparent recovery for connection sock = " PLATFORM_SOCKET_FORMAT_TYPE ", err = %d\n",__FILE__,__FUNCTION__,__LINE__,sock,err);
2034 
2035                   break;
2036                }
2037                else {
2038             	   if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__,__LINE__);
2039             	   if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__,__LINE__);
2040 
2041                   disconnectSocket();
2042                   break;
2043                }
2044             } while (1);
2045         }
2046 
2047         if(err < 0) {
2048         	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Before END sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str());
2049         	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Before END sock = " PLATFORM_SOCKET_FORMAT_TYPE ", err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str());
2050             disconnectSocket();
2051         }
2052         else {
2053         	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Valid recovery for connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str());
2054         	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Valid recovery for connection sock = " PLATFORM_SOCKET_FORMAT_TYPE ", err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,err,getLastSocketErrorFormattedText().c_str());
2055         	connectedIpAddress = ip.getString();
2056         }
2057 	}
2058 	else {
2059 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Connected to host [%s] on port = %d sock = %d err = %d", ip.getString().c_str(),port,sock,err);
2060 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Connected to host [%s] on port = %d sock = " PLATFORM_SOCKET_FORMAT_TYPE " err = %d", ip.getString().c_str(),port,sock,err);
2061 		connectedIpAddress = ip.getString();
2062 	}
2063 }
2064 
2065 //=======================================================================
2066 // Function :		discovery response thread
2067 // Description:		Runs in its own thread to listen for broadcasts from
2068 //					other servers
2069 //
BroadCastClientSocketThread(DiscoveredServersInterface * cb)2070 BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterface *cb) : BaseThread() {
2071 
2072 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2073 
2074 	discoveredServersCB = cb;
2075 	uniqueID = "BroadCastClientSocketThread";
2076 
2077 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2078 }
2079 
2080 //=======================================================================
2081 // Function :		broadcast thread
2082 // Description:		Runs in its own thread to send out a broadcast to the local network
2083 //					the current broadcast message is <myhostname:my.ip.address.dotted>
2084 //
execute()2085 void BroadCastClientSocketThread::execute() {
2086 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2087 	RunningStatusSafeWrapper runningStatus(this);
2088 
2089 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n");
2090 
2091 	std::vector<string> foundServers;
2092 
2093 	short port;                 // The port for the broadcast.
2094     struct sockaddr_in bcSender; // local socket address for the broadcast.
2095     struct sockaddr_in bcaddr;  // The broadcast address for the receiver.
2096     PLATFORM_SOCKET bcfd;                // The file descriptor used for the broadcast.
2097     //bool one = true;            // Parameter for "setscokopt".
2098     socklen_t alen=0;
2099 
2100     port = htons( Socket::getBroadCastPort() );
2101 
2102     // Prepare to receive the broadcast.
2103     bcfd = socket(AF_INET, SOCK_DGRAM, 0);
2104     if( bcfd <= 0 )	{
2105     	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"socket failed: %s\n", Socket::getLastSocketErrorFormattedText().c_str());
2106 	}
2107     else {
2108 		// Create the address we are receiving on.
2109 		memset( (char*)&bcaddr, 0, sizeof(bcaddr));
2110 		bcaddr.sin_family = AF_INET;
2111 		bcaddr.sin_addr.s_addr = htonl(INADDR_ANY);
2112 		bcaddr.sin_port = port;
2113 
2114 		int val = 1;
2115 #ifndef WIN32
2116 		int opt_result = setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
2117 #else
2118 		int opt_result = setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
2119 #endif
2120 		if(::bind( bcfd,  (struct sockaddr *)&bcaddr, sizeof(bcaddr) ) < 0 )	{
2121 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"bind failed: %s opt_result = %d\n", Socket::getLastSocketErrorFormattedText().c_str(),opt_result);
2122 		}
2123 		else {
2124 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] opt_result = %d\n",__FILE__,__FUNCTION__,__LINE__,opt_result);
2125 
2126 			Socket::setBlock(false, bcfd);
2127 
2128 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2129 
2130 			try	{
2131 				char buff[10024]="";  // Buffers the data to be broadcasted.
2132 				// Keep getting packets forever.
2133 				for( time_t elapsed = time(NULL); difftime((long int)time(NULL),elapsed) <= 5; ) {
2134 					alen = sizeof(struct sockaddr);
2135 					int nb=0;// The number of bytes read.
2136 					bool gotData = (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) > 0;
2137 
2138 					//printf("Broadcasting client nb = %d buff [%s] gotData = %d\n",nb,buff,gotData);
2139 
2140 					if(gotData == false) {
2141 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %s\n", Socket::getLastSocketErrorFormattedText().c_str());
2142 					}
2143 					else {
2144 						//string fromIP = inet_ntoa(bcSender.sin_addr);
2145 						char szHostFrom[100]="";
2146 						Ip::Inet_NtoA(SockAddrToUint32(&bcSender.sin_addr), szHostFrom);
2147 						//printf("Client szHostFrom [%s]\n",szHostFrom);
2148 
2149 						string fromIP = szHostFrom;
2150 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,fromIP.c_str() );
2151 
2152 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Client got broadcast from server: [%s] data [%s]\n",fromIP.c_str(),buff);
2153 
2154 						int serverGamePort = Socket::getBroadCastPort();
2155 						vector<string> paramPartPortsTokens;
2156 						Tokenize(buff,paramPartPortsTokens,":");
2157 						if(paramPartPortsTokens.size() >= 3 && paramPartPortsTokens[2].length() > 0) {
2158 							serverGamePort = strToInt(paramPartPortsTokens[2]);
2159 						}
2160 
2161 						if(std::find(foundServers.begin(),foundServers.end(),fromIP) == foundServers.end()) {
2162 							foundServers.push_back(fromIP + ":" + intToStr(serverGamePort));
2163 						}
2164 
2165 						// For now break as soon as we find a server
2166 						break;
2167 					}
2168 
2169 					if(getQuitStatus() == true) {
2170 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2171 						break;
2172 					}
2173 					sleep( 100 ); // send out broadcast every 1 seconds
2174 					if(getQuitStatus() == true) {
2175 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2176 						break;
2177 					}
2178 				}
2179 			}
2180 			catch(const exception &ex) {
2181 				SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
2182 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
2183 			}
2184 			catch(...) {
2185 				SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
2186 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
2187 			}
2188 		}
2189     }
2190 
2191 #ifndef WIN32
2192     if(bcfd >= 0) ::close(bcfd);
2193     bcfd = -1;
2194 #else
2195     if(bcfd != INVALID_SOCKET) ::closesocket(bcfd);
2196     bcfd = INVALID_SOCKET;
2197 #endif
2198 
2199     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2200 
2201     // Here we callback into the implementer class
2202     if(getQuitStatus() == false && discoveredServersCB != NULL) {
2203     	discoveredServersCB->DiscoveredServers(foundServers);
2204     }
2205 
2206     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n");
2207     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2208 }
2209 
2210 // ===============================================
2211 //	class ServerSocket
2212 // ===============================================
2213 
ServerSocket(bool basicMode)2214 ServerSocket::ServerSocket(bool basicMode) : Socket() {
2215 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] basicMode = %d\n",__FILE__,__FUNCTION__,__LINE__,basicMode);
2216 
2217 	this->basicMode = basicMode;
2218 	this->bindSpecificAddress = "";
2219 	//printf("SERVER SOCKET CONSTRUCTOR\n");
2220 
2221 	boundPort = 0;
2222 	portBound = false;
2223 	broadCastThread = NULL;
2224 	if(this->basicMode == false) {
2225 		UPNP_Tools::enabledUPNP = false;
2226 	}
2227 
2228 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2229 }
2230 
~ServerSocket()2231 ServerSocket::~ServerSocket() {
2232 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2233 
2234 	//printf("In [%s::%s] Line: %d UPNP_Tools::enabledUPNP = %d\n",__FILE__,__FUNCTION__,__LINE__,UPNP_Tools::enabledUPNP);
2235 
2236 	stopBroadCastThread();
2237 
2238 	if(this->basicMode == false) {
2239 		MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
2240 		if(ServerSocket::upnpdiscoverThread != NULL) {
2241 
2242 			ServerSocket::cancelUpnpdiscoverThread = true;
2243 			SDL_WaitThread(ServerSocket::upnpdiscoverThread, NULL);
2244 			ServerSocket::upnpdiscoverThread = NULL;
2245 			ServerSocket::cancelUpnpdiscoverThread = false;
2246 		}
2247 		safeMutexUPNP.ReleaseLock();
2248 		if (UPNP_Tools::enabledUPNP) {
2249 			UPNP_Tools::NETremRedirects(this->getExternalPort());
2250 		}
2251 
2252 		MutexSafeWrapper safeMutexUPNP1(&UPNP_Tools::mutexUPNP,CODE_AT_LINE);
2253 		if(urls.controlURL && urls.ipcondescURL && urls.controlURL_CIF) {
2254 			FreeUPNPUrls(&urls);
2255 		}
2256 
2257 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2258 		safeMutexUPNP1.ReleaseLock();
2259 	}
2260 }
2261 
stopBroadCastThread()2262 void ServerSocket::stopBroadCastThread() {
2263 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2264 
2265 	//printf("Stopping broadcast thread [%p]\n",broadCastThread);
2266 
2267 	if(broadCastThread != NULL) {
2268 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2269 
2270 		//printf("Stopping broadcast thread [%p] - A\n",broadCastThread);
2271 
2272 		if(broadCastThread->canShutdown(false) == true) {
2273 			sleep(0);
2274 		}
2275 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2276 		//printf("Stopping broadcast thread [%p] - B\n",broadCastThread);
2277 
2278 		if(broadCastThread->shutdownAndWait() == true) {
2279 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2280 			delete broadCastThread;
2281 
2282 			//printf("Stopping broadcast thread [%p] - C\n",broadCastThread);
2283 		}
2284 		broadCastThread = NULL;
2285 		//printf("Stopping broadcast thread [%p] - D\n",broadCastThread);
2286 
2287 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2288 	}
2289 
2290 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2291 }
2292 
startBroadCastThread()2293 void ServerSocket::startBroadCastThread() {
2294 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2295 
2296 	stopBroadCastThread();
2297 
2298 	broadCastThread = new BroadCastSocketThread(this->boundPort);
2299 
2300 	//printf("Start broadcast thread [%p]\n",broadCastThread);
2301 
2302 	static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
2303 	broadCastThread->setUniqueID(mutexOwnerId);
2304 	broadCastThread->start();
2305 
2306 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2307 }
2308 
resumeBroadcast()2309 void ServerSocket::resumeBroadcast() {
2310 	if(broadCastThread != NULL) {
2311 		broadCastThread->setPauseBroadcast(false);
2312 	}
2313 }
pauseBroadcast()2314 void ServerSocket::pauseBroadcast() {
2315 	if(broadCastThread != NULL) {
2316 		broadCastThread->setPauseBroadcast(true);
2317 	}
2318 }
2319 
isBroadCastThreadRunning()2320 bool ServerSocket::isBroadCastThreadRunning() {
2321 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2322 
2323 	bool isThreadRunning = (broadCastThread != NULL && broadCastThread->getRunningStatus() == true);
2324 
2325 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] isThreadRunning = %d\n",__FILE__,__FUNCTION__,__LINE__,isThreadRunning);
2326 
2327 	return isThreadRunning;
2328 }
2329 
bind(int port)2330 void ServerSocket::bind(int port) {
2331 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d port = %d, portBound = %d START\n",__FILE__,__FUNCTION__,__LINE__,port,portBound);
2332 
2333 	boundPort = port;
2334 
2335 	if(isSocketValid() == false) {
2336 		sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2337 		if(isSocketValid() == false) {
2338 			throwException("Error creating socket");
2339 		}
2340 		setBlock(false);
2341 	}
2342 
2343 	//sockaddr structure
2344 	sockaddr_in addr;
2345 	addr.sin_family= AF_INET;
2346 	if(this->bindSpecificAddress != "") {
2347 		addr.sin_addr.s_addr= inet_addr(this->bindSpecificAddress.c_str());
2348 	}
2349 	else {
2350 		addr.sin_addr.s_addr= INADDR_ANY;
2351 	}
2352 	addr.sin_port= htons(port);
2353 	addr.sin_zero[0] = 0;
2354 
2355 	int val = 1;
2356 
2357 #ifndef WIN32
2358 	int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
2359 #else
2360 	int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
2361 #endif
2362 
2363 	int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
2364 	if(err < 0) {
2365 	    char szBuf[8096]="";
2366 	    snprintf(szBuf, 8096,"In [%s::%s] Error binding socket sock = " PLATFORM_SOCKET_FORMAT_TYPE ", address [%s] port = %d err = %d, error = %s opt_result = %d\n",__FILE__,__FUNCTION__,sock,this->bindSpecificAddress.c_str(),port,err,getLastSocketErrorFormattedText().c_str(),opt_result);
2367 	    if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"%s",szBuf);
2368 
2369 	    snprintf(szBuf, 8096,"Error binding socket sock = " PLATFORM_SOCKET_FORMAT_TYPE ", address [%s] port = %d err = %d, error = %s\n",sock,this->bindSpecificAddress.c_str(),port,err,getLastSocketErrorFormattedText().c_str());
2370 	    throw megaglest_runtime_error(szBuf);
2371 	}
2372 	portBound = true;
2373 
2374 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d port = %d, portBound = %d END\n",__FILE__,__FUNCTION__,__LINE__,port,portBound);
2375 }
2376 
disconnectSocket()2377 void ServerSocket::disconnectSocket() {
2378 	Socket::disconnectSocket();
2379 	portBound = false;
2380 }
2381 
listen(int connectionQueueSize)2382 void ServerSocket::listen(int connectionQueueSize) {
2383 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d connectionQueueSize = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionQueueSize);
2384 
2385 	if(connectionQueueSize > 0) {
2386 		if(isSocketValid() == false) {
2387 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2388 
2389 			sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2390 			if(isSocketValid() == false) {
2391 				throwException("Error creating socket");
2392 			}
2393 			setBlock(false);
2394 		}
2395 
2396 		if(portBound == false) {
2397 			bind(boundPort);
2398 		}
2399 
2400 		int err= ::listen(sock, connectionQueueSize);
2401 		if(err < 0) {
2402 			char szBuf[8096]="";
2403 			snprintf(szBuf, 8096,"In [%s::%s] Error listening socket sock = " PLATFORM_SOCKET_FORMAT_TYPE ", err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str());
2404 			throwException(szBuf);
2405 		}
2406 	}
2407 	else {
2408 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2409 		disconnectSocket();
2410 	}
2411 
2412 	if(this->basicMode == false) {
2413 		if(connectionQueueSize > 0) {
2414 			if(isBroadCastThreadRunning() == false) {
2415 				startBroadCastThread();
2416 			}
2417 			else {
2418 				resumeBroadcast();
2419 			}
2420 		}
2421 		else {
2422 			pauseBroadcast();
2423 		}
2424 	}
2425 }
2426 
accept(bool errorOnFail)2427 Socket *ServerSocket::accept(bool errorOnFail) {
2428 	if(isSocketValid() == false) {
2429 		if(errorOnFail == true) {
2430 			throwException("socket is invalid!");
2431 		}
2432 		else {
2433 			return NULL;
2434 		}
2435 	}
2436 
2437 	PLATFORM_SOCKET newSock=0;
2438 	char client_host[100]="";
2439 	//const int max_attempts = 100;
2440 	//for(int attempt = 0; attempt < max_attempts; ++attempt) {
2441 		struct sockaddr_in cli_addr;
2442 		socklen_t clilen = sizeof(cli_addr);
2443 		client_host[0]='\0';
2444 		MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE);
2445 		newSock= ::accept(sock, (struct sockaddr *) &cli_addr, &clilen);
2446 		safeMutex.ReleaseLock();
2447 
2448 		if(isSocketValid(&newSock) == false) {
2449 			char szBuf[8096]="";
2450 			snprintf(szBuf, 8096,"In [%s::%s Line: %d] Error accepting socket connection sock = " PLATFORM_SOCKET_FORMAT_TYPE ", err = " PLATFORM_SOCKET_FORMAT_TYPE ", error = %s\n",__FILE__,__FUNCTION__,__LINE__,sock,newSock,getLastSocketErrorFormattedText().c_str());
2451 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
2452 
2453 			int lastSocketError = getLastSocketError();
2454 			if(lastSocketError == PLATFORM_SOCKET_TRY_AGAIN) {
2455 				//if(attempt+1 >= max_attempts) {
2456 				//	return NULL;
2457 				//}
2458 				//else {
2459 					sleep(0);
2460 				//}
2461 			}
2462 			if(errorOnFail == true) {
2463 				throwException(szBuf);
2464 			}
2465 			else {
2466 	#ifndef WIN32
2467 			::close(newSock);
2468 			newSock = -1;
2469 	#else
2470 			::closesocket(newSock);
2471 			newSock = INVALID_SOCKET;
2472 	#endif
2473 
2474 				return NULL;
2475 			}
2476 
2477 		}
2478 		else {
2479 			Ip::Inet_NtoA(SockAddrToUint32((struct sockaddr *)&cli_addr), client_host);
2480 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got connection, newSock = %d client_host [%s]\n",__FILE__,__FUNCTION__,__LINE__,newSock,client_host);
2481 		}
2482 		if(isIPAddressBlocked((client_host[0] != '\0' ? client_host : "")) == true) {
2483 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] BLOCKING connection, newSock = %d client_host [%s]\n",__FILE__,__FUNCTION__,__LINE__,newSock,client_host);
2484 
2485 	#ifndef WIN32
2486 			::close(newSock);
2487 			newSock = -1;
2488 	#else
2489 			::closesocket(newSock);
2490 			newSock = INVALID_SOCKET;
2491 	#endif
2492 
2493 			return NULL;
2494 		}
2495 
2496 		//break;
2497 	//}
2498 	Socket *result = new Socket(newSock);
2499 	result->setIpAddress((client_host[0] != '\0' ? client_host : ""));
2500 	return result;
2501 }
2502 
NETdiscoverUPnPDevices()2503 void ServerSocket::NETdiscoverUPnPDevices() {
2504 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] UPNP - Start\n",__FILE__,__FUNCTION__,__LINE__);
2505 
2506 	MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
2507 	if(ServerSocket::upnpdiscoverThread != NULL) {
2508 		ServerSocket::cancelUpnpdiscoverThread = true;
2509 		SDL_WaitThread(ServerSocket::upnpdiscoverThread, NULL);
2510 		ServerSocket::upnpdiscoverThread = NULL;
2511 		ServerSocket::cancelUpnpdiscoverThread = false;
2512 	}
2513 
2514     // WATCH OUT! Because the thread takes void * as a parameter we MUST cast to the pointer type
2515     // used on the other side (inside the thread)
2516 	//printf("STARTING UPNP Thread\n");
2517 	ServerSocket::upnpdiscoverThread = SDL_CreateThread(&UPNP_Tools::upnp_init, "upnpdiscoverThread", dynamic_cast<UPNPInitInterface *>(this));
2518 	safeMutexUPNP.ReleaseLock();
2519 	//printf("In [%s::%s] Line: %d safeMutexUPNP\n",__FILE__,__FUNCTION__,__LINE__);
2520 
2521 	//printf("SERVER SOCKET NETdiscoverUPnPDevices - END\n");
2522 }
2523 
UPNPInitStatus(bool result)2524 void ServerSocket::UPNPInitStatus(bool result) {
2525 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result);
2526 
2527     if(result == true) {
2528         //int ports[4] = { this->getExternalPort(), this->getBindPort(), this->getFTPServerPort(), this->getFTPServerPort() };
2529         std::vector<int> UPNPPortForwardList;
2530 
2531         // Glest Game Server port
2532         UPNPPortForwardList.push_back(this->getExternalPort());
2533         UPNPPortForwardList.push_back(this->getBindPort());
2534 
2535         // Glest mini FTP Server Listen Port
2536         UPNPPortForwardList.push_back(this->getFTPServerPort());
2537         UPNPPortForwardList.push_back(this->getFTPServerPort());
2538 
2539         // GLest mini FTP Server Passive file TRansfer ports (1 per game player)
2540         for(int clientIndex = 1; clientIndex <= ServerSocket::maxPlayerCount; ++clientIndex) {
2541             UPNPPortForwardList.push_back(this->getFTPServerPort() + clientIndex);
2542             UPNPPortForwardList.push_back(this->getFTPServerPort() + clientIndex);
2543         }
2544 
2545         UPNP_Tools::NETaddRedirects(UPNPPortForwardList,false);
2546     }
2547 }
2548 
2549 //
2550 // UPNP Tools Start
2551 //
AddUPNPPortForward(int internalPort,int externalPort)2552 void UPNP_Tools::AddUPNPPortForward(int internalPort, int externalPort) {
2553 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] internalPort = %d, externalPort = %d\n",__FILE__,__FUNCTION__,__LINE__,internalPort,externalPort);
2554 
2555     bool addPorts = (UPNP_Tools::enabledUPNP == true);
2556     if(addPorts == false) {
2557         int result = UPNP_Tools::upnp_init(NULL);
2558         addPorts = (result != 0);
2559     }
2560 
2561     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] internalPort = %d, externalPort = %d, addPorts = %d\n",__FILE__,__FUNCTION__,__LINE__,internalPort,externalPort,addPorts);
2562 
2563     if(addPorts == true) {
2564         int ports[2] = { externalPort, internalPort };
2565         UPNP_Tools::upnp_add_redirect(ports);
2566     }
2567 }
2568 
RemoveUPNPPortForward(int internalPort,int externalPort)2569 void UPNP_Tools::RemoveUPNPPortForward(int internalPort, int externalPort) {
2570     UPNP_Tools::upnp_rem_redirect(externalPort);
2571 }
2572 
2573 //
2574 // This code below handles Universal Plug and Play Router Discovery
2575 //
upnp_init(void * param)2576 int UPNP_Tools::upnp_init(void *param) {
2577 	int result				= -1;
2578 	struct UPNPDev *devlist = NULL;
2579 	struct UPNPDev *dev     = NULL;
2580 	int descXMLsize         = 0;
2581 	char buf[255]           = "";
2582 	// Callers MUST pass in NULL or a UPNPInitInterface *
2583 	UPNPInitInterface *callback = (UPNPInitInterface *)(param);
2584 
2585 	MutexSafeWrapper safeMutexUPNP(&UPNP_Tools::mutexUPNP,CODE_AT_LINE);
2586 	memset(&urls, 0, sizeof(struct UPNPUrls));
2587 	memset(&data, 0, sizeof(struct IGDdatas));
2588 
2589 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] isUPNP = %d callback = %p\n",__FILE__,__FUNCTION__,__LINE__,UPNP_Tools::isUPNP,callback);
2590 
2591 	if(UPNP_Tools::isUPNP == true) {
2592 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Searching for UPnP devices for automatic port forwarding...\n");
2593 
2594 		int upnp_delay = 5000;
2595 		const char *upnp_multicastif = NULL;
2596 		const char *upnp_minissdpdsock = NULL;
2597 		int upnp_sameport = 0;
2598 		int upnp_ipv6 = 0;
2599 		int upnp_error = 0;
2600 
2601 #ifndef MINIUPNPC_VERSION_PRE1_6
2602 	#if !defined(MINIUPNPC_API_VERSION) || MINIUPNPC_API_VERSION < 14
2603 		devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport, upnp_ipv6, &upnp_error);
2604 	#else
2605 		// miniupnpc 1.9.20150730
2606 		devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport, upnp_ipv6, 2, &upnp_error);
2607 	#endif
2608 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP discover returned upnp_error = %d.\n",upnp_error);
2609 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP discover returned upnp_error = %d.\n",upnp_error);
2610 
2611 #else
2612 		devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport);
2613 #endif
2614 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP device search finished devlist = %p.\n",devlist);
2615 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP device search finished devlist = %p.\n",devlist);
2616 
2617 		if(ServerSocket::cancelUpnpdiscoverThread == true) {
2618 			if(devlist != NULL) {
2619 				freeUPNPDevlist(devlist);
2620 			}
2621 			devlist = NULL;
2622 			return result;
2623 		}
2624 
2625 		if (devlist) {
2626 			dev = devlist;
2627 			while (dev) {
2628 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP discover deviceList [%s].\n",(dev->st ? dev->st : "null"));
2629 				if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP discover deviceList [%s].\n",(dev->st ? dev->st : "null"));
2630 
2631 				dev = dev->pNext;
2632 			}
2633 
2634 			dev = devlist;
2635 			while (dev && dev->st) {
2636 				if (strstr(dev->st, "InternetGatewayDevice")) {
2637 					break;
2638 				}
2639 				dev = dev->pNext;
2640 			}
2641 			if (!dev) {
2642 				dev = devlist; /* defaulting to first device */
2643 			}
2644 
2645 			if(dev != NULL) {
2646 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP device found: %s %s\n", dev->descURL, dev->st);
2647 				if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP device found: %s %s\n", dev->descURL, dev->st);
2648 
2649 				//printf("UPnP device found: [%s] [%s] lanaddr [%s]\n", dev->descURL, dev->st,lanaddr);
2650 #if (defined(MINIUPNPC_API_VERSION)  && MINIUPNPC_API_VERSION >= 16)
2651 				char *descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, (sizeof(lanaddr) / sizeof(lanaddr[0])), 0, NULL);
2652 #elif (defined(MINIUPNPC_API_VERSION)  && MINIUPNPC_API_VERSION >= 9) || (!defined(MINIUPNPC_VERSION_PRE1_7) && !defined(MINIUPNPC_VERSION_PRE1_6))
2653                 char *descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, (sizeof(lanaddr) / sizeof(lanaddr[0])), 0);
2654 #else
2655 				char *descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, (sizeof(lanaddr) / sizeof(lanaddr[0])));
2656 #endif
2657 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"LAN address: %s\n", lanaddr);
2658 
2659 				if (descXML) {
2660 					parserootdesc (descXML, descXMLsize, &data);
2661 					free (descXML); descXML = 0;
2662 
2663 #if (defined(MINIUPNPC_API_VERSION)  && MINIUPNPC_API_VERSION >= 9) || (!defined(MINIUPNPC_VERSION_PRE1_7) && !defined(MINIUPNPC_VERSION_PRE1_6))
2664 					GetUPNPUrls (&urls, &data, dev->descURL,0);
2665 #else
2666 					GetUPNPUrls (&urls, &data, dev->descURL);
2667 #endif
2668 				}
2669 				snprintf(buf, 255,"UPnP device found: %s %s LAN address %s", dev->descURL, dev->st, lanaddr);
2670 
2671 				freeUPNPDevlist(devlist);
2672 				devlist = NULL;
2673 			}
2674 
2675 			if(ServerSocket::cancelUpnpdiscoverThread == true) {
2676 				//if(devlist != NULL) {
2677 				//	freeUPNPDevlist(devlist);
2678 				//}
2679 				//devlist = NULL;
2680 				return result;
2681 			}
2682 
2683 			if (!urls.controlURL || urls.controlURL[0] == '\0')	{
2684 				snprintf(buf, 255,"controlURL not available, UPnP disabled");
2685 				if(callback) {
2686 					safeMutexUPNP.ReleaseLock();
2687 				    callback->UPNPInitStatus(false);
2688 				}
2689 				result = 0;
2690 			}
2691 			else {
2692 				char externalIP[16]     = "";
2693 #ifndef MINIUPNPC_VERSION_PRE1_5
2694 				UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP);
2695 #else
2696 				UPNP_GetExternalIPAddress(urls.controlURL, data.servicetype, externalIP);
2697 #endif
2698 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP device found at: [%s] callback [%p]\n",externalIP,callback);
2699 
2700 				//UPNP_Tools::NETaddRedirects(ports);
2701 				UPNP_Tools::enabledUPNP = true;
2702 				if(callback) {
2703 					safeMutexUPNP.ReleaseLock();
2704 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2705 					callback->UPNPInitStatus(true);
2706 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2707 				}
2708 				result = 1;
2709 			}
2710 		}
2711 
2712 		if(result == -1) {
2713 			snprintf(buf, 255,"UPnP device not found.");
2714 
2715 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"No UPnP devices found.\n");
2716 
2717 			if(ServerSocket::cancelUpnpdiscoverThread == true) {
2718 				//if(devlist != NULL) {
2719 				//	freeUPNPDevlist(devlist);
2720 				//}
2721 				//devlist = NULL;
2722 				return result;
2723 			}
2724 
2725 			if(callback) {
2726 				safeMutexUPNP.ReleaseLock();
2727 				callback->UPNPInitStatus(false);
2728 			}
2729 			result = 0;
2730 		}
2731 	}
2732 	else {
2733 		snprintf(buf, 255,"UPnP detection routine disabled by user.");
2734 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP detection routine disabled by user.\n");
2735 
2736 		if(ServerSocket::cancelUpnpdiscoverThread == true) {
2737 			//if(devlist != NULL) {
2738 			//	freeUPNPDevlist(devlist);
2739 			//}
2740 			//devlist = NULL;
2741 			return result;
2742 		}
2743 
2744         if(callback) {
2745         	safeMutexUPNP.ReleaseLock();
2746             callback->UPNPInitStatus(false);
2747         }
2748         result = 0;
2749 	}
2750 
2751 	//printf("ENDING UPNP Thread\n");
2752 
2753 	return result;
2754 }
2755 
upnp_add_redirect(int ports[2],bool mutexLock)2756 bool UPNP_Tools::upnp_add_redirect(int ports[2],bool mutexLock) {
2757 	bool result				= true;
2758 
2759 	//printf("SERVER SOCKET upnp_add_redirect - START\n");
2760 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] upnp_add_redir(%d : %d)\n",__FILE__,__FUNCTION__,__LINE__,ports[0],ports[1]);
2761 
2762 	if(mutexLock) {
2763 		MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
2764 		if(ServerSocket::upnpdiscoverThread != NULL) {
2765 			ServerSocket::cancelUpnpdiscoverThread = true;
2766 			SDL_WaitThread(ServerSocket::upnpdiscoverThread, NULL);
2767 			ServerSocket::upnpdiscoverThread = NULL;
2768 			ServerSocket::cancelUpnpdiscoverThread = false;
2769 		}
2770 		safeMutexUPNP.ReleaseLock();
2771 	}
2772 
2773 	MutexSafeWrapper safeMutexUPNP(&UPNP_Tools::mutexUPNP,CODE_AT_LINE);
2774 	if (!urls.controlURL || urls.controlURL[0] == '\0')	{
2775 		result = false;
2776 	}
2777 	else {
2778 		char externalIP[16] = "";
2779 #ifndef MINIUPNPC_VERSION_PRE1_5
2780 		UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP);
2781 #else
2782 		UPNP_GetExternalIPAddress(urls.controlURL, data.servicetype, externalIP);
2783 #endif
2784 
2785 		char ext_port_str[16]   = "";
2786 		char int_port_str[16]   = "";
2787 		sprintf(ext_port_str, "%d", ports[0]);
2788 		sprintf(int_port_str, "%d", ports[1]);
2789 
2790 		//int r                   = 0;
2791 #ifndef MINIUPNPC_VERSION_PRE1_5
2792 	#ifndef MINIUPNPC_VERSION_PRE1_6
2793 		int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0, NULL);
2794 	#else
2795 		int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0);
2796 	#endif
2797 #else
2798 		int r = UPNP_AddPortMapping(urls.controlURL, data.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0);
2799 #endif
2800 		if (r != UPNPCOMMAND_SUCCESS) {
2801 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] AddPortMapping(%s, %s, %s) failed\n",__FILE__,__FUNCTION__,__LINE__,ext_port_str, int_port_str, lanaddr);
2802 			result = false;
2803 		}
2804 
2805 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] AddPortMapping(%s, %s, %s) success\n",__FILE__,__FUNCTION__,__LINE__,ext_port_str, int_port_str, lanaddr);
2806 	}
2807 
2808 	//printf("SERVER SOCKET upnp_add_redirect - END [%d]\n",result);
2809 	return result;
2810 }
2811 
upnp_rem_redirect(int ext_port)2812 void UPNP_Tools::upnp_rem_redirect(int ext_port) {
2813 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] upnp_rem_redir(%d)\n",__FILE__,__FUNCTION__,__LINE__,ext_port);
2814 
2815 	MutexSafeWrapper safeMutexUPNP(&ServerSocket::mutexUpnpdiscoverThread,CODE_AT_LINE);
2816     if(ServerSocket::upnpdiscoverThread != NULL) {
2817     	ServerSocket::cancelUpnpdiscoverThread = true;
2818         SDL_WaitThread(ServerSocket::upnpdiscoverThread, NULL);
2819         ServerSocket::upnpdiscoverThread = NULL;
2820         ServerSocket::cancelUpnpdiscoverThread = false;
2821     }
2822     safeMutexUPNP.ReleaseLock();
2823 
2824     MutexSafeWrapper safeMutexUPNP1(&UPNP_Tools::mutexUPNP,CODE_AT_LINE);
2825 	if (urls.controlURL && urls.controlURL[0] != '\0')	{
2826 		char ext_port_str[16]="";
2827 		sprintf(ext_port_str, "%d", ext_port);
2828 
2829 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n#1 DEBUGGING urls.controlURL [%s]\n",urls.controlURL);
2830 
2831 		int result = 0;
2832 	#ifndef MINIUPNPC_VERSION_PRE1_5
2833 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n#1 DEBUGGING data.first.servicetype [%s]\n",data.first.servicetype);
2834 		result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, ext_port_str, "TCP", 0);
2835 	#else
2836 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n#1 DEBUGGING data.servicetype [%s]\n",data.servicetype);
2837 		result = UPNP_DeletePortMapping(urls.controlURL, data.servicetype, ext_port_str, "TCP", 0);
2838 	#endif
2839 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\nresult = %d\n",result);
2840 		//printf("\n\nresult = %d\n",result);
2841 	}
2842 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n#2 DEBUGGING urls.controlURL [%s]\n",urls.controlURL);
2843 
2844 	//printf("SERVER SOCKET upnp_rem_redirect - END\n");
2845 }
2846 
NETaddRedirects(std::vector<int> UPNPPortForwardList,bool mutexLock)2847 void UPNP_Tools::NETaddRedirects(std::vector<int> UPNPPortForwardList,bool mutexLock) {
2848 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] upnp_rem_redir(%d)\n",__FILE__,__FUNCTION__,__LINE__);
2849 
2850     if(UPNPPortForwardList.size() % 2 != 0) {
2851         // We need groups of 2 ports.. one external and one internal for opening ports on UPNP router
2852         throw megaglest_runtime_error("UPNPPortForwardList.size() MUST BE divisable by 2");
2853     }
2854 
2855     for(unsigned int clientIndex = 0; clientIndex < UPNPPortForwardList.size(); clientIndex += 2) {
2856         int ports[2] = { UPNPPortForwardList[clientIndex], UPNPPortForwardList[clientIndex+1] };
2857         upnp_add_redirect(ports,mutexLock);
2858     }
2859 }
2860 
NETremRedirects(int ext_port)2861 void UPNP_Tools::NETremRedirects(int ext_port) {
2862 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] upnp_rem_redir(%d)\n",__FILE__,__FUNCTION__,__LINE__);
2863     upnp_rem_redirect(ext_port);
2864 }
2865 //
2866 // UPNP Tools END
2867 //
2868 
2869 //=======================================================================
2870 // Function :		broadcast_thread
2871 // in		:		none
2872 // return	:		none
2873 // Description:		To be forked in its own thread to send out a broadcast to the local subnet
2874 //					the current broadcast message is <myhostname:my.ip.address.dotted>
2875 //
BroadCastSocketThread(int boundPort)2876 BroadCastSocketThread::BroadCastSocketThread(int boundPort) : BaseThread() {
2877 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2878 	mutexPauseBroadcast = new Mutex(CODE_AT_LINE);
2879 	setPauseBroadcast(false);
2880 	this->boundPort = boundPort;
2881 	uniqueID = "BroadCastSocketThread";
2882 	//printf("new broadcast thread [%p]\n",this);
2883 }
2884 
~BroadCastSocketThread()2885 BroadCastSocketThread::~BroadCastSocketThread() {
2886 	//printf("delete broadcast thread [%p]\n",this);
2887 
2888 	delete mutexPauseBroadcast;
2889 	mutexPauseBroadcast = NULL;
2890 }
2891 
getPauseBroadcast()2892 bool BroadCastSocketThread::getPauseBroadcast() {
2893 	MutexSafeWrapper safeMutexSocketDestructorFlag(mutexPauseBroadcast,CODE_AT_LINE);
2894 	mutexPauseBroadcast->setOwnerId(CODE_AT_LINE);
2895 	return pauseBroadcast;
2896 }
2897 
setPauseBroadcast(bool value)2898 void BroadCastSocketThread::setPauseBroadcast(bool value) {
2899 	MutexSafeWrapper safeMutexSocketDestructorFlag(mutexPauseBroadcast,CODE_AT_LINE);
2900 	mutexPauseBroadcast->setOwnerId(CODE_AT_LINE);
2901 	pauseBroadcast = value;
2902 }
2903 
2904 
canShutdown(bool deleteSelfIfShutdownDelayed)2905 bool BroadCastSocketThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
2906 	bool ret = (getExecutingTask() == false);
2907 	if(ret == false && deleteSelfIfShutdownDelayed == true) {
2908 	    setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
2909 	    deleteSelfIfRequired();
2910 	    signalQuit();
2911 	}
2912 
2913 	return ret;
2914 }
2915 
execute()2916 void BroadCastSocketThread::execute() {
2917 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2918 	//setRunningStatus(true);
2919 	RunningStatusSafeWrapper runningStatus(this);
2920 	ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
2921 
2922 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n");
2923 
2924 	const int MAX_NIC_COUNT = 10;
2925     short port=0;                 // The port for the broadcast.
2926     struct sockaddr_in bcLocal[MAX_NIC_COUNT]; // local socket address for the broadcast.
2927     PLATFORM_SOCKET bcfd[MAX_NIC_COUNT];                // The socket used for the broadcast.
2928     int one = 1;            // Parameter for "setscokopt".
2929     int pn=0;                     // The number of the packet broadcasted.
2930     const int buffMaxSize=1024;
2931     char buff[buffMaxSize]="";            // Buffers the data to be broadcasted.
2932     char myhostname[100]="";       // hostname of local machine
2933     //char subnetmask[MAX_NIC_COUNT][100];       // Subnet mask to broadcast to
2934     //struct hostent* myhostent=NULL;
2935 
2936     for(unsigned int idx = 0; idx < (unsigned int)MAX_NIC_COUNT; idx++) {
2937     	memset( &bcLocal[idx], 0, sizeof( struct sockaddr_in));
2938 
2939 #ifdef WIN32
2940 		bcfd[idx] = INVALID_SOCKET;
2941 #else
2942 		bcfd[idx] = -1;
2943 #endif
2944     }
2945     /* get my host name */
2946     gethostname(myhostname,100);
2947     //struct hostent*myhostent = gethostbyname(myhostname);
2948 
2949     // get all host IP addresses
2950     std::vector<std::string> ipList = Socket::getLocalIPAddressList();
2951 
2952     // Subnet, IP Address
2953     std::vector<std::string> ipSubnetMaskList;
2954 	for(unsigned int idx = 0; idx < (unsigned int)ipList.size() && idx < (unsigned int)MAX_NIC_COUNT; idx++) {
2955 		string broadCastAddress = getNetworkInterfaceBroadcastAddress(ipList[idx]);
2956 		//printf("idx = %d broadCastAddress [%s]\n",idx,broadCastAddress.c_str());
2957 
2958 		//strcpy(subnetmask[idx], broadCastAddress.c_str());
2959 		if(broadCastAddress != "" && std::find(ipSubnetMaskList.begin(),ipSubnetMaskList.end(),broadCastAddress) == ipSubnetMaskList.end()) {
2960 			ipSubnetMaskList.push_back(broadCastAddress);
2961 		}
2962 	}
2963 
2964 	port = htons( Socket::getBroadCastPort() );
2965 
2966 	//for(unsigned int idx = 0; idx < ipList.size() && idx < MAX_NIC_COUNT; idx++) {
2967 	for(unsigned int idx = 0; idx < (unsigned int)ipSubnetMaskList.size(); idx++) {
2968 		// Create the broadcast socket
2969 		memset( &bcLocal[idx], 0, sizeof( struct sockaddr_in));
2970 		bcLocal[idx].sin_family			= AF_INET;
2971 		bcLocal[idx].sin_addr.s_addr	= inet_addr(ipSubnetMaskList[idx].c_str()); //htonl( INADDR_BROADCAST );
2972 		bcLocal[idx].sin_port			= port;  // We are letting the OS fill in the port number for the local machine.
2973 #ifdef WIN32
2974 		bcfd[idx] = INVALID_SOCKET;
2975 #else
2976 		bcfd[idx] = -1;
2977 #endif
2978 		//if(strlen(subnetmask[idx]) > 0) {
2979 		bcfd[idx] = socket( AF_INET, SOCK_DGRAM, 0 );
2980 
2981 		if( bcfd[idx] <= 0  ) {
2982 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Unable to allocate broadcast socket [%s]: %s\n", ipSubnetMaskList[idx].c_str(), Socket::getLastSocketErrorFormattedText().c_str());
2983 			//exit(-1);
2984 		}
2985 		// Mark the socket for broadcast.
2986 		else if( setsockopt( bcfd[idx], SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof( int ) ) < 0 ) {
2987 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not set socket to broadcast [%s]: %s\n", ipSubnetMaskList[idx].c_str(), Socket::getLastSocketErrorFormattedText().c_str());
2988 			//exit(-1);
2989 		}
2990 		//}
2991 
2992 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] setting up broadcast on address [%s]\n",__FILE__,__FUNCTION__,__LINE__,ipSubnetMaskList[idx].c_str());
2993 	}
2994 
2995 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
2996 
2997 	time_t elapsed = 0;
2998 	for( pn = 1; getQuitStatus() == false; pn++ ) {
2999 		for(unsigned int idx = 0; getQuitStatus() == false && idx < ipSubnetMaskList.size(); idx++) {
3000 			if( Socket::isSocketValid(&bcfd[idx]) == true ) {
3001 				try {
3002 					// Send this machine's host name and address in hostname:n.n.n.n format
3003 					snprintf(buff,1024,"%s",myhostname);
3004 					for(unsigned int idx1 = 0; idx1 < ipList.size(); idx1++) {
3005 //						strcat(buff,":");
3006 //						strcat(buff,ipList[idx1].c_str());
3007 //						strcat(buff,":");
3008 //						string port_string = intToStr(this->boundPort);
3009 //#ifdef WIN32
3010 //						strncat(buff,port_string.c_str(),min((int)port_string.length(),100));
3011 //#else
3012 //						strncat(buff,port_string.c_str(),std::min((int)port_string.length(),100));
3013 //#endif
3014 						string buffCopy = buff;
3015 						snprintf(buff,1024,"%s:%s:%d",buffCopy.c_str(),ipList[idx1].c_str(),this->boundPort);
3016 					}
3017 
3018 					if(difftime((long int)time(NULL),elapsed) >= 1 && getQuitStatus() == false) {
3019 						elapsed = time(NULL);
3020 
3021 						bool pauseBroadCast = getPauseBroadcast();
3022 						if(pauseBroadCast == false) {
3023 							// Broadcast the packet to the subnet
3024 							//if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 )
3025 
3026 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Server is sending broadcast data [%s]\n",buff);
3027 
3028 							ssize_t send_res = sendto( bcfd[idx], buff, buffMaxSize, 0 , (struct sockaddr *)&bcLocal[idx], sizeof(struct sockaddr_in) );
3029 							if( send_res != buffMaxSize ) {
3030 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Sendto error: %s\n", Socket::getLastSocketErrorFormattedText().c_str());
3031 							}
3032 							else {
3033 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting on port [%d] the message: [%s]\n",Socket::getBroadCastPort(),buff);
3034 							}
3035 						}
3036 						//printf("Broadcasting server send_res = %d buff [%s] ip [%s] getPauseBroadcast() = %d\n",send_res,buff,ipSubnetMaskList[idx].c_str(),pauseBroadCast);
3037 
3038 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
3039 					}
3040 
3041 					if(getQuitStatus() == true) {
3042 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
3043 						break;
3044 					}
3045 					sleep(100); // send out broadcast every 1 seconds
3046 				}
3047 				catch(const exception &ex) {
3048 					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
3049 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
3050 					this->setQuitStatus(true);
3051 				}
3052 				catch(...) {
3053 					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
3054 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
3055 					this->setQuitStatus(true);
3056 				}
3057 			}
3058 
3059 			if(getQuitStatus() == true) {
3060 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
3061 				break;
3062 			}
3063 		}
3064 		if(getQuitStatus() == true) {
3065 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
3066 			break;
3067 		}
3068 	}
3069 
3070 	for(unsigned int idx = 0; idx < ipSubnetMaskList.size(); idx++) {
3071 		if( Socket::isSocketValid(&bcfd[idx]) == true ) {
3072 #ifndef WIN32
3073         ::close(bcfd[idx]);
3074         bcfd[idx] = -1;
3075 #else
3076         ::closesocket(bcfd[idx]);
3077         bcfd[idx] = INVALID_SOCKET;
3078 #endif
3079 		}
3080 	}
3081 
3082 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Broadcast thread is exiting\n",__FILE__,__FUNCTION__,__LINE__);
3083 }
3084 
getAveragePingMS(std::string host,int pingCount)3085 double Socket::getAveragePingMS(std::string host, int pingCount) {
3086 	double result = -1;
3087 	return result;
3088 
3089 /*
3090 	const bool debugPingOutput = false;
3091 	char szCmd[1024]="";
3092 #ifdef WIN32
3093 	sprintf(szCmd,"ping -n %d %s",pingCount,host.c_str());
3094 	if(debugPingOutput) printf("WIN32 is defined\n");
3095 #elif defined(__GNUC__)
3096 	sprintf(szCmd,"ping -c %d %s",pingCount,host.c_str());
3097 	if(debugPingOutput) printf("NON WIN32 is defined\n");
3098 #else
3099 	#error "Your compiler needs to support popen!"
3100 #endif
3101 	if(szCmd[0] != '\0') {
3102 		FILE *ping= NULL;
3103 #ifdef WIN32
3104 		ping= _popen(szCmd, "r");
3105 		if(debugPingOutput) printf("WIN32 style _popen\n");
3106 #elif defined(__GNUC__)
3107 		ping= popen(szCmd, "r");
3108 		if(debugPingOutput) printf("POSIX style _popen\n");
3109 #else
3110 	#error "Your compiler needs to support popen!"
3111 #endif
3112 		if (ping != NULL){
3113 			char buf[4000]="";
3114 			int bufferPos = 0;
3115 			for(;feof(ping) == false;) {
3116 				char *data = fgets(&buf[bufferPos], 256, ping);
3117 				bufferPos = strlen(buf);
3118 			}
3119 #ifdef WIN32
3120 			_pclose(ping);
3121 #elif defined(__GNUC__)
3122 			pclose(ping);
3123 #else
3124 	#error "Your compiler needs to support popen!"
3125 
3126 #endif
3127 
3128 			if(debugPingOutput) printf("Running cmd [%s] got [%s]\n",szCmd,buf);
3129 
3130 			// Linux
3131 			//softcoder@softhauslinux:~/Code/megaglest/trunk/mk/linux$ ping -c 5 soft-haus.com
3132 			//PING soft-haus.com (65.254.250.110) 56(84) bytes of data.
3133 			//64 bytes from 65-254-250-110.yourhostingaccount.com (65.254.250.110): icmp_seq=1 ttl=242 time=133 ms
3134 			//64 bytes from 65-254-250-110.yourhostingaccount.com (65.254.250.110): icmp_seq=2 ttl=242 time=137 ms
3135 			//
3136 			// Windows XP
3137 			//C:\Code\megaglest\trunk\data\glest_game>ping -n 5 soft-haus.com
3138 			//
3139 			//Pinging soft-haus.com [65.254.250.110] with 32 bytes of data:
3140 			//
3141 			//Reply from 65.254.250.110: bytes=32 time=125ms TTL=242
3142 			//Reply from 65.254.250.110: bytes=32 time=129ms TTL=242
3143 
3144 			std::string str = buf;
3145 			std::string::size_type ms_pos = 0;
3146 			int count = 0;
3147 			while ( ms_pos != std::string::npos) {
3148 				ms_pos = str.find("time=", ms_pos);
3149 
3150 				if(debugPingOutput) printf("count = %d ms_pos = %d\n",count,ms_pos);
3151 
3152 				if ( ms_pos != std::string::npos ) {
3153 					++count;
3154 
3155 					int endPos = str.find(" ms", ms_pos+5 );
3156 
3157 					if(debugPingOutput) printf("count = %d endPos = %d\n",count,endPos);
3158 
3159 					if(endPos == std::string::npos) {
3160 						endPos = str.find("ms ", ms_pos+5 );
3161 
3162 						if(debugPingOutput) printf("count = %d endPos = %d\n",count,endPos);
3163 					}
3164 
3165 					if(endPos != std::string::npos) {
3166 
3167 						if(count == 1) {
3168 							result = 0;
3169 						}
3170 						int startPos = ms_pos + 5;
3171 						int posLength = endPos - startPos;
3172 						if(debugPingOutput) printf("count = %d startPos = %d posLength = %d str = [%s]\n",count,startPos,posLength,str.substr(startPos, posLength).c_str());
3173 
3174 						float pingMS = strToFloat(str.substr(startPos, posLength));
3175 						result += pingMS;
3176 					}
3177 
3178 					ms_pos += 5; // start next search after this "time="
3179 				}
3180 			}
3181 
3182 			if(result > 0 && count > 1) {
3183 				result /= count;
3184 			}
3185 		}
3186 	}
3187 	return result;
3188 */
3189 }
3190 
getIpAddress()3191 std::string Socket::getIpAddress() {
3192 	return ipAddress;
3193 }
3194 
addIPAddressToBlockedList(string value)3195 void ServerSocket::addIPAddressToBlockedList(string value) {
3196 	if(isIPAddressBlocked(value) == false) {
3197 		blockIPList.push_back(value);
3198 		if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Blocked IP Address [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,value.c_str());
3199 	}
3200 }
isIPAddressBlocked(string value) const3201 bool ServerSocket::isIPAddressBlocked(string value) const {
3202 	bool result = (std::find(blockIPList.begin(),blockIPList.end(),value) != blockIPList.end());
3203 	return result;
3204 }
3205 
removeBlockedIPAddress(string value)3206 void ServerSocket::removeBlockedIPAddress(string value) {
3207 	vector<string>::iterator iterFind = std::find(blockIPList.begin(),blockIPList.end(),value);
3208 	if(iterFind != blockIPList.end()) {
3209 		blockIPList.erase(iterFind);
3210 	}
3211 }
3212 
clearBlockedIPAddress()3213 void ServerSocket::clearBlockedIPAddress() {
3214 	blockIPList.clear();
3215 }
3216 
hasBlockedIPAddresses() const3217 bool ServerSocket::hasBlockedIPAddresses() const {
3218 	return(blockIPList.size() > 0);
3219 }
3220 
3221 }}//end namespace
3222