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