From da230fc73d48f6ddb92ddf3b63f22f1a46002ea3 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sun, 11 Apr 2010 07:12:56 +0000 Subject: [PATCH] Bugfix for LAN autofind servers. Needed to change the way we broadcast UDP so that we do it individually for each NIC's broadcast address. (see: http://stackoverflow.com/questions/683624/udp-broadcast-on-all-interfaces) --- mk/windoze/Glest.suo | Bin 172544 -> 174592 bytes mk/windoze/glest_game.vcproj | 2 +- .../sources/platform/win32/socket.cpp | 481 ++++++++++++++---- 3 files changed, 397 insertions(+), 86 deletions(-) diff --git a/mk/windoze/Glest.suo b/mk/windoze/Glest.suo index abf10e32a5da9c7b77b19e337722af9a2f7188d9..d835d4a4b41a3286bb642d24251ef413e175aa73 100755 GIT binary patch delta 6014 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 delta 2981 zcmZuzeNa@_6@TaQc3Bpcbww%!VFe-xWLc0Xv49JL3ISXx76nl>M(_(4ilC0bVo*~n z&BAdwwl#5aQd>VJ*|>Gzw00)zM>7UZO53#2W@@F)jICew51YhHsy%mE(?sI)$bX_!hH>;DB4P${{emDYQilPK!ai=<>i(ylx$>ETJ0fXw>uDh)2 zmB%cGakAYws+-KuObRxA?U74Vyr5?5_Aqx9A4WZ|)3X&B?A8C2&D)D`r>Prid=E_# zAgl_;o8!an+)=M6IRBkkpWWQ2*PUfT1P768wNOQ|&iDDWa=?~WXgb2 ztnwMO$}~8s*OunMn=s&9I%E~e+EZC@9WOG1%R?l3Z0_(JX~<1E{SQ=8?Am^k{0eX-+!~06`h-#>NlL_*%VT+_A)L zVW;|ya0vtRBZi{o=n@#?#+QU%F+kS;pMPkeh7{8q25W52hCh$T=1n}ha*PdUy*GA?qHdh6AX2K2cbW|F5K)=+Oce1Lh6;^g+%P~t{Nr)Mj8>z^MI zz5Z3;0&MAA#cP!`G$0qa5yk+MnwrsbJ4uFBLs{vNFBkMGdAGqd{MEV`ifw?K|I^$=JI=Mo}JwINAI+ zLq7j0${XQ%Pq-4$cg5^VqhAI=6&4d6Zj1+%_6}6Q<1S z2zAMFHkBdw=LsiIzvQHJYSX>&cOcVgm`hm;;CJ-bJa~qlSqzua-LM=TrAG4RLjtL1 z;0yZk1bH3y=?Jz$E=$@BOmHWo)-D1ir6S;I^ zwx}T2c`l5eRDKIvZq0rHUIv&DOepQaMIap}Y_yFZ(WujKOM@#Q1b)0QhEpnuX8Yhh zx^IJi>K}nkw8kc82D4hr8-|BfVC0t2v z|ah6=A!bla%z=Y|1?N917QJ_>5(Yb7xPnOe= zN~^QQFa=PQlIt}{)3(?J0v$O36Sav8#clEbysMDjRka()uwU%*SBZ*Pb*-u>GI%`K_dg!Bs`{UYo2(jHjTOBurO!DiKzaPF_WpboL zG|w^#}2S!Tri!URe?ELKucEvMk7eZsBP?iI(w z$Yh1@$UEQ6g)3fO4}&xXMcL3H;Uagbu#xQ`7_g;7Pq(U}c<4tW03*oXi{#lWhS5=C pAXg8VG#+?6jBHtOjU4e1H(uA@-Y2GNeTPLo(7t|A5DYc=_g`-SRXzX! diff --git a/mk/windoze/glest_game.vcproj b/mk/windoze/glest_game.vcproj index 06f98df45..6317702d2 100755 --- a/mk/windoze/glest_game.vcproj +++ b/mk/windoze/glest_game.vcproj @@ -155,7 +155,7 @@ /> #include "util.h" #include "platform_util.h" +//#include + +#ifdef WIN32 +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +//typedef unsigned long uint32; + #include "leak_dumper.h" #define socklen_t int @@ -211,6 +232,313 @@ Socket::SocketManager::~SocketManager(){ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Winsock cleanup complete.\n"); } +#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__) +# define USE_GETIFADDRS 1 +# include +static uint32 SockAddrToUint32(struct sockaddr * a) +{ + return ((a)&&(a->sa_family == AF_INET)) ? ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0; +} +#endif + +// convert a numeric IP address into its string representation +static void Inet_NtoA(uint32 addr, char * ipbuf) +{ + sprintf(ipbuf, "%li.%li.%li.%li", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); +} + +// convert a string represenation of an IP address into its numeric equivalent +static uint32 Inet_AtoN(const char * buf) +{ + // net_server inexplicably doesn't have this function; so I'll just fake it + uint32 ret = 0; + int shift = 24; // fill out the MSB first + bool startQuad = true; + while((shift >= 0)&&(*buf)) + { + if (startQuad) + { + unsigned char quad = (unsigned char) atoi(buf); + ret |= (((uint32)quad) << shift); + shift -= 8; + } + startQuad = (*buf == '.'); + buf++; + } + return ret; +} + +/* +static void PrintNetworkInterfaceInfos() +{ +#if defined(USE_GETIFADDRS) + // BSD-style implementation + struct ifaddrs * ifap; + if (getifaddrs(&ifap) == 0) + { + struct ifaddrs * p = ifap; + while(p) + { + uint32 ifaAddr = SockAddrToUint32(p->ifa_addr); + uint32 maskAddr = SockAddrToUint32(p->ifa_netmask); + uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr); + if (ifaAddr > 0) + { + char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr); + printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + } + p = p->ifa_next; + } + freeifaddrs(ifap); + } +#elif defined(WIN32) + // Windows XP style implementation + + // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx + // Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable() + // multiple times in order to deal with potential race conditions properly. + MIB_IPADDRTABLE * ipTable = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false); + if (ipRet == ERROR_INSUFFICIENT_BUFFER) + { + free(ipTable); // in case we had previously allocated it + ipTable = (MIB_IPADDRTABLE *) malloc(bufLen); + } + else if (ipRet == NO_ERROR) break; + else + { + free(ipTable); + ipTable = NULL; + break; + } + } + } + + if (ipTable) + { + // Try to get the Adapters-info table, so we can given useful names to the IP + // addresses we are returning. Gotta call GetAdaptersInfo() up to 5 times to handle + // the potential race condition between the size-query call and the get-data call. + // I love a well-designed API :^P + IP_ADAPTER_INFO * pAdapterInfo = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen); + if (apRet == ERROR_BUFFER_OVERFLOW) + { + free(pAdapterInfo); // in case we had previously allocated it + pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen); + } + else if (apRet == ERROR_SUCCESS) break; + else + { + free(pAdapterInfo); + pAdapterInfo = NULL; + break; + } + } + } + + for (DWORD i=0; idwNumEntries; i++) + { + const MIB_IPADDRROW & row = ipTable->table[i]; + + // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it + const char * name = NULL; + const char * desc = NULL; + if (pAdapterInfo) + { + IP_ADAPTER_INFO * next = pAdapterInfo; + while((next)&&(name==NULL)) + { + IP_ADDR_STRING * ipAddr = &next->IpAddressList; + while(ipAddr) + { + if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) + { + name = next->AdapterName; + desc = next->Description; + break; + } + ipAddr = ipAddr->Next; + } + next = next->Next; + } + } + char buf[128]; + if (name == NULL) + { + sprintf(buf, "unnamed-%i", i); + name = buf; + } + + uint32 ipAddr = ntohl(row.dwAddr); + uint32 netmask = ntohl(row.dwMask); + uint32 baddr = ipAddr & netmask; + if (row.dwBCastAddr) baddr |= ~netmask; + + char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr); + printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + } + + free(pAdapterInfo); + free(ipTable); + } +#else + // Dunno what we're running on here! +# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!" +#endif +} +*/ + +string getNetworkInterfaceBroadcastAddress(string ipAddress) +{ + string broadCastAddress = ""; + +#if defined(USE_GETIFADDRS) + // BSD-style implementation + struct ifaddrs * ifap; + if (getifaddrs(&ifap) == 0) + { + struct ifaddrs * p = ifap; + while(p) + { + uint32 ifaAddr = SockAddrToUint32(p->ifa_addr); + uint32 maskAddr = SockAddrToUint32(p->ifa_netmask); + uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr); + if (ifaAddr > 0) + { + char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr); + printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + } + p = p->ifa_next; + } + freeifaddrs(ifap); + } +#elif defined(WIN32) + // Windows XP style implementation + + // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx + // Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable() + // multiple times in order to deal with potential race conditions properly. + MIB_IPADDRTABLE * ipTable = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false); + if (ipRet == ERROR_INSUFFICIENT_BUFFER) + { + free(ipTable); // in case we had previously allocated it + ipTable = (MIB_IPADDRTABLE *) malloc(bufLen); + } + else if (ipRet == NO_ERROR) break; + else + { + free(ipTable); + ipTable = NULL; + break; + } + } + } + + if (ipTable) + { + // Try to get the Adapters-info table, so we can given useful names to the IP + // addresses we are returning. Gotta call GetAdaptersInfo() up to 5 times to handle + // the potential race condition between the size-query call and the get-data call. + // I love a well-designed API :^P + IP_ADAPTER_INFO * pAdapterInfo = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen); + if (apRet == ERROR_BUFFER_OVERFLOW) + { + free(pAdapterInfo); // in case we had previously allocated it + pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen); + } + else if (apRet == ERROR_SUCCESS) break; + else + { + free(pAdapterInfo); + pAdapterInfo = NULL; + break; + } + } + } + + for (DWORD i=0; idwNumEntries; i++) + { + const MIB_IPADDRROW & row = ipTable->table[i]; + + // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it + const char * name = NULL; + const char * desc = NULL; + if (pAdapterInfo) + { + IP_ADAPTER_INFO * next = pAdapterInfo; + while((next)&&(name==NULL)) + { + IP_ADDR_STRING * ipAddr = &next->IpAddressList; + while(ipAddr) + { + if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) + { + name = next->AdapterName; + desc = next->Description; + break; + } + ipAddr = ipAddr->Next; + } + next = next->Next; + } + } + char buf[128]; + if (name == NULL) + { + //sprintf(buf, "unnamed-%i", i); + name = buf; + } + + uint32 ipAddr = ntohl(row.dwAddr); + uint32 netmask = ntohl(row.dwMask); + uint32 baddr = ipAddr & netmask; + if (row.dwBCastAddr) baddr |= ~netmask; + + char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr); + //printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + if(strcmp(ifaAddrStr,ipAddress.c_str()) == 0) { + broadCastAddress = dstAddrStr; + } + } + + free(pAdapterInfo); + free(ipTable); + } +#else + // Dunno what we're running on here! +# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!" +#endif + + return broadCastAddress; +} + std::vector Socket::getLocalIPAddressList() { std::vector ipList; @@ -1141,17 +1469,18 @@ void BroadCastSocketThread::execute() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - unsigned int tbcaddr; // The broadcast address. + const int MAX_NIC_COUNT = 10; + //unsigned int tbcaddr; // The broadcast address. short port; // The port for the broadcast. - struct sockaddr_in bcLocal; // local socket address for the broadcast. - struct sockaddr_in bcaddr; // The broadcast address for the receiver. - int bcfd; // The socket used for the broadcast. + struct sockaddr_in bcLocal[MAX_NIC_COUNT]; // local socket address for the broadcast. + //struct sockaddr_in bcaddr; // The broadcast address for the receiver. + int bcfd[MAX_NIC_COUNT]; // The socket used for the broadcast. bool one = true; // Parameter for "setscokopt". int pn; // The number of the packet broadcasted. char buff[1024]; // Buffers the data to be broadcasted. char myhostname[100]; // hostname of local machine - //char subnetmask[100]; // Subnet mask to broadcast to - struct in_addr myaddr; // My host address in net format + char subnetmask[MAX_NIC_COUNT][100]; // Subnet mask to broadcast to + //struct in_addr myaddr; // My host address in net format struct hostent* myhostent; char * ptr; // some transient vars int len,i; @@ -1160,103 +1489,76 @@ void BroadCastSocketThread::execute() { gethostname(myhostname,100); myhostent = gethostbyname(myhostname); - // get only the first host IP address + // get all host IP addresses std::vector ipList = Socket::getLocalIPAddressList(); - /* - strcpy(subnetmask, ipList[0].c_str()); - ptr = &subnetmask[0]; - len = strlen(ptr); + for(unsigned int idx = 0; idx < ipList.size() && idx < MAX_NIC_COUNT; idx++) { + string broadCastAddress = getNetworkInterfaceBroadcastAddress(ipList[idx]); + strcpy(subnetmask[idx], broadCastAddress.c_str()); + } - // substitute the address with class C subnet mask x.x.x.255 - for(i=len;i>0;i--) { - if(ptr[i] == '.') { - strcpy(&ptr[i+1],"255"); - break; - } - } - */ - - // Convert the broadcast address from dot notation to a broadcast address. - //if( (tbcaddr = inet_addr( subnetmask )) == INADDR_NONE ) - //{ - // SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Badly formatted BC address: %d\n", WSAGetLastError()); - //exit(-1); - //} - //else - { - port = htons( Socket::getBroadCastPort() ); + port = htons( Socket::getBroadCastPort() ); + for(unsigned int idx = 0; idx < ipList.size() && idx < MAX_NIC_COUNT; idx++) { // Create the broadcast socket - memset( &bcLocal, 0, sizeof( struct sockaddr_in)); - bcLocal.sin_family = AF_INET; - bcLocal.sin_addr.s_addr = htonl( INADDR_BROADCAST ); - bcLocal.sin_port = port; // We are letting the OS fill in the port number for the local machine. - bcfd = socket( AF_INET, SOCK_DGRAM, 0 ); - - // If there is an error, report it and terminate. - if( bcfd <= 0 ) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Unable to allocate broadcast socket.: %d\n", WSAGetLastError()); + memset( &bcLocal[idx], 0, sizeof( struct sockaddr_in)); + bcLocal[idx].sin_family = AF_INET; + bcLocal[idx].sin_addr.s_addr = inet_addr(subnetmask[idx]); //htonl( INADDR_BROADCAST ); + bcLocal[idx].sin_port = port; // We are letting the OS fill in the port number for the local machine. + bcfd[idx] = socket( AF_INET, SOCK_DGRAM, 0 ); + if( bcfd[idx] <= 0 ) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Unable to allocate broadcast socket [%s]: %d\n", subnetmask[idx], WSAGetLastError()); //exit(-1); } // Mark the socket for broadcast. - else if( setsockopt( bcfd, SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof( int ) ) < 0 ) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not set socket to broadcast.: %d\n", WSAGetLastError()); + else if( setsockopt( bcfd[idx], SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof( int ) ) < 0 ) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not set socket to broadcast [%s]: %d\n", subnetmask[idx], WSAGetLastError()); //exit(-1); } - // Bind the address to the broadcast socket. - else { - //int val = 1; - //setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] setting up broadcast on address [%s]\n",__FILE__,__FUNCTION__,__LINE__,subnetmask[idx]); + } - //if(::bind(bcfd, (struct sockaddr *) &bcLocal, sizeof(struct sockaddr_in)) < 0) { - // SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not bind address to BC socket.: %d\n", WSAGetLastError()); - //exit(-1); - //} - //else - { - // Record the broadcast address of the receiver. - bcaddr.sin_family = AF_INET; - bcaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);//tbcaddr; - bcaddr.sin_port = port; + setRunningStatus(true); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n"); - setRunningStatus(true); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n"); - - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + time_t elapsed = 0; + for( pn = 1; ; pn++ ) + { + for(unsigned int idx = 0; idx < ipList.size() && idx < MAX_NIC_COUNT; idx++) { + if( bcfd[idx] > 0 ) { try { // Send this machine's host name and address in hostname:n.n.n.n format sprintf(buff,"%s",myhostname); - for(int idx = 0; idx < ipList.size(); idx++) { - sprintf(buff,"%s:%s",buff,ipList[idx].c_str()); + for(unsigned int idx1 = 0; idx1 < ipList.size(); idx1++) { + sprintf(buff,"%s:%s",buff,ipList[idx1].c_str()); } - time_t elapsed = 0; - for( pn = 1; ; pn++ ) - { - if(difftime(time(NULL),elapsed) >= 1) { - elapsed = time(NULL); - // Broadcast the packet to the subnet - if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 ) - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Sendto error: %d\n", WSAGetLastError()); - //exit(-1); - } - else { - //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting to [%s] the message: [%s]\n",subnetmask,buff); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting on port [%d] the message: [%s]\n",Socket::getBroadCastPort(),buff); - } + if(difftime(time(NULL),elapsed) >= 1) { + elapsed = time(NULL); + // Broadcast the packet to the subnet + //if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 ) + if( sendto( bcfd[idx], buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcLocal[idx], sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 ) + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Sendto error: %d\n", WSAGetLastError()); + //exit(-1); + } + else { + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting to [%s] the message: [%s]\n",subnetmask,buff); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting on port [%d] the message: [%s]\n",Socket::getBroadCastPort(),buff); + } - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - } - if(getQuitStatus() == true) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - break; - } - sleep( 100 ); // send out broadcast every 1 seconds + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } + + if(getQuitStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + break; + } + sleep( 100 ); // send out broadcast every 1 seconds + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } catch(const exception &ex) { @@ -1267,12 +1569,21 @@ void BroadCastSocketThread::execute() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__); setRunningStatus(false); } + } - setRunningStatus(false); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is exiting\n"); + if(getQuitStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + break; } } - } + if(getQuitStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + break; + } + } + + setRunningStatus(false); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is exiting\n"); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); }