|
|
@ -13,7 +13,24 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
GNU General Public License for more details. |
|
|
|
GNU General Public License for more details. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
// Winsock
|
|
|
|
#include <winsock.h> |
|
|
|
#include <winsock.h> |
|
|
|
|
|
|
|
#include <wsipx.h> |
|
|
|
|
|
|
|
#define socklen_t int //#include <ws2tcpip.h>
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
// BSD sockets
|
|
|
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
|
|
|
#include <sys/socket.h> |
|
|
|
|
|
|
|
#include <sys/ioctl.h> |
|
|
|
|
|
|
|
#include <sys/select.h> |
|
|
|
|
|
|
|
#include <netinet/in.h> |
|
|
|
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
|
|
|
#include <netdb.h> |
|
|
|
|
|
|
|
// Errors handling
|
|
|
|
|
|
|
|
#include <errno.h> |
|
|
|
|
|
|
|
#include <fcntl.h> |
|
|
|
|
|
|
|
#endif |
|
|
|
#include "common.h" |
|
|
|
#include "common.h" |
|
|
|
#include "netchan.h" |
|
|
|
#include "netchan.h" |
|
|
|
#include "mathlib.h" |
|
|
|
#include "mathlib.h" |
|
|
@ -28,6 +45,11 @@ GNU General Public License for more details. |
|
|
|
#define SPLIT_SIZE ( MAX_ROUTEABLE_PACKET - sizeof( SPLITPACKET )) |
|
|
|
#define SPLIT_SIZE ( MAX_ROUTEABLE_PACKET - sizeof( SPLITPACKET )) |
|
|
|
#define NET_MAX_FRAGMENTS ( NET_MAX_FRAGMENT / SPLIT_SIZE ) |
|
|
|
#define NET_MAX_FRAGMENTS ( NET_MAX_FRAGMENT / SPLIT_SIZE ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 // it seems we need to use WS2 to support it
|
|
|
|
|
|
|
|
#define HAVE_GETADDRINFO |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
// wsock32.dll exports
|
|
|
|
// wsock32.dll exports
|
|
|
|
static int (_stdcall *pWSACleanup)( void ); |
|
|
|
static int (_stdcall *pWSACleanup)( void ); |
|
|
|
static word (_stdcall *pNtohs)( word netshort ); |
|
|
|
static word (_stdcall *pNtohs)( word netshort ); |
|
|
@ -81,6 +103,69 @@ static dllfunc_t winsock_funcs[] = |
|
|
|
|
|
|
|
|
|
|
|
dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false }; |
|
|
|
dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static dllfunc_t kernel32_funcs[] = |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
{ "InitializeCriticalSection", (void **) &pInitializeCriticalSection }, |
|
|
|
|
|
|
|
{ "EnterCriticalSection", (void **) &pEnterCriticalSection }, |
|
|
|
|
|
|
|
{ "LeaveCriticalSection", (void **) &pLeaveCriticalSection }, |
|
|
|
|
|
|
|
{ "DeleteCriticalSection", (void **) &pDeleteCriticalSection }, |
|
|
|
|
|
|
|
{ NULL, NULL } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dll_info_t kernel32_dll = { "kernel32.dll", kernel32_funcs, false }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void NET_InitializeCriticalSections( void ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qboolean NET_OpenWinSock( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( Sys_LoadLibrary( &kernel32_dll ) ) |
|
|
|
|
|
|
|
NET_InitializeCriticalSections(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// initialize the Winsock function vectors (we do this instead of statically linking
|
|
|
|
|
|
|
|
// so we can run on Win 3.1, where there isn't necessarily Winsock)
|
|
|
|
|
|
|
|
return Sys_LoadLibrary( &winsock_dll ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void NET_FreeWinSock( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Sys_FreeLibrary( &winsock_dll ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define pHtons htons |
|
|
|
|
|
|
|
#define pConnect connect |
|
|
|
|
|
|
|
#define pInet_Addr inet_addr |
|
|
|
|
|
|
|
#define pRecvFrom recvfrom |
|
|
|
|
|
|
|
#define pSendTo sendto |
|
|
|
|
|
|
|
#define pSocket socket |
|
|
|
|
|
|
|
#define pIoctlSocket ioctl |
|
|
|
|
|
|
|
#define pCloseSocket close |
|
|
|
|
|
|
|
#define pSetSockopt setsockopt |
|
|
|
|
|
|
|
#define pBind bind |
|
|
|
|
|
|
|
#define pGetHostName gethostname |
|
|
|
|
|
|
|
#define pGetSockName getsockname |
|
|
|
|
|
|
|
#define pGetHs |
|
|
|
|
|
|
|
#define pRecv recv |
|
|
|
|
|
|
|
#define pSend send |
|
|
|
|
|
|
|
#define pInet_Ntoa inet_ntoa |
|
|
|
|
|
|
|
#define pNtohs ntohs |
|
|
|
|
|
|
|
#define pGetHostByName gethostbyname |
|
|
|
|
|
|
|
#define pSelect select |
|
|
|
|
|
|
|
#define pGetAddrInfo getaddrinfo |
|
|
|
|
|
|
|
#define SOCKET int |
|
|
|
|
|
|
|
#define INVALID_SOCKET 0 |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __EMSCRIPTEN__ |
|
|
|
|
|
|
|
/* All socket operations are non-blocking already */ |
|
|
|
|
|
|
|
static int ioctl_stub( int d, unsigned long r, ...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#undef pIoctlSocket |
|
|
|
|
|
|
|
#define pIoctlSocket ioctl_stub |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
{ |
|
|
|
byte data[NET_MAX_MESSAGE]; |
|
|
|
byte data[NET_MAX_MESSAGE]; |
|
|
@ -132,10 +217,12 @@ typedef struct |
|
|
|
int split_flags[NET_MAX_FRAGMENTS]; |
|
|
|
int split_flags[NET_MAX_FRAGMENTS]; |
|
|
|
long sequence_number; |
|
|
|
long sequence_number; |
|
|
|
int ip_sockets[NS_COUNT]; |
|
|
|
int ip_sockets[NS_COUNT]; |
|
|
|
WSADATA winsockdata; |
|
|
|
|
|
|
|
qboolean initialized; |
|
|
|
qboolean initialized; |
|
|
|
qboolean configured; |
|
|
|
qboolean configured; |
|
|
|
qboolean allow_ip; |
|
|
|
qboolean allow_ip; |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
WSADATA winsockdata; |
|
|
|
|
|
|
|
#endif |
|
|
|
} net_state_t; |
|
|
|
} net_state_t; |
|
|
|
|
|
|
|
|
|
|
|
static net_state_t net; |
|
|
|
static net_state_t net; |
|
|
@ -150,34 +237,6 @@ static convar_t *net_address; |
|
|
|
convar_t *net_clockwindow; |
|
|
|
convar_t *net_clockwindow; |
|
|
|
netadr_t net_local; |
|
|
|
netadr_t net_local; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
==================== |
|
|
|
|
|
|
|
NET_OpenWinSock |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
load wsock32.dll |
|
|
|
|
|
|
|
==================== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
qboolean NET_OpenWinSock( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// initialize the Winsock function vectors (we do this instead of statically linking
|
|
|
|
|
|
|
|
// so we can run on Win 3.1, where there isn't necessarily Winsock)
|
|
|
|
|
|
|
|
if( Sys_LoadLibrary( &winsock_dll )) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
==================== |
|
|
|
|
|
|
|
NET_FreeWinSock |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unload wsock32.dll |
|
|
|
|
|
|
|
==================== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
void NET_FreeWinSock( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Sys_FreeLibrary( &winsock_dll ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
==================== |
|
|
|
==================== |
|
|
|
NET_ErrorString |
|
|
|
NET_ErrorString |
|
|
@ -185,6 +244,7 @@ NET_ErrorString |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
char *NET_ErrorString( void ) |
|
|
|
char *NET_ErrorString( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
int err = WSANOTINITIALISED; |
|
|
|
int err = WSANOTINITIALISED; |
|
|
|
|
|
|
|
|
|
|
|
if( net.initialized ) |
|
|
|
if( net.initialized ) |
|
|
@ -238,6 +298,27 @@ char *NET_ErrorString( void ) |
|
|
|
case WSANO_DATA: return "WSANO_DATA"; |
|
|
|
case WSANO_DATA: return "WSANO_DATA"; |
|
|
|
default: return "NO ERROR"; |
|
|
|
default: return "NO ERROR"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return strerror( errno ); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_inline qboolean NET_IsSocketError( int retval ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
return retval == SOCKET_ERROR ? true : false; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return retval < 0 ? true : false; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_inline qboolean NET_IsSocketValid( int socket ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
return socket != INVALID_SOCKET; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return socket; |
|
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -278,6 +359,151 @@ static void NET_SockadrToNetadr( struct sockaddr *s, netadr_t *a ) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined XASH_NO_ASYNC_NS_RESOLVE && ( defined _WIN32 || !defined __EMSCRIPTEN__ ) |
|
|
|
|
|
|
|
#define CAN_ASYNC_NS_RESOLVE |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CAN_ASYNC_NS_RESOLVE |
|
|
|
|
|
|
|
static void NET_ResolveThread( void ); |
|
|
|
|
|
|
|
#if !defined _WIN32 |
|
|
|
|
|
|
|
#include <pthread.h> |
|
|
|
|
|
|
|
#define mutex_lock pthread_mutex_lock |
|
|
|
|
|
|
|
#define mutex_unlock pthread_mutex_unlock |
|
|
|
|
|
|
|
#define exit_thread( x ) pthread_exit(x) |
|
|
|
|
|
|
|
#define create_thread( pfn ) !pthread_create( &nsthread.thread, NULL, (pfn), NULL ) |
|
|
|
|
|
|
|
#define detach_thread( x ) pthread_detach(x) |
|
|
|
|
|
|
|
#define mutex_t pthread_mutex_t |
|
|
|
|
|
|
|
#define thread_t pthread_t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void *NET_ThreadStart( void *unused ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
NET_ResolveThread(); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else // WIN32
|
|
|
|
|
|
|
|
struct cs { |
|
|
|
|
|
|
|
void* p1; |
|
|
|
|
|
|
|
int i1, i2; |
|
|
|
|
|
|
|
void *p2, *p3; |
|
|
|
|
|
|
|
uint i4; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
#define mutex_lock pEnterCriticalSection |
|
|
|
|
|
|
|
#define mutex_unlock pLeaveCriticalSection |
|
|
|
|
|
|
|
#define detach_thread( x ) CloseHandle(x) |
|
|
|
|
|
|
|
#define create_thread( pfn ) nsthread.thread = CreateThread( NULL, 0, pfn, NULL, 0, NULL ) |
|
|
|
|
|
|
|
#define mutex_t struct cs |
|
|
|
|
|
|
|
#define thread_t HANDLE |
|
|
|
|
|
|
|
DWORD WINAPI NET_ThreadStart( LPVOID unused ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
NET_ResolveThread(); |
|
|
|
|
|
|
|
ExitThread(0); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_RESOLVE |
|
|
|
|
|
|
|
#define RESOLVE_DBG(x) Sys_PrintLog(x) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define RESOLVE_DBG(x) |
|
|
|
|
|
|
|
#endif // DEBUG_RESOLVE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct nsthread_s |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mutex_t mutexns; |
|
|
|
|
|
|
|
mutex_t mutexres; |
|
|
|
|
|
|
|
thread_t thread; |
|
|
|
|
|
|
|
int result; |
|
|
|
|
|
|
|
string hostname; |
|
|
|
|
|
|
|
qboolean busy; |
|
|
|
|
|
|
|
} nsthread |
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
|
|
|
= { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER } |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
static void NET_InitializeCriticalSections( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pInitializeCriticalSection( &nsthread.mutexns ); |
|
|
|
|
|
|
|
pInitializeCriticalSection( &nsthread.mutexres ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void NET_ResolveThread( void ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef HAVE_GETADDRINFO |
|
|
|
|
|
|
|
struct addrinfo *ai = NULL, *cur; |
|
|
|
|
|
|
|
struct addrinfo hints; |
|
|
|
|
|
|
|
int sin_addr = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] starting resolve for " ); |
|
|
|
|
|
|
|
RESOLVE_DBG( nsthread.hostname ); |
|
|
|
|
|
|
|
RESOLVE_DBG( " with getaddrinfo\n" ); |
|
|
|
|
|
|
|
memset( &hints, 0, sizeof( hints ) ); |
|
|
|
|
|
|
|
hints.ai_family = AF_INET; |
|
|
|
|
|
|
|
if( !pGetAddrInfo( nsthread.hostname, NULL, &hints, &ai ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( cur = ai; cur; cur = cur->ai_next ) { |
|
|
|
|
|
|
|
if( cur->ai_family == AF_INET ) { |
|
|
|
|
|
|
|
sin_addr = *((int*)&((struct sockaddr_in *)cur->ai_addr)->sin_addr); |
|
|
|
|
|
|
|
freeaddrinfo( ai ); |
|
|
|
|
|
|
|
ai = NULL; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( ai ) |
|
|
|
|
|
|
|
freeaddrinfo( ai ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( sin_addr ) |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] getaddrinfo success\n" ); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] getaddrinfo failed\n" ); |
|
|
|
|
|
|
|
mutex_lock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
nsthread.result = sin_addr; |
|
|
|
|
|
|
|
nsthread.busy = false; |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] returning result\n" ); |
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] exiting thread\n" ); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
struct hostent *res; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] starting resolve for " ); |
|
|
|
|
|
|
|
RESOLVE_DBG( nsthread.hostname ); |
|
|
|
|
|
|
|
RESOLVE_DBG( " with gethostbyname\n" ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock( &nsthread.mutexns ); |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] locked gethostbyname mutex\n" ); |
|
|
|
|
|
|
|
res = pGetHostByName( nsthread.hostname ); |
|
|
|
|
|
|
|
if(res) |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] gethostbyname success\n" ); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] gethostbyname failed\n" ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] returning result\n" ); |
|
|
|
|
|
|
|
if( res ) |
|
|
|
|
|
|
|
nsthread.result = *(int *)res->h_addr_list[0]; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nsthread.result = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nsthread.busy = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexns ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] unlocked gethostbyname mutex\n" ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RESOLVE_DBG( "[resolve thread] exiting thread\n" ); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // CAN_ASYNC_NS_RESOLVE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
============= |
|
|
|
============= |
|
|
|
NET_StringToAdr |
|
|
|
NET_StringToAdr |
|
|
@ -289,8 +515,9 @@ idnewt:28000 |
|
|
|
192.246.40.70:28000 |
|
|
|
192.246.40.70:28000 |
|
|
|
============= |
|
|
|
============= |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static qboolean NET_StringToSockaddr( const char *s, struct sockaddr *sadr ) |
|
|
|
static int NET_StringToSockaddr( const char *s, struct sockaddr *sadr, qboolean nonblocking ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
int ip = 0; |
|
|
|
char *colon; |
|
|
|
char *colon; |
|
|
|
char copy[128]; |
|
|
|
char copy[128]; |
|
|
|
|
|
|
|
|
|
|
@ -313,18 +540,137 @@ static qboolean NET_StringToSockaddr( const char *s, struct sockaddr *sadr ) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
((struct sockaddr_in *)sadr)->sin_addr.s_addr = pInet_Addr( copy ); |
|
|
|
if( copy[0] >= '0' && copy[0] <= '9' ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = pInet_Addr( copy ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef CAN_ASYNC_NS_RESOLVE |
|
|
|
|
|
|
|
qboolean asyncfailed = false; |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
if( pInitializeCriticalSection ) |
|
|
|
|
|
|
|
#endif // _WIN32
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( !nonblocking ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef HAVE_GETADDRINFO |
|
|
|
|
|
|
|
struct addrinfo *ai = NULL, *cur; |
|
|
|
|
|
|
|
struct addrinfo hints; |
|
|
|
|
|
|
|
|
|
|
|
if(((struct sockaddr_in *)sadr)->sin_addr.s_addr == INADDR_NONE ) |
|
|
|
memset( &hints, 0, sizeof( hints ) ); |
|
|
|
|
|
|
|
hints.ai_family = AF_INET; |
|
|
|
|
|
|
|
if( !pGetAddrInfo( copy, NULL, &hints, &ai ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( cur = ai; cur; cur = cur->ai_next ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( cur->ai_family == AF_INET ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct hostent *h = pGetHostByName( copy ); |
|
|
|
ip = *((int*)&((struct sockaddr_in *)cur->ai_addr)->sin_addr); |
|
|
|
|
|
|
|
freeaddrinfo(ai); |
|
|
|
|
|
|
|
ai = NULL; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( h == NULL || h->h_addr == NULL ) |
|
|
|
if( ai ) |
|
|
|
return false; |
|
|
|
freeaddrinfo(ai); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
struct hostent *h; |
|
|
|
|
|
|
|
|
|
|
|
((struct sockaddr_in *)sadr)->sin_addr.s_addr = *(uint *)h->h_addr; |
|
|
|
mutex_lock( &nsthread.mutexns ); |
|
|
|
|
|
|
|
h = pGetHostByName( copy ); |
|
|
|
|
|
|
|
if( !h ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexns ); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
ip = *(int *)h->h_addr_list[0]; |
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexns ); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mutex_lock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( nsthread.busy ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
return 2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !Q_strcmp( copy, nsthread.hostname ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ip = nsthread.result; |
|
|
|
|
|
|
|
nsthread.hostname[0] = 0; |
|
|
|
|
|
|
|
detach_thread( nsthread.thread ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Q_strncpy( nsthread.hostname, copy, MAX_STRING ); |
|
|
|
|
|
|
|
nsthread.busy = true; |
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( create_thread( NET_ThreadStart ) ) |
|
|
|
|
|
|
|
return 2; |
|
|
|
|
|
|
|
else // failed to create thread
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MsgDev( D_ERROR, "NET_StringToSockaddr: failed to create thread!\n"); |
|
|
|
|
|
|
|
nsthread.busy = false; |
|
|
|
|
|
|
|
asyncfailed = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_unlock( &nsthread.mutexres ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
asyncfailed = true; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
if( asyncfailed ) |
|
|
|
|
|
|
|
#endif // _WIN32
|
|
|
|
|
|
|
|
#endif // CAN_ASYNC_NS_RESOLVE
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef HAVE_GETADDRINFO |
|
|
|
|
|
|
|
struct addrinfo *ai = NULL, *cur; |
|
|
|
|
|
|
|
struct addrinfo hints; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset( &hints, 0, sizeof( hints ) ); |
|
|
|
|
|
|
|
hints.ai_family = AF_INET; |
|
|
|
|
|
|
|
if( !pGetAddrInfo( copy, NULL, &hints, &ai ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( cur = ai; cur; cur = cur->ai_next ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( cur->ai_family == AF_INET ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ip = *((int*)&((struct sockaddr_in *)cur->ai_addr)->sin_addr); |
|
|
|
|
|
|
|
freeaddrinfo(ai); |
|
|
|
|
|
|
|
ai = NULL; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( ai ) |
|
|
|
|
|
|
|
freeaddrinfo(ai); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
struct hostent *h; |
|
|
|
|
|
|
|
if(!( h = pGetHostByName( copy ))) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
ip = *(int *)h->h_addr_list[0]; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !ip ) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = ip; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -477,20 +823,43 @@ qboolean NET_StringToAdr( const char *string, netadr_t *adr ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr s; |
|
|
|
struct sockaddr s; |
|
|
|
|
|
|
|
|
|
|
|
if( !Q_stricmp( string, "localhost" )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
memset( adr, 0, sizeof( netadr_t )); |
|
|
|
memset( adr, 0, sizeof( netadr_t )); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
adr->type = NA_LOOPBACK; |
|
|
|
adr->type = NA_LOOPBACK; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( !NET_StringToSockaddr( string, &s )) |
|
|
|
if( !NET_StringToSockaddr( string, &s, false )) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
NET_SockadrToNetadr( &s, adr ); |
|
|
|
NET_SockadrToNetadr( &s, adr ); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int NET_StringToAdrNB( const char *string, netadr_t *adr ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct sockaddr s; |
|
|
|
|
|
|
|
int res; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset( adr, 0, sizeof( netadr_t )); |
|
|
|
|
|
|
|
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
adr->type = NA_LOOPBACK; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res = NET_StringToSockaddr( string, &s, true ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( res == 0 || res == 2 ) |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NET_SockadrToNetadr( &s, adr ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
============================================================================= |
|
|
|
============================================================================= |
|
|
|
|
|
|
|
|
|
|
@ -758,7 +1127,7 @@ static qboolean NET_LagPacket( qboolean newdata, netsrc_t sock, netadr_t *from, |
|
|
|
|
|
|
|
|
|
|
|
Mem_Free( pPacket ); |
|
|
|
Mem_Free( pPacket ); |
|
|
|
|
|
|
|
|
|
|
|
return TRUE; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -858,7 +1227,7 @@ queue normal and lagged packets |
|
|
|
qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *length ) |
|
|
|
qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *length ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
byte buf[NET_MAX_FRAGMENT]; |
|
|
|
byte buf[NET_MAX_FRAGMENT]; |
|
|
|
int ret = SOCKET_ERROR; |
|
|
|
int ret; |
|
|
|
int net_socket; |
|
|
|
int net_socket; |
|
|
|
int addr_len; |
|
|
|
int addr_len; |
|
|
|
struct sockaddr addr; |
|
|
|
struct sockaddr addr; |
|
|
@ -867,12 +1236,12 @@ qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *len |
|
|
|
|
|
|
|
|
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
|
|
|
|
|
|
|
|
if( net_socket != INVALID_SOCKET ) |
|
|
|
if( NET_IsSocketValid( net_socket ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
addr_len = sizeof( addr ); |
|
|
|
addr_len = sizeof( addr ); |
|
|
|
ret = pRecvFrom( net_socket, buf, sizeof( buf ), 0, (struct sockaddr *)&addr, &addr_len ); |
|
|
|
ret = pRecvFrom( net_socket, buf, sizeof( buf ), 0, (struct sockaddr *)&addr, &addr_len ); |
|
|
|
|
|
|
|
|
|
|
|
if( ret != SOCKET_ERROR ) |
|
|
|
if( !NET_IsSocketError( ret ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
NET_SockadrToNetadr( &addr, from ); |
|
|
|
NET_SockadrToNetadr( &addr, from ); |
|
|
|
|
|
|
|
|
|
|
@ -898,6 +1267,7 @@ qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *len |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
int err = pWSAGetLastError(); |
|
|
|
int err = pWSAGetLastError(); |
|
|
|
|
|
|
|
|
|
|
|
switch( err ) |
|
|
|
switch( err ) |
|
|
@ -911,6 +1281,19 @@ qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *len |
|
|
|
MsgDev( D_ERROR, "NET_QueuePacket: %s from %s\n", NET_ErrorString(), NET_AdrToString( *from )); |
|
|
|
MsgDev( D_ERROR, "NET_QueuePacket: %s from %s\n", NET_ErrorString(), NET_AdrToString( *from )); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
switch( errno ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case EWOULDBLOCK: |
|
|
|
|
|
|
|
case ECONNRESET: |
|
|
|
|
|
|
|
case ECONNREFUSED: |
|
|
|
|
|
|
|
case EMSGSIZE: |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: // let's continue even after errors
|
|
|
|
|
|
|
|
MsgDev( D_ERROR, "NET_QueuePacket: %s from %s\n", NET_ErrorString(), NET_AdrToString( *from )); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1026,13 +1409,13 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to |
|
|
|
else if( to.type == NA_BROADCAST ) |
|
|
|
else if( to.type == NA_BROADCAST ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
if( net_socket == INVALID_SOCKET ) |
|
|
|
if( !NET_IsSocketValid( net_socket ) ) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else if( to.type == NA_IP ) |
|
|
|
else if( to.type == NA_IP ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
net_socket = net.ip_sockets[sock]; |
|
|
|
if( net_socket == INVALID_SOCKET ) |
|
|
|
if( !NET_IsSocketValid( net_socket ) ) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -1044,8 +1427,10 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to |
|
|
|
|
|
|
|
|
|
|
|
ret = NET_SendLong( sock, net_socket, data, length, 0, &addr, sizeof( addr )); |
|
|
|
ret = NET_SendLong( sock, net_socket, data, length, 0, &addr, sizeof( addr )); |
|
|
|
|
|
|
|
|
|
|
|
if( ret == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( err )) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
err = pWSAGetLastError(); |
|
|
|
err = pWSAGetLastError(); |
|
|
|
|
|
|
|
|
|
|
|
// WSAEWOULDBLOCK is silent
|
|
|
|
// WSAEWOULDBLOCK is silent
|
|
|
@ -1055,13 +1440,25 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to |
|
|
|
// some PPP links don't allow broadcasts
|
|
|
|
// some PPP links don't allow broadcasts
|
|
|
|
if( err == WSAEADDRNOTAVAIL && to.type == NA_BROADCAST ) |
|
|
|
if( err == WSAEADDRNOTAVAIL && to.type == NA_BROADCAST ) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
// WSAEWOULDBLOCK is silent
|
|
|
|
|
|
|
|
if( errno == EWOULDBLOCK ) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
// let dedicated servers continue after errors
|
|
|
|
// some PPP links don't allow broadcasts
|
|
|
|
|
|
|
|
if( errno == EADDRNOTAVAIL && to.type == NA_BROADCAST ) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
if( host.type == HOST_DEDICATED ) |
|
|
|
if( host.type == HOST_DEDICATED ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_ERROR, "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
MsgDev( D_ERROR, "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
else if( err == WSAEADDRNOTAVAIL || err == WSAENOBUFS ) |
|
|
|
else if( err == WSAEADDRNOTAVAIL || err == WSAENOBUFS ) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
else if( err == EADDRNOTAVAIL || err == ENOBUFS ) |
|
|
|
|
|
|
|
#endif |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_ERROR, "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
MsgDev( D_ERROR, "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
} |
|
|
|
} |
|
|
@ -1070,6 +1467,7 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to |
|
|
|
Host_Error( "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
Host_Error( "NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString( to )); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -1141,36 +1539,41 @@ NET_IPSocket |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static int NET_IPSocket( const char *net_interface, int port, qboolean multicast ) |
|
|
|
static int NET_IPSocket( const char *net_interface, int port, qboolean multicast ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
struct sockaddr_in addr; |
|
|
|
int err, net_socket; |
|
|
|
int err, net_socket; |
|
|
|
uint optval = 1; |
|
|
|
uint optval = 1; |
|
|
|
struct sockaddr_in addr; |
|
|
|
dword _true = 1; |
|
|
|
|
|
|
|
|
|
|
|
if(( net_socket = pSocket( PF_INET, SOCK_DGRAM, IPPROTO_UDP )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError(( net_socket = pSocket( PF_INET, SOCK_DGRAM, IPPROTO_UDP )) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
err = pWSAGetLastError(); |
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
int err = pWSAGetLastError(); |
|
|
|
if( err != WSAEAFNOSUPPORT ) |
|
|
|
if( err != WSAEAFNOSUPPORT ) |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d socket: %s\n", port, NET_ErrorString( )); |
|
|
|
#else |
|
|
|
|
|
|
|
if( err != EAFNOSUPPORT ) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: socket = %s\n", NET_ErrorString( )); |
|
|
|
return INVALID_SOCKET; |
|
|
|
return INVALID_SOCKET; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( pIoctlSocket( net_socket, FIONBIO, &optval ) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pIoctlSocket( net_socket, FIONBIO, &_true ) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d ioctl FIONBIO: %s\n", port, NET_ErrorString( )); |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: ioctlsocket FIONBIO = %s\n", NET_ErrorString( )); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
return INVALID_SOCKET; |
|
|
|
return INVALID_SOCKET; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// make it broadcast capable
|
|
|
|
// make it broadcast capable
|
|
|
|
if( pSetSockopt( net_socket, SOL_SOCKET, SO_BROADCAST, (const char *)&optval, sizeof( optval )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pSetSockopt( net_socket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof( _true ) ) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d setsockopt SO_BROADCAST: %s\n", port, NET_ErrorString( )); |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: setsockopt SO_BROADCAST = %s\n", NET_ErrorString( )); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
return INVALID_SOCKET; |
|
|
|
return INVALID_SOCKET; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( Sys_CheckParm( "-reuse" ) || multicast ) |
|
|
|
if( Sys_CheckParm( "-reuse" ) || multicast ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if( pSetSockopt( net_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( optval )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pSetSockopt( net_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( optval )) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d setsockopt SO_REUSEADDR: %s\n", port, NET_ErrorString( )); |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d setsockopt SO_REUSEADDR: %s\n", port, NET_ErrorString( )); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
pCloseSocket( net_socket ); |
|
|
@ -1183,10 +1586,14 @@ static int NET_IPSocket( const char *net_interface, int port, qboolean multicast |
|
|
|
optval = 16; |
|
|
|
optval = 16; |
|
|
|
Con_Printf( "Enabling LOWDELAY TOS option\n" ); |
|
|
|
Con_Printf( "Enabling LOWDELAY TOS option\n" ); |
|
|
|
|
|
|
|
|
|
|
|
if( pSetSockopt( net_socket, IPPROTO_IP, IP_TOS, (const char *)&optval, sizeof( optval )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pSetSockopt( net_socket, IPPROTO_IP, IP_TOS, (const char *)&optval, sizeof( optval )) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
err = pWSAGetLastError(); |
|
|
|
err = pWSAGetLastError(); |
|
|
|
if( err != WSAENOPROTOOPT ) |
|
|
|
if( err != WSAENOPROTOOPT ) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
if( errno != ENOPROTOOPT ) |
|
|
|
|
|
|
|
#endif |
|
|
|
Con_Printf( S_WARN "NET_UDPSocket: port: %d setsockopt IP_TOS: %s\n", port, NET_ErrorString( )); |
|
|
|
Con_Printf( S_WARN "NET_UDPSocket: port: %d setsockopt IP_TOS: %s\n", port, NET_ErrorString( )); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
return INVALID_SOCKET; |
|
|
|
return INVALID_SOCKET; |
|
|
@ -1195,14 +1602,14 @@ static int NET_IPSocket( const char *net_interface, int port, qboolean multicast |
|
|
|
|
|
|
|
|
|
|
|
if( !net_interface[0] || !Q_stricmp( net_interface, "localhost" )) |
|
|
|
if( !net_interface[0] || !Q_stricmp( net_interface, "localhost" )) |
|
|
|
addr.sin_addr.s_addr = INADDR_ANY; |
|
|
|
addr.sin_addr.s_addr = INADDR_ANY; |
|
|
|
else NET_StringToSockaddr( net_interface, (struct sockaddr *)&addr ); |
|
|
|
else NET_StringToSockaddr( net_interface, (struct sockaddr *)&addr, false ); |
|
|
|
|
|
|
|
|
|
|
|
if( port == PORT_ANY ) addr.sin_port = 0; |
|
|
|
if( port == PORT_ANY ) addr.sin_port = 0; |
|
|
|
else addr.sin_port = pHtons((short)port); |
|
|
|
else addr.sin_port = pHtons((short)port); |
|
|
|
|
|
|
|
|
|
|
|
addr.sin_family = AF_INET; |
|
|
|
addr.sin_family = AF_INET; |
|
|
|
|
|
|
|
|
|
|
|
if( pBind( net_socket, (void *)&addr, sizeof( addr )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pBind( net_socket, (void *)&addr, sizeof( addr )) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d bind: %s\n", port, NET_ErrorString( )); |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port: %d bind: %s\n", port, NET_ErrorString( )); |
|
|
|
pCloseSocket( net_socket ); |
|
|
|
pCloseSocket( net_socket ); |
|
|
@ -1212,7 +1619,7 @@ static int NET_IPSocket( const char *net_interface, int port, qboolean multicast |
|
|
|
if( Sys_CheckParm( "-loopback" )) |
|
|
|
if( Sys_CheckParm( "-loopback" )) |
|
|
|
{ |
|
|
|
{ |
|
|
|
optval = 1; |
|
|
|
optval = 1; |
|
|
|
if( pSetSockopt( net_socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&optval, sizeof( optval )) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pSetSockopt( net_socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&optval, sizeof( optval )) ) ) |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port %d setsockopt IP_MULTICAST_LOOP: %s\n", port, NET_ErrorString( )); |
|
|
|
MsgDev( D_WARN, "NET_UDPSocket: port %d setsockopt IP_MULTICAST_LOOP: %s\n", port, NET_ErrorString( )); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1228,14 +1635,14 @@ static void NET_OpenIP( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int port, sv_port = 0, cl_port = 0; |
|
|
|
int port, sv_port = 0, cl_port = 0; |
|
|
|
|
|
|
|
|
|
|
|
if( net.ip_sockets[NS_SERVER] == INVALID_SOCKET ) |
|
|
|
if( !NET_IsSocketValid( net.ip_sockets[NS_SERVER] ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
port = net_iphostport->value; |
|
|
|
port = net_iphostport->value; |
|
|
|
if( !port ) port = net_hostport->value; |
|
|
|
if( !port ) port = net_hostport->value; |
|
|
|
if( !port ) port = PORT_SERVER; // forcing to default
|
|
|
|
if( !port ) port = PORT_SERVER; // forcing to default
|
|
|
|
net.ip_sockets[NS_SERVER] = NET_IPSocket( net_ipname->string, port, false ); |
|
|
|
net.ip_sockets[NS_SERVER] = NET_IPSocket( net_ipname->string, port, false ); |
|
|
|
|
|
|
|
|
|
|
|
if( net.ip_sockets[NS_SERVER] == INVALID_SOCKET && host.type == HOST_DEDICATED ) |
|
|
|
if( !NET_IsSocketValid( net.ip_sockets[NS_SERVER] ) && host.type == HOST_DEDICATED ) |
|
|
|
Host_Error( "Couldn't allocate dedicated server IP port %d.\n", port ); |
|
|
|
Host_Error( "Couldn't allocate dedicated server IP port %d.\n", port ); |
|
|
|
sv_port = port; |
|
|
|
sv_port = port; |
|
|
|
} |
|
|
|
} |
|
|
@ -1243,14 +1650,14 @@ static void NET_OpenIP( void ) |
|
|
|
// dedicated servers don't need client ports
|
|
|
|
// dedicated servers don't need client ports
|
|
|
|
if( host.type == HOST_DEDICATED ) return; |
|
|
|
if( host.type == HOST_DEDICATED ) return; |
|
|
|
|
|
|
|
|
|
|
|
if( net.ip_sockets[NS_CLIENT] == INVALID_SOCKET ) |
|
|
|
if( !NET_IsSocketValid( net.ip_sockets[NS_CLIENT] ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
port = net_ipclientport->value; |
|
|
|
port = net_ipclientport->value; |
|
|
|
if( !port ) port = net_clientport->value; |
|
|
|
if( !port ) port = net_clientport->value; |
|
|
|
if( !port ) port = PORT_ANY; // forcing to default
|
|
|
|
if( !port ) port = PORT_ANY; // forcing to default
|
|
|
|
net.ip_sockets[NS_CLIENT] = NET_IPSocket( net_ipname->string, port, false ); |
|
|
|
net.ip_sockets[NS_CLIENT] = NET_IPSocket( net_ipname->string, port, false ); |
|
|
|
|
|
|
|
|
|
|
|
if( net.ip_sockets[NS_CLIENT] == INVALID_SOCKET ) |
|
|
|
if( !NET_IsSocketValid( net.ip_sockets[NS_CLIENT] ) ) |
|
|
|
net.ip_sockets[NS_CLIENT] = NET_IPSocket( net_ipname->string, PORT_ANY, false ); |
|
|
|
net.ip_sockets[NS_CLIENT] = NET_IPSocket( net_ipname->string, PORT_ANY, false ); |
|
|
|
cl_port = port; |
|
|
|
cl_port = port; |
|
|
|
} |
|
|
|
} |
|
|
@ -1291,7 +1698,7 @@ void NET_GetLocalAddress( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
namelen = sizeof( address ); |
|
|
|
namelen = sizeof( address ); |
|
|
|
|
|
|
|
|
|
|
|
if( pGetSockName( net.ip_sockets[NS_SERVER], (struct sockaddr *)&address, &namelen ) == SOCKET_ERROR ) |
|
|
|
if( NET_IsSocketError( pGetSockName( net.ip_sockets[NS_SERVER], (struct sockaddr *)&address, &namelen ) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// this may happens if multiple clients running on single machine
|
|
|
|
// this may happens if multiple clients running on single machine
|
|
|
|
MsgDev( D_ERROR, "Could not get TCP/IP address. Reason: %s\n", NET_ErrorString( )); |
|
|
|
MsgDev( D_ERROR, "Could not get TCP/IP address. Reason: %s\n", NET_ErrorString( )); |
|
|
@ -1461,6 +1868,7 @@ void NET_Init( void ) |
|
|
|
net.ip_sockets[i] = INVALID_SOCKET; |
|
|
|
net.ip_sockets[i] = INVALID_SOCKET; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
if( !NET_OpenWinSock( )) // loading wsock32.dll
|
|
|
|
if( !NET_OpenWinSock( )) // loading wsock32.dll
|
|
|
|
{ |
|
|
|
{ |
|
|
|
MsgDev( D_ERROR, "network failed to load wsock32.dll.\n" ); |
|
|
|
MsgDev( D_ERROR, "network failed to load wsock32.dll.\n" ); |
|
|
@ -1473,6 +1881,7 @@ void NET_Init( void ) |
|
|
|
NET_FreeWinSock(); |
|
|
|
NET_FreeWinSock(); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if( Sys_CheckParm( "-noip" )) |
|
|
|
if( Sys_CheckParm( "-noip" )) |
|
|
|
net.allow_ip = false; |
|
|
|
net.allow_ip = false; |
|
|
@ -1505,7 +1914,9 @@ void NET_Shutdown( void ) |
|
|
|
NET_ClearLagData( true, true ); |
|
|
|
NET_ClearLagData( true, true ); |
|
|
|
|
|
|
|
|
|
|
|
NET_Config( false ); |
|
|
|
NET_Config( false ); |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
pWSACleanup(); |
|
|
|
pWSACleanup(); |
|
|
|
NET_FreeWinSock(); |
|
|
|
NET_FreeWinSock(); |
|
|
|
|
|
|
|
#endif |
|
|
|
net.initialized = false; |
|
|
|
net.initialized = false; |
|
|
|
} |
|
|
|
} |