/************************************************************************/ /* BattlEye Server code */ /************************************************************************/ #include "../server/server.h" #include #include #include #include #include #include #include extern qboolean Sys_StringToSockaddr(char *s, struct sockaddr *sadr); #ifdef BATTLEYE static int mastersocket = -1; qboolean SV_BE_ConnectToMaster(void) { qboolean _true = qtrue; struct sockaddr masteraddress; SV_BE_DisconnectFromMaster(); // create a TCP socket if ((mastersocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { Com_Printf("ERROR: SV_BE_ConnectToMaster: socket: %s\n", NET_ErrorString()); return qfalse; } // make it non-blocking if (ioctl(mastersocket, FIONBIO, &_true) == -1) { Com_Printf("ERROR: SV_BE_ConnectToMaster: ioctl FIONBIO: %s\n", NET_ErrorString()); return qfalse; } // resolve BE Master DNS host name if (!Sys_StringToSockaddr(BATTLEYE_MASTERSERVER, &masteraddress)) { Com_Printf("ERROR: SV_BE_ConnectToMaster: Sys_StringToSockaddr: %s\n", hstrerror(h_errno)); return qfalse; } if (connect(mastersocket, &masteraddress, sizeof(masteraddress)) == -1 && errno != EINPROGRESS) { Com_Printf("ERROR: SV_BE_ConnectToMaster: connect: %s\n", NET_ErrorString()); return qfalse; } return qtrue; } int SV_BE_CheckConnectAttempt(void) { int result; struct timeval timeout = { 0, 0 }; fd_set set; FD_ZERO(&set); FD_SET(mastersocket, &set); if ((result = select(mastersocket+1, NULL, &set, NULL, &timeout)) == -1) { Com_Printf("ERROR: SV_BE_CheckConnectAttempt: select: %s\n", NET_ErrorString()); return -1; } else if (result) { struct sockaddr addr; socklen_t len; if( !FD_ISSET(mastersocket, &set) ) { Com_Printf("ERROR: SV_BE_CheckConnectAttempt: write fd not set\n"); return -1; } // trick to check if we actually got connection succesfully // idea from http://cr.yp.to/docs/connect.html if( getpeername(mastersocket, &addr, &len) != 0 ) { char ch; read(mastersocket, &ch, 1); return -1; } return 1; } else return 0; } void SV_BE_SendToMaster(void* buf, int len) { #if ( defined(__FreeBSD__) && (__FreeBSD_version < 600020) ) int opt_val = 1; // Currently ignore the return code from setsockopt // Disable SIGPIPE setsockopt( mastersocket, SOL_SOCKET, SO_NOSIGPIPE, &opt_val, sizeof( opt_val ) ); send(mastersocket, buf, len, 0); opt_val = 0; // Enable SIGPIPE setsockopt( mastersocket, SOL_SOCKET, SO_NOSIGPIPE, &opt_val, sizeof( opt_val ) ); #else send(mastersocket, buf, len, MSG_NOSIGNAL); #endif } int SV_BE_ReceiveFromMaster(void* buf, int len) { int result = recv(mastersocket, buf, len, 0); if (result == -1 && errno == EWOULDBLOCK) return 0; else if (result == -1 || result == 0 || result != len) return -1; else return 1; } void SV_BE_DisconnectFromMaster(void) { if (mastersocket != -1) { close(mastersocket); mastersocket = -1; } } #endif // BATTLEYE