diff options
Diffstat (limited to 'src/qcommon/net_ip.c')
-rw-r--r-- | src/qcommon/net_ip.c | 107 |
1 files changed, 78 insertions, 29 deletions
diff --git a/src/qcommon/net_ip.c b/src/qcommon/net_ip.c index c1e527c5..e3a95e4a 100644 --- a/src/qcommon/net_ip.c +++ b/src/qcommon/net_ip.c @@ -51,6 +51,7 @@ typedef unsigned short sa_family_t; # define EADDRNOTAVAIL WSAEADDRNOTAVAIL # define EAFNOSUPPORT WSAEAFNOSUPPORT # define ECONNRESET WSAECONNRESET +typedef u_long ioctlarg_t; # define socketError WSAGetLastError( ) static WSADATA winsockdata; @@ -86,6 +87,7 @@ typedef int SOCKET; # define SOCKET_ERROR -1 # define closesocket close # define ioctlsocket ioctl +typedef int ioctlarg_t; # define socketError errno #endif @@ -108,6 +110,8 @@ static cvar_t *net_port6; static cvar_t *net_mcast6addr; static cvar_t *net_mcast6iface; +static cvar_t *net_dropsim; + static struct sockaddr socksRelayAddr; static SOCKET ip_socket = INVALID_SOCKET; @@ -202,7 +206,7 @@ char *NET_ErrorString( void ) { default: return "NO ERROR"; } #else - return strerror (errno); + return strerror(socketError); #endif } @@ -521,16 +525,17 @@ qboolean NET_IsLocalAddress( netadr_t adr ) { /* ================== -Sys_GetPacket +NET_GetPacket -Never called by the game logic, just the system event queing +Receive one packet ================== */ #ifdef _DEBUG int recvfromCount; #endif -qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { +qboolean NET_GetPacket(netadr_t *net_from, msg_t *net_message, fd_set *fdr) +{ int ret; struct sockaddr_storage from; socklen_t fromlen; @@ -540,7 +545,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { recvfromCount++; // performance check #endif - if(ip_socket != INVALID_SOCKET) + if(ip_socket != INVALID_SOCKET && FD_ISSET(ip_socket, fdr)) { fromlen = sizeof(from); ret = recvfrom( ip_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen ); @@ -574,7 +579,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { net_message->readcount = 0; } - if( ret == net_message->maxsize ) { + if( ret >= net_message->maxsize ) { Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); return qfalse; } @@ -584,7 +589,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { } } - if(ip6_socket != INVALID_SOCKET) + if(ip6_socket != INVALID_SOCKET && FD_ISSET(ip6_socket, fdr)) { fromlen = sizeof(from); ret = recvfrom(ip6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen); @@ -601,7 +606,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { SockadrToNetadr((struct sockaddr *) &from, net_from); net_message->readcount = 0; - if(ret == net_message->maxsize) + if(ret >= net_message->maxsize) { Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); return qfalse; @@ -612,7 +617,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { } } - if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket) + if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket && FD_ISSET(multicast6_socket, fdr)) { fromlen = sizeof(from); ret = recvfrom(multicast6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen); @@ -629,7 +634,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { SockadrToNetadr((struct sockaddr *) &from, net_from); net_message->readcount = 0; - if(ret == net_message->maxsize) + if(ret >= net_message->maxsize) { Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); return qfalse; @@ -825,7 +830,7 @@ NET_IPSocket int NET_IPSocket( char *net_interface, int port, int *err ) { SOCKET newsocket; struct sockaddr_in address; - u_long _true = 1; + ioctlarg_t _true = 1; int i = 1; *err = 0; @@ -893,7 +898,7 @@ NET_IP6Socket int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, int *err ) { SOCKET newsocket; struct sockaddr_in6 address; - u_long _true = 1; + ioctlarg_t _true = 1; *err = 0; @@ -1496,6 +1501,8 @@ static qboolean NET_GetCvars( void ) { modified += net_socksPassword->modified; net_socksPassword->modified = qfalse; + net_dropsim = Cvar_Get("net_dropsim", "", CVAR_TEMP); + return modified ? qtrue : qfalse; } @@ -1624,6 +1631,42 @@ void NET_Shutdown( void ) { #endif } +/* +==================== +NET_Event + +Called from NET_Sleep which uses select() to determine which sockets have seen action. +==================== +*/ + +void NET_Event(fd_set *fdr) +{ + byte bufData[MAX_MSGLEN + 1]; + netadr_t from; + msg_t netmsg; + + while(1) + { + MSG_Init(&netmsg, bufData, sizeof(bufData)); + + if(NET_GetPacket(&from, &netmsg, fdr)) + { + if(net_dropsim->value > 0.0f && net_dropsim->value <= 100.0f) + { + // com_dropsim->value percent of incoming packets get dropped. + if(rand() < (int) (((double) RAND_MAX) / 100.0 * (double) net_dropsim->value)) + continue; // drop this packet + } + + if(com_sv_running->integer) + Com_RunAndTimeServerPacket(&from, &netmsg); + else + CL_PacketEvent(from, &netmsg); + } + else + break; + } +} /* ==================== @@ -1632,31 +1675,23 @@ NET_Sleep Sleeps msec or until something happens on the network ==================== */ -void NET_Sleep( int msec ) { +void NET_Sleep(int msec) +{ struct timeval timeout; - fd_set fdset; - int highestfd = -1; - - if (!com_dedicated->integer) - return; // we're not a server, just run full speed - - if (ip_socket == INVALID_SOCKET && ip6_socket == INVALID_SOCKET) - return; - - if (msec < 0 ) - return; + fd_set fdr; + int highestfd = -1, retval; - FD_ZERO(&fdset); + FD_ZERO(&fdr); if(ip_socket != INVALID_SOCKET) { - FD_SET(ip_socket, &fdset); + FD_SET(ip_socket, &fdr); highestfd = ip_socket; } if(ip6_socket != INVALID_SOCKET) { - FD_SET(ip6_socket, &fdset); + FD_SET(ip6_socket, &fdr); if(ip6_socket > highestfd) highestfd = ip6_socket; @@ -1664,9 +1699,23 @@ void NET_Sleep( int msec ) { timeout.tv_sec = msec/1000; timeout.tv_usec = (msec%1000)*1000; - select(highestfd + 1, &fdset, NULL, NULL, &timeout); -} + +#ifdef _WIN32 + if(highestfd < 0) + { + // windows ain't happy when select is called without valid FDs + SleepEx(msec, 0); + return; + } +#endif + retval = select(highestfd + 1, &fdr, NULL, NULL, &timeout); + + if(retval < 0) + Com_Printf("Warning: select() syscall failed: %s\n", NET_ErrorString()); + else if(retval > 0) + NET_Event(&fdr); +} /* ==================== |