Index: code/q3_ui/ui_servers2.c =================================================================== --- code/q3_ui/ui_servers2.c (revision 1121) +++ code/q3_ui/ui_servers2.c (working copy) @@ -142,7 +142,7 @@ static char* netnames[] = { "???", "UDP", - "IPX", + "IPX", // FIXME: remove ipx remnants NULL }; Index: code/unix/unix_net.c =================================================================== --- code/unix/unix_net.c (revision 1121) +++ code/unix/unix_net.c (working copy) @@ -24,6 +24,47 @@ #include "../qcommon/q_shared.h" #include "../qcommon/qcommon.h" +#define MAX_IPS 16 +static int numIP; +static byte localIP[MAX_IPS][4]; + +#ifndef _WIN32 +typedef int SOCKET; +#endif // ! _WIN32 + +#ifndef SOCKET_ERROR +#define SOCKET_ERROR -1 +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET -1 +#endif + +#ifdef AF_INET +#undef AF_INET +#define AF_INET PF_INET +#endif + +static SOCKET ip_socket; + +#ifdef _WIN32 +static WSADATA winsockdata; +static qboolean winsockInitialized = qfalse; +static qboolean usingSocks = qfalse; +static qboolean networkingEnabled = qfalse; + +static cvar_t *net_noudp; + +static cvar_t *net_socksEnabled; +static cvar_t *net_socksServer; +static cvar_t *net_socksPort; +static cvar_t *net_socksUsername; +static cvar_t *net_socksPassword; +static struct sockaddr socksRelayAddr; + +static SOCKET socks_socket; + +#else // Unix or similar #include #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 // needed for socket_t on OSX 10.2 @@ -53,302 +94,366 @@ #include #endif -static cvar_t *noudp; +static cvar_t * noudp; -netadr_t net_local_adr; +netadr_t net_local_adr; +#endif // _WIN32 -int ip_socket; -int ipx_socket; +/*void NET_Init (void); +void NET_Shutdown (void)*/ +char * NET_ErrorString (void); +int NET_IPSocket (char *net_interface, int port); +void NET_OpenIP (void); +void NET_Sleep (int msec); +void NET_GetLocalAddress (void); -#define MAX_IPS 16 -static int numIP; -static byte localIP[MAX_IPS][4]; +#ifdef _WIN32 +void NetadrToSockadr (netadr_t *a, struct sockaddr *s); +void SockadrToNetadr (struct sockaddr *s, netadr_t *a); +#else +void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s); +void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a); +#endif // _WIN32 -int NET_Socket (char *net_interface, int port); -char *NET_ErrorString (void); +qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr); +qboolean Sys_StringToAdr (const char *s, netadr_t *a); +qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message); +void Sys_SendPacket (int length, const void *data, netadr_t to); +qboolean Sys_IsLANAddress (netadr_t adr); +void Sys_ShowIP (void); -//============================================================================= +#ifdef _WIN32 +static void NET_Config (qboolean enableNetworking); +static qboolean NET_GetCvars(void); +void NET_OpenSocks (int port); +void NET_Restart (void); +#endif // _WIN32 -void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s) -{ - memset (s, 0, sizeof(*s)); +// ======================================================================== - if (a->type == NA_BROADCAST) - { - s->sin_family = AF_INET; - - s->sin_port = a->port; - *(int *)&s->sin_addr = -1; +/* +==================== +NET_Init +==================== +*/ +void NET_Init (void) { +#ifdef _WIN32 + int r; + + r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata ); + + if( r ) { + Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r ); + return; } - else if (a->type == NA_IP) - { - s->sin_family = AF_INET; - *(int *)&s->sin_addr = *(int *)&a->ip; - s->sin_port = a->port; - } -} + winsockInitialized = qtrue; + Com_Printf( "Winsock Initialized\n" ); -void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a) -{ - *(int *)&a->ip = *(int *)&s->sin_addr; - a->port = s->sin_port; - a->type = NA_IP; -} + // this is really just to get the cvars registered + NET_GetCvars(); -char *NET_BaseAdrToString (netadr_t a) -{ - static char s[64]; - - Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); - - return s; + //FIXME testing! + NET_Config( qtrue ); +#else // Unix or simliar + noudp = Cvar_Get ("net_noudp", "0", 0); + // open sockets + if (! noudp->value) { + NET_OpenIP (); + } +#endif // _WIN32 } /* -============= -Sys_StringToAdr - -idnewt -192.246.40.70 -============= +==================== +NET_Shutdown +==================== */ -qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr) -{ - struct hostent *h; - //char *colon; // bk001204 - unused - - memset (sadr, 0, sizeof(*sadr)); - ((struct sockaddr_in *)sadr)->sin_family = AF_INET; - - ((struct sockaddr_in *)sadr)->sin_port = 0; - - if ( s[0] >= '0' && s[0] <= '9') - { - *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s); +void NET_Shutdown (void) { +#ifdef _WIN32 + if ( !winsockInitialized ) { + return; } - else - { - if (! (h = gethostbyname(s)) ) - return qfalse; - *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; + NET_Config( qfalse ); + WSACleanup(); + winsockInitialized = qfalse; +#else // Unix or similar + if (ip_socket) { + close(ip_socket); + ip_socket = 0; } - - return qtrue; +#endif // _WIN32 } /* -============= -Sys_StringToAdr - -localhost -idnewt -idnewt:28000 -192.246.40.70 -192.246.40.70:28000 -============= +==================== +NET_ErrorString +==================== */ -qboolean Sys_StringToAdr (const char *s, netadr_t *a) -{ - struct sockaddr_in sadr; +char * NET_ErrorString (void) { +#ifdef _WIN32 + int code; - if (!Sys_StringToSockaddr (s, (struct sockaddr *)&sadr)) - return qfalse; + code = WSAGetLastError(); - SockadrToNetadr (&sadr, a); - - return qtrue; + switch( code ) { + case WSAEINTR: return "WSAEINTR"; + case WSAEBADF: return "WSAEBADF"; + case WSAEACCES: return "WSAEACCES"; + case WSAEDISCON: return "WSAEDISCON"; + case WSAEFAULT: return "WSAEFAULT"; + case WSAEINVAL: return "WSAEINVAL"; + case WSAEMFILE: return "WSAEMFILE"; + case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK"; + case WSAEINPROGRESS: return "WSAEINPROGRESS"; + case WSAEALREADY: return "WSAEALREADY"; + case WSAENOTSOCK: return "WSAENOTSOCK"; + case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ"; + case WSAEMSGSIZE: return "WSAEMSGSIZE"; + case WSAEPROTOTYPE: return "WSAEPROTOTYPE"; + case WSAENOPROTOOPT: return "WSAENOPROTOOPT"; + case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT"; + case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT"; + case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP"; + case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT"; + case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT"; + case WSAEADDRINUSE: return "WSAEADDRINUSE"; + case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL"; + case WSAENETDOWN: return "WSAENETDOWN"; + case WSAENETUNREACH: return "WSAENETUNREACH"; + case WSAENETRESET: return "WSAENETRESET"; + case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR"; + case WSAECONNRESET: return "WSAECONNRESET"; + case WSAENOBUFS: return "WSAENOBUFS"; + case WSAEISCONN: return "WSAEISCONN"; + case WSAENOTCONN: return "WSAENOTCONN"; + case WSAESHUTDOWN: return "WSAESHUTDOWN"; + case WSAETOOMANYREFS: return "WSAETOOMANYREFS"; + case WSAETIMEDOUT: return "WSAETIMEDOUT"; + case WSAECONNREFUSED: return "WSAECONNREFUSED"; + case WSAELOOP: return "WSAELOOP"; + case WSAENAMETOOLONG: return "WSAENAMETOOLONG"; + case WSAEHOSTDOWN: return "WSAEHOSTDOWN"; + case WSASYSNOTREADY: return "WSASYSNOTREADY"; + case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED"; + case WSANOTINITIALISED: return "WSANOTINITIALISED"; + case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND"; + case WSATRY_AGAIN: return "WSATRY_AGAIN"; + case WSANO_RECOVERY: return "WSANO_RECOVERY"; + case WSANO_DATA: return "WSANO_DATA"; + default: return "NO ERROR"; + } +#else // Unix or similar + int code; + code = errno; + return strerror(code); +#endif // _WIN32 } +/* +==================== +NET_IPSocket +==================== +*/ +int NET_IPSocket (char *net_interface, int port) { + struct sockaddr_in address; + int i = 1; + SOCKET newsocket; + qboolean trueValue = qtrue; +#ifdef _WIN32 + int err; +#endif // _WIN32 -//============================================================================= + if (net_interface) { + Com_Printf("Opening IP socket: %s:%i\n", net_interface, port); + } else { + Com_Printf("Opening IP socket: localhost:%i\n", port); + } + + if ((newsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { +#ifdef _WIN32 + err = WSAGetLastError(); + if (err != WSAEAFNOSUPPORT) { + Com_Printf("ERROR: UDP_OpenSocket: socket: %s\n", NET_ErrorString()); + } +#else // Unix or similar + Com_Printf("ERROR: UDP_OpenSocket: socket: %s\n", NET_ErrorString()); +#endif // _WIN32 + return 0; + } + + // make it non-blocking +#ifdef _WIN32 + if (ioctlsocket(newsocket, FIONBIO, (u_long *)&trueValue) == SOCKET_ERROR) { +#else // Unix or similar + if (ioctl(newsocket, FIONBIO, &trueValue) == SOCKET_ERROR) { +#endif // _WIN32 + Com_Printf("ERROR: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString()); + return 0; -qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message) -{ - int ret; - struct sockaddr_in from; - socklen_t fromlen; - int net_socket; - int protocol; - int err; + } + + // make it broadcast capable + if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == SOCKET_ERROR) { + Com_Printf("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString()); + return 0; + } - for (protocol = 0 ; protocol < 2 ; protocol++) - { - if (protocol == 0) - net_socket = ip_socket; - else - net_socket = ipx_socket; + if ((! net_interface) || (! net_interface[0]) || (! Q_stricmp(net_interface, "localhost"))) { + address.sin_addr.s_addr = INADDR_ANY; + } else { + Sys_StringToSockaddr(net_interface, (struct sockaddr *)&address); + } - if (!net_socket) - continue; + if (port == PORT_ANY) { + address.sin_port = 0; + } else { + address.sin_port = htons((short)port); + } - fromlen = sizeof(from); - ret = recvfrom (net_socket, net_message->data, net_message->maxsize - , 0, (struct sockaddr *)&from, &fromlen); + address.sin_family = AF_INET; - SockadrToNetadr (&from, net_from); - // bk000305: was missing - net_message->readcount = 0; + if (bind(newsocket, (void *)&address, sizeof(address)) == SOCKET_ERROR) { + Com_Printf("Error: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); +#ifdef _WIN32 + closesocket(newsocket); +#else // Unix or similar + close(newsocket); +#endif // _WIN32 + return 0; + } - if (ret == -1) - { - err = errno; + return newsocket; +} - if (err == EWOULDBLOCK || err == ECONNREFUSED) - continue; - Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(), - NET_AdrToString(*net_from)); - continue; - } +/* +==================== +NET_OpenIP +==================== +*/ +void NET_OpenIP( void ) { + cvar_t * ip; + int port; + int i; + + ip = Cvar_Get("net_ip", "localhost", CVAR_LATCH); + port = Cvar_Get("net_port", va( "%i", PORT_SERVER ), CVAR_LATCH)->integer; - if (ret == net_message->maxsize) - { - Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); - continue; + // automatically scan for a valid port, so multiple + // dedicated servers can be started without requiring + // a different net_port for each one + for (i = 0 ; i < 10 ; i++) { + ip_socket = NET_IPSocket(ip->string, port + i); + if (ip_socket) { + Cvar_SetValue("net_port", port + i); + +#ifdef _WIN32 + if (net_socksEnabled->integer) { + NET_OpenSocks(port + i); + } +#endif // _WIN32 + NET_GetLocalAddress(); + return; } - - net_message->cursize = ret; - return qtrue; } - - return qfalse; + Com_Error(ERR_FATAL, "Couldn't allocate IP port\n"); } -//============================================================================= +/* +==================== +NET_Sleep +==================== +*/ +void NET_Sleep (int msec) { +//============================ +// FIXME: Why not for _WIN32 also? +//============================ +#ifndef _WIN32 + struct timeval timeout; + fd_set fdset; + extern qboolean stdin_active; + int highestfd = 0; -void Sys_SendPacket( int length, const void *data, netadr_t to ) -{ - int ret; - struct sockaddr_in addr; - int net_socket; + if (!com_dedicated->integer) { + return; // we're not a server, just run full speed + } - if (to.type == NA_BROADCAST) - { - net_socket = ip_socket; + FD_ZERO(&fdset); + if (stdin_active) { + FD_SET(0, &fdset); // stdin is processed too + highestfd = 1; } - else if (to.type == NA_IP) - { - net_socket = ip_socket; + + if (ip_socket) { + FD_SET(ip_socket, &fdset); // network socket + if (ip_socket >= highestfd) { + highestfd = ip_socket + 1; + } } - else if (to.type == NA_IPX) - { - net_socket = ipx_socket; + + if (highestfd) { + if(msec >= 0) { + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + select(highestfd, &fdset, NULL, NULL, &timeout); + } else { + // Block indefinitely + select(highestfd, &fdset, NULL, NULL, NULL); + } } - else if (to.type == NA_BROADCAST_IPX) - { - net_socket = ipx_socket; - } - else { - Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); - return; - } - - if (!net_socket) - return; - - NetadrToSockadr (&to, &addr); - - ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); - if (ret == -1) - { - Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), - NET_AdrToString (to)); - } +#endif // ! _WIN32 } - -//============================================================================= - /* -================== -Sys_IsLANAddress - -LAN clients will have their rate var ignored -================== +===================== +NET_GetLocalAddress +===================== */ -qboolean Sys_IsLANAddress (netadr_t adr) { - int i; +#ifdef _WIN32 +void NET_GetLocalAddress( void ) { + char hostname[256]; + struct hostent *hostInfo; + int error; + char *p; + int ip; + int n; - if( adr.type == NA_LOOPBACK ) { - return qtrue; + if( gethostname( hostname, 256 ) == SOCKET_ERROR ) { + error = WSAGetLastError(); + return; } - if( adr.type == NA_IPX ) { - return qtrue; + hostInfo = gethostbyname( hostname ); + if( !hostInfo ) { + error = WSAGetLastError(); + return; } - if( adr.type != NA_IP ) { - return qfalse; + Com_Printf( "Hostname: %s\n", hostInfo->h_name ); + n = 0; + while( ( p = hostInfo->h_aliases[n++] ) != NULL ) { + Com_Printf( "Alias: %s\n", p ); } - // RFC1918: - // 10.0.0.0 - 10.255.255.255 (10/8 prefix) - // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) - // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) - if(adr.ip[0] == 10) - return qtrue; - if(adr.ip[0] == 172 && (adr.ip[1]&0xf0) == 16) - return qtrue; - if(adr.ip[0] == 192 && adr.ip[1] == 168) - return qtrue; - - // the checks below are bogus, aren't they? -- ln - - // choose which comparison to use based on the class of the address being tested - // any local adresses of a different class than the address being tested will fail based on the first byte - - // Class A - if( (adr.ip[0] & 0x80) == 0x00 ) { - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] ) { - return qtrue; - } - } - // the RFC1918 class a block will pass the above test - return qfalse; + if ( hostInfo->h_addrtype != AF_INET ) { + return; } - // Class B - if( (adr.ip[0] & 0xc0) == 0x80 ) { - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) { - return qtrue; - } - // also check against the RFC1918 class b blocks - if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) { - return qtrue; - } - } - return qfalse; + numIP = 0; + while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) { + ip = ntohl( *(int *)p ); + localIP[ numIP ][0] = p[0]; + localIP[ numIP ][1] = p[1]; + localIP[ numIP ][2] = p[2]; + localIP[ numIP ][3] = p[3]; + Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff ); + numIP++; } - - // Class C - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) { - return qtrue; - } - // also check against the RFC1918 class c blocks - if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) { - return qtrue; - } - } - return qfalse; } +#else // Unix or similar +// unix /* -================== -Sys_ShowIP -================== -*/ -void Sys_ShowIP(void) { - int i; - - for (i = 0; i < numIP; i++) { - Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] ); - } -} - -/* ===================== NET_GetLocalAddress ===================== @@ -470,7 +575,7 @@ close(interfaceSocket); } -#else +#else // Unix, but not Mac OS X void NET_GetLocalAddress( void ) { char hostname[256]; struct hostent *hostInfo; @@ -508,176 +613,675 @@ Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff ); } } -#endif +#endif // MACOS_X +#endif // _WIN32 /* -==================== -NET_OpenIP -==================== +===================== +NetadrToSockadr +===================== */ -// bk001204 - prototype needed -int NET_IPSocket (char *net_interface, int port); -void NET_OpenIP (void) -{ - cvar_t *ip; - int port; - int i; +#ifdef _WIN32 +void NetadrToSockadr (netadr_t *a, struct sockaddr *s) { +#else // Unix or similar +void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s) { +#endif // _WIN32 + memset( s, 0, sizeof(*s) ); - ip = Cvar_Get ("net_ip", "localhost", 0); + if (a->type == NA_BROADCAST) { +#ifdef _WIN32 + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_port = a->port; + ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; +#else // Unix or similar + s->sin_family = AF_INET; + s->sin_port = a->port; + *(int *)&s->sin_addr = -1; +#endif // _WIN32 + } else if (a->type == NA_IP) { +#ifdef _WIN32 + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; + ((struct sockaddr_in *)s)->sin_port = a->port; +#else // Unix or similar + s->sin_family = AF_INET; + *(int *)&s->sin_addr = *(int *)&a->ip; + s->sin_port = a->port; +#endif // _WIN32 + } +} - port = Cvar_Get("net_port", va("%i", PORT_SERVER), 0)->value; +/* +===================== +SockadrToNetadr +===================== +*/ +#ifdef _WIN32 +void SockadrToNetadr (struct sockaddr *s, netadr_t *a) { + a->type = NA_IP; + *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; + a->port = ((struct sockaddr_in *)s)->sin_port; +#else // Unix or similar +void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a) { + a->type = NA_IP; + *(int *)&a->ip = *(int *)&s->sin_addr; + a->port = s->sin_port; +#endif // _WIN32 +} - for ( i = 0 ; i < 10 ; i++ ) { - ip_socket = NET_IPSocket (ip->string, port + i); - if ( ip_socket ) { - Cvar_SetValue( "net_port", port + i ); - NET_GetLocalAddress(); - return; +/* +===================== +Sys_StringToAdr +===================== +*/ +qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr) { + struct hostent * h; + + memset(sadr, 0, sizeof(*sadr)); + + ((struct sockaddr_in *)sadr)->sin_family = AF_INET; + ((struct sockaddr_in *)sadr)->sin_port = 0; + + if (s[0] >= '0' && s[0] <= '9') { + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s); + } else { + if (( h = gethostbyname(s)) == 0 ) { + return 0; } + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; } - Com_Error (ERR_FATAL, "Couldn't allocate IP port"); + + return qtrue; } +/* +===================== +Sys_StringToAdr +===================== +*/ +qboolean Sys_StringToAdr (const char *s, netadr_t *a) { +#ifdef _WIN32 + struct sockaddr sadr; + + if (! Sys_StringToSockaddr(s, &sadr)) { + return qfalse; + } +#else // Unix or similar + struct sockaddr_in sadr; + + if (! Sys_StringToSockaddr(s, (struct sockaddr *)&sadr)) { + return qfalse; + } +#endif // _WIN32 + SockadrToNetadr(&sadr, a); + return qtrue; +} /* -==================== -NET_Init -==================== +===================== +Sys_GetPacket + +Never called by the game logic, just the system event queing +===================== */ -void NET_Init (void) -{ - noudp = Cvar_Get ("net_noudp", "0", 0); - // open sockets - if (! noudp->value) { - NET_OpenIP (); +#ifdef _WIN32 +int recvfromCount; +#endif // _WIN32 + +qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message) { + int ret; + socklen_t fromlen; + int net_socket; + int protocol; + int err; +#ifdef _WIN32 + struct sockaddr from; +#else // Unix or similar + struct sockaddr_in from; +#endif // _WIN32 + + for (protocol = 0; protocol < 2; protocol++) { + if (protocol == 0) { + net_socket = ip_socket; + } + + if (! net_socket) { + continue; + } + + fromlen = sizeof(from); +#ifdef _WIN32 + recvfromCount++; // performance check +#endif // _WIN32 + ret = recvfrom (net_socket, net_message->data, + net_message->maxsize, 0, (struct sockaddr *)&from, + &fromlen); + +#ifdef _WIN32 + if (ret == SOCKET_ERROR) { + err = WSAGetLastError(); + + if (err == WSAEWOULDBLOCK || err == WSAECONNRESET) { + continue; + } + Com_Printf("NET_GetPacket: %s\n", NET_ErrorString()); + continue; + } + + if (net_socket == ip_socket) { + memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 ); + } + + if (usingSocks && net_socket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0) { + if ( ret < 10 || net_message->data[0] != 0 + || net_message->data[1] != 0 + || net_message->data[2] != 0 + || net_message->data[3] != 1 ) { + continue; + } + net_from->type = NA_IP; + net_from->ip[0] = net_message->data[4]; + net_from->ip[1] = net_message->data[5]; + net_from->ip[2] = net_message->data[6]; + net_from->ip[3] = net_message->data[7]; + net_from->port = *(short *)&net_message->data[8]; + net_message->readcount = 10; + } else { + SockadrToNetadr( &from, net_from ); + net_message->readcount = 0; + } + +#else // Unix or similar + //============================ + // FIXME: why does this code come + // before if()s in Unix branch, + // but after if()s in Win branch? + //============================ + SockadrToNetadr (&from, net_from); + // bk000305: was missing + net_message->readcount = 0; + // END FIXME + + if (ret == -1) { + err = errno; + + if (err == EWOULDBLOCK || err == ECONNREFUSED) { + continue; + } + Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(), + NET_AdrToString(*net_from)); + continue; + } +#endif // _WIN32 + if (ret == net_message->maxsize) { + Com_Printf("Oversize packet from %s\n", NET_AdrToString (*net_from)); + continue; + } + + net_message->cursize = ret; + return qtrue; } + + return qfalse; } - /* -==================== -NET_IPSocket -==================== +===================== +Sys_SendPacket +===================== */ -int NET_IPSocket (char *net_interface, int port) -{ - int newsocket; - struct sockaddr_in address; - qboolean _qtrue = qtrue; - int i = 1; +#ifdef _WIN32 +static char socksBuf[4096]; +#endif // _WIN32 +void Sys_SendPacket (int length, const void *data, netadr_t to) { + int ret; +#ifdef _WIN32 + struct sockaddr addr; + SOCKET net_socket; +#else // Unix or similar + struct sockaddr_in addr; + int net_socket; +#endif // _WIN32 + if (to.type == NA_BROADCAST) { + net_socket = ip_socket; + } else if (to.type == NA_IP) { + net_socket = ip_socket; + } else { + Com_Error(ERR_FATAL, "Sys_SendPacket: bad address type"); + return; + } + + if (! net_socket) { + return; + } + + NetadrToSockadr(&to, &addr); - if ( net_interface ) { - Com_Printf("Opening IP socket: %s:%i\n", net_interface, port ); +#ifdef _WIN32 + if (usingSocks && to.type == NA_IP) { + socksBuf[0] = 0; // reserved + socksBuf[1] = 0; + socksBuf[2] = 0; // fragment (not fragmented) + socksBuf[3] = 1; // address type: IPV4 + *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr; + *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port; + memcpy( &socksBuf[10], data, length ); + ret = sendto(net_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr)); } else { - Com_Printf("Opening IP socket: localhost:%i\n", port ); + ret = sendto(net_socket, data, length, 0, &addr, sizeof(addr)); } + + if (ret == SOCKET_ERROR) { + int err = WSAGetLastError(); - if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - { - Com_Printf ("ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString()); - return 0; + // wouldblock is silent + if (err == WSAEWOULDBLOCK) { + return; + } + + // some PPP links do not allow broadcasts and return an error + if ((err == WSAEADDRNOTAVAIL) && (to.type == NA_BROADCAST)) { + return; + } + + Com_Printf( "NET_SendPacket: %s\n", NET_ErrorString() ); } +#else + ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); + if (ret == -1) { + Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), + NET_AdrToString (to)); + } +#endif // _WIN32 +} - // make it non-blocking - if (ioctl (newsocket, FIONBIO, &_qtrue) == -1) - { - Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString()); - return 0; +/* +===================== +Sys_IsLANAddress + +LAN clients will have their rate var ignored +===================== +*/ +qboolean Sys_IsLANAddress (netadr_t adr) { + int i; + + if (adr.type == NA_LOOPBACK) { + return qtrue; } - // make it broadcast capable - if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) - { - Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString()); - return 0; + if (adr.type != NA_IP) { + return qfalse; } - if (!net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost")) - address.sin_addr.s_addr = INADDR_ANY; - else - Sys_StringToSockaddr (net_interface, (struct sockaddr *)&address); + // RFC1918: + // 10.0.0.0 - 10.255.255.255 (10/8 prefix) + // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) + // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) + + // Internal Class A + if (adr.ip[0] == 10) { + return qtrue; + } + // Internal Class B + if (adr.ip[0] == 172 && (adr.ip[1]&0xf0) == 16) { + return qtrue; + } + // Internal Class C + if (adr.ip[0] == 192 && adr.ip[1] == 168) { + return qtrue; + } + // Loopback + if(adr.ip[0] == 127) { + return qtrue; + } - if (port == PORT_ANY) - address.sin_port = 0; - else - address.sin_port = htons((short)port); + // choose which comparison to use based on the class of the address being tested + // any local adresses of a different class than the address being tested will fail based on the first byte - address.sin_family = AF_INET; + // Class A + if ((adr.ip[0] & 0x80) == 0x00) { + for (i = 0 ; i < numIP ; i++) { + if( adr.ip[0] == localIP[i][0] ) { + return qtrue; + } + } + // the RFC1918 class a block will pass the above test + return qfalse; + } - if( bind (newsocket, (void *)&address, sizeof(address)) == -1) - { - Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); - close (newsocket); - return 0; + // Class B + if ((adr.ip[0] & 0xc0) == 0x80) { + for (i = 0 ; i < numIP ; i++) { + if (adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1]) { + return qtrue; + } + // also check against the RFC1918 class b blocks + if (adr.ip[0] == 172 && localIP[i][0] == 172 + && (adr.ip[1] & 0xf0) == 16 + && (localIP[i][1] & 0xf0) == 16) { + return qtrue; + } + } + return qfalse; } - return newsocket; + // Class C + for (i = 0 ; i < numIP ; i++) { + if (adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] + && adr.ip[2] == localIP[i][2]) { + return qtrue; + } + // also check against the RFC1918 class c blocks + if (adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 + && localIP[i][1] == 168) { + return qtrue; + } + } + return qfalse; } /* -==================== -NET_Shutdown -==================== +===================== +Sys_ShowIP +===================== */ -void NET_Shutdown (void) -{ - if (ip_socket) { - close(ip_socket); - ip_socket = 0; +void Sys_ShowIP (void) { + int i; + + for (i = 0; i < numIP; i++) { + Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] ); } } +#ifdef _WIN32 +/* +===================== +NET_Config +===================== +*/ +void NET_Config (qboolean enableNetworking) { + qboolean modified; + qboolean stop; + qboolean start; + // get any latched changes to cvars + modified = NET_GetCvars(); + + if (net_noudp->integer) { + enableNetworking = qfalse; + } + + // if enable state is the same and no cvars were modified, we have nothing to do + if( enableNetworking == networkingEnabled && !modified ) { + return; + } + + if( enableNetworking == networkingEnabled ) { + if( enableNetworking ) { + stop = qtrue; + start = qtrue; + } + else { + stop = qfalse; + start = qfalse; + } + } + else { + if( enableNetworking ) { + stop = qfalse; + start = qtrue; + } + else { + stop = qtrue; + start = qfalse; + } + networkingEnabled = enableNetworking; + } + + if( stop ) { + if ( ip_socket && ip_socket != INVALID_SOCKET ) { + closesocket( ip_socket ); + ip_socket = 0; + } + + if ( socks_socket && socks_socket != INVALID_SOCKET ) { + closesocket( socks_socket ); + socks_socket = 0; + } + } + + if( start ) { + if (! net_noudp->integer ) { + NET_OpenIP(); + } + } +} + /* -==================== -NET_ErrorString -==================== +===================== +NET_GetCvars +===================== */ -char *NET_ErrorString (void) -{ - int code; +static qboolean NET_GetCvars (void) { + qboolean modified = qfalse; - code = errno; - return strerror (code); + if( net_noudp && net_noudp->modified ) { + modified = qtrue; + } + net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE ); + + if( net_socksEnabled && net_socksEnabled->modified ) { + modified = qtrue; + } + net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE ); + + if( net_socksServer && net_socksServer->modified ) { + modified = qtrue; + } + net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE ); + + if( net_socksPort && net_socksPort->modified ) { + modified = qtrue; + } + net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE ); + + if( net_socksUsername && net_socksUsername->modified ) { + modified = qtrue; + } + net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE ); + + if( net_socksPassword && net_socksPassword->modified ) { + modified = qtrue; + } + net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE ); + + + return modified; } -// sleeps msec or until net socket is ready -void NET_Sleep(int msec) -{ - struct timeval timeout; - fd_set fdset; - extern qboolean stdin_active; - int highestfd = 0; +/* +===================== +NET_OpenSocks +===================== +*/ +void NET_OpenSocks (int port) { + struct sockaddr_in address; + int err; + struct hostent * h; + int len; + qboolean rfc1929; + unsigned char buf[64]; - if (!com_dedicated->integer) - return; // we're not a server, just run full speed + usingSocks = qfalse; - FD_ZERO(&fdset); - if (stdin_active) - { - FD_SET(0, &fdset); // stdin is processed too - highestfd = 1; + Com_Printf( "Opening connection to SOCKS server.\n" ); + + if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) { + err = WSAGetLastError(); + Com_Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() ); + return; } - if(ip_socket) - { - FD_SET(ip_socket, &fdset); // network socket - if(ip_socket >= highestfd) - highestfd = ip_socket + 1; + + h = gethostbyname( net_socksServer->string ); + if ( h == NULL ) { + err = WSAGetLastError(); + Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() ); + return; } - - if(highestfd) - { - if(msec >= 0) - { - timeout.tv_sec = msec/1000; - timeout.tv_usec = (msec%1000)*1000; - select(highestfd, &fdset, NULL, NULL, &timeout); + if ( h->h_addrtype != AF_INET ) { + Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" ); + return; + } + address.sin_family = AF_INET; + address.sin_addr.s_addr = *(int *)h->h_addr_list[0]; + address.sin_port = htons( (short)net_socksPort->integer ); + + if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() ); + return; + } + + // send socks authentication handshake + if ( *net_socksUsername->string || *net_socksPassword->string ) { + rfc1929 = qtrue; + } + else { + rfc1929 = qfalse; + } + + buf[0] = 5; // SOCKS version + // method count + if ( rfc1929 ) { + buf[1] = 2; + len = 4; + } + else { + buf[1] = 1; + len = 3; + } + buf[2] = 0; // method #1 - method id #00: no authentication + if ( rfc1929 ) { + buf[2] = 2; // method #2 - method id #02: username/password + } + if ( send( socks_socket, buf, len, 0 ) == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); + return; + } + + // get the response + len = recv( socks_socket, buf, 64, 0 ); + if ( len == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); + return; + } + if ( len != 2 || buf[0] != 5 ) { + Com_Printf( "NET_OpenSocks: bad response\n" ); + return; + } + switch( buf[1] ) { + case 0: // no authentication + break; + case 2: // username/password authentication + break; + default: + Com_Printf( "NET_OpenSocks: request denied\n" ); + return; + } + + // do username/password authentication if needed + if ( buf[1] == 2 ) { + int ulen; + int plen; + + // build the request + ulen = strlen( net_socksUsername->string ); + plen = strlen( net_socksPassword->string ); + + buf[0] = 1; // username/password authentication version + buf[1] = ulen; + if ( ulen ) { + memcpy( &buf[2], net_socksUsername->string, ulen ); } - else - { - // Block indefinitely - select(highestfd, &fdset, NULL, NULL, NULL); + buf[2 + ulen] = plen; + if ( plen ) { + memcpy( &buf[3 + ulen], net_socksPassword->string, plen ); } + + // send it + if ( send( socks_socket, buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); + return; + } + + // get the response + len = recv( socks_socket, buf, 64, 0 ); + if ( len == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); + return; + } + if ( len != 2 || buf[0] != 1 ) { + Com_Printf( "NET_OpenSocks: bad response\n" ); + return; + } + if ( buf[1] != 0 ) { + Com_Printf( "NET_OpenSocks: authentication failed\n" ); + return; + } } + + // send the UDP associate request + buf[0] = 5; // SOCKS version + buf[1] = 3; // command: UDP associate + buf[2] = 0; // reserved + buf[3] = 1; // address type: IPV4 + *(int *)&buf[4] = INADDR_ANY; + *(short *)&buf[8] = htons( (short)port ); // port + if ( send( socks_socket, buf, 10, 0 ) == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); + return; + } + + // get the response + len = recv( socks_socket, buf, 64, 0 ); + if( len == SOCKET_ERROR ) { + err = WSAGetLastError(); + Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); + return; + } + if( len < 2 || buf[0] != 5 ) { + Com_Printf( "NET_OpenSocks: bad response\n" ); + return; + } + // check completion code + if( buf[1] != 0 ) { + Com_Printf( "NET_OpenSocks: request denied: %i\n", buf[1] ); + return; + } + if( buf[3] != 1 ) { + Com_Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] ); + return; + } + ((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4]; + ((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8]; + memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 ); + + usingSocks = qtrue; } +/* +===================== +NET_Restart +===================== +*/ +void NET_Restart (void) { + NET_Config(networkingEnabled); +} + +#endif // _WIN32 Index: code/win32/win_local.h =================================================================== --- code/win32/win_local.h (revision 1121) +++ code/win32/win_local.h (working copy) @@ -36,7 +36,7 @@ #include #include #include -#include +#include // FIXME: remove ipx remnants #include void IN_MouseEvent (int mstate); Index: code/qcommon/net_chan.c =================================================================== --- code/qcommon/net_chan.c (revision 1121) +++ code/qcommon/net_chan.c (working copy) @@ -482,12 +482,12 @@ return qfalse; } - if (a.type == NA_IPX) +/* if (a.type == NA_IPX) { if ((memcmp(a.ipx, b.ipx, 10) == 0)) return qtrue; return qfalse; - } + }*/ // FIXME: remove IPX remnants Com_Printf ("NET_CompareBaseAdr: bad address type\n"); @@ -507,7 +507,7 @@ a.ip[0], a.ip[1], a.ip[2], a.ip[3], BigShort(a.port)); } else { Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x:%hu", - a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], + a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], // FIXME: remove ipx remnants BigShort(a.port)); } @@ -530,12 +530,12 @@ return qfalse; } - if (a.type == NA_IPX) +/* if (a.type == NA_IPX) { if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port) return qtrue; return qfalse; - } + }*/ // FIXME: remove IPX remnants Com_Printf ("NET_CompareAdr: bad address type\n"); return qfalse; Index: code/qcommon/qcommon.h =================================================================== --- code/qcommon/qcommon.h (revision 1121) +++ code/qcommon/qcommon.h (working copy) @@ -137,7 +137,7 @@ NA_LOOPBACK, NA_BROADCAST, NA_IP, - NA_IPX, + NA_IPX, // FIXME: remove IPX remnants NA_BROADCAST_IPX } netadrtype_t; @@ -150,7 +150,8 @@ netadrtype_t type; byte ip[4]; - byte ipx[10]; + byte ipx[10]; // FIXME: remove IPX remnants + // can we easily remove this? unsigned short port; } netadr_t; Index: code/ui/ui_main.c =================================================================== --- code/ui/ui_main.c (revision 1121) +++ code/ui/ui_main.c (working copy) @@ -116,7 +116,7 @@ static char* netnames[] = { "???", "UDP", - "IPX", +// "IPX", // FIXME: remove ipx remnants NULL }; Index: code/client/cl_main.c =================================================================== --- code/client/cl_main.c (revision 1121) +++ code/client/cl_main.c (working copy) @@ -2867,11 +2867,11 @@ type = 1; break; - case NA_IPX: +/* case NA_IPX: // FIXME: remove IPX remnants case NA_BROADCAST_IPX: str = "ipx"; type = 2; - break; + break;*/ default: str = "???"; @@ -3161,8 +3161,9 @@ to.type = NA_BROADCAST; NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); - to.type = NA_BROADCAST_IPX; - NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); +/* to.type = NA_BROADCAST_IPX; + NET_SendPacket( NS_CLIENT, strlen( message ), message, to );*/ + // FIXME: remove ipx remnants } } }