2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2010-02-15 23:26:55 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2010-06-21 12:27:30 +00:00
2010-08-14 20:55:39 +00:00
# include "q_stdinc.h"
* Makefile, Makefile.darwin, Makefile.w32, Makefile.w64: Build changes:
The SDL_net driver is now disabled by default and platform-specific network
drivers will be used. To compile for SDL_net, a command like "make SDLNET=1"
must be used, in which case a new preprocessor macro _USE_SDLNET will be
defined in the CFLAGS. For windows targets when not using SDL_net, WINSOCK2
is added as another option: A command line like "make WINSOCK2=1" will enable
WinSock2 api and a new preprocessor macro _USE_WINSOCK2 will be defined in
the CFLAGS. Or, a command line like "make WINSOCK2=0" will disable WinSock2
api and the old WinSock 1.1 api will be used instead. For Win64, WinSock2 is
enabled by default. For Win32, WinSock 1.1 is the default api.
* net_bsd.c, net_dgrm.c, net_loop.c, net_main.c, net_sdl.c, net_sdlnet.c,
net_udp.c, net_win.c, net_wins.c, net_wipx.c: Use the newly added net_sys.h
header. The sys_socket_t type is not in use, yet.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@215 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-06-21 11:10:38 +00:00
# include "arch_def.h"
# include "net_sys.h"
2010-02-15 23:26:55 +00:00
# include "quakedef.h"
2010-06-20 17:21:10 +00:00
# include "net_defs.h"
2010-02-15 23:26:55 +00:00
qsocket_t * net_activeSockets = NULL ;
qsocket_t * net_freeSockets = NULL ;
2010-06-21 10:41:34 +00:00
int net_numsockets = 0 ;
2010-02-15 23:26:55 +00:00
qboolean ipxAvailable = false ;
2017-09-17 02:12:53 +00:00
qboolean ipv4Available = false ;
qboolean ipv6Available = false ;
2010-02-15 23:26:55 +00:00
2010-06-21 10:41:34 +00:00
int net_hostport ;
int DEFAULTnet_hostport = 26000 ;
2010-02-15 23:26:55 +00:00
char my_ipx_address [ NET_NAMELEN ] ;
2017-09-17 02:12:53 +00:00
char my_ipv4_address [ NET_NAMELEN ] ;
char my_ipv6_address [ NET_NAMELEN ] ;
2010-02-15 23:26:55 +00:00
static qboolean listening = false ;
qboolean slistInProgress = false ;
qboolean slistSilent = false ;
2017-09-17 02:12:53 +00:00
enum slistScope_e slistScope = SLIST_LOOP ;
2010-02-15 23:26:55 +00:00
static double slistStartTime ;
2017-09-17 02:12:53 +00:00
static double slistActiveTime ;
2010-02-15 23:26:55 +00:00
static int slistLastShown ;
2010-08-24 10:29:19 +00:00
static void Slist_Send ( void * ) ;
static void Slist_Poll ( void * ) ;
2010-06-21 10:41:34 +00:00
static PollProcedure slistSendProcedure = { NULL , 0.0 , Slist_Send } ;
static PollProcedure slistPollProcedure = { NULL , 0.0 , Slist_Poll } ;
2010-02-15 23:26:55 +00:00
2010-06-21 10:41:34 +00:00
sizebuf_t net_message ;
int net_activeconnections = 0 ;
2010-02-15 23:26:55 +00:00
2010-06-21 10:41:34 +00:00
int messagesSent = 0 ;
int messagesReceived = 0 ;
int unreliableMessagesSent = 0 ;
int unreliableMessagesReceived = 0 ;
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
cvar_t net_messagetimeout = { " net_messagetimeout " , " 300 " , CVAR_NONE } ;
cvar_t net_connecttimeout = { " net_connecttimeout " , " 10 " , CVAR_NONE } ; //this might be a little brief, but we don't have a way to protect against smurf attacks.
2011-12-28 22:01:33 +00:00
cvar_t hostname = { " hostname " , " UNNAMED " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
// these two macros are to make the code more readable
# define sfunc net_drivers[sock->driver]
# define dfunc net_drivers[net_driverlevel]
2010-06-21 10:41:34 +00:00
int net_driverlevel ;
2010-02-15 23:26:55 +00:00
2010-06-21 10:41:34 +00:00
double net_time ;
2010-02-15 23:26:55 +00:00
2010-06-21 10:41:34 +00:00
double SetNetTime ( void )
2010-02-15 23:26:55 +00:00
{
2011-12-12 16:01:01 +00:00
net_time = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
return net_time ;
}
/*
= = = = = = = = = = = = = = = = = = =
NET_NewQSocket
Called by drivers when a new communications endpoint is required
The sequence and buffer fields will be filled in properly
= = = = = = = = = = = = = = = = = = =
*/
qsocket_t * NET_NewQSocket ( void )
{
qsocket_t * sock ;
if ( net_freeSockets = = NULL )
return NULL ;
if ( net_activeconnections > = svs . maxclients )
return NULL ;
// get one from free list
sock = net_freeSockets ;
net_freeSockets = sock - > next ;
// add it to active list
sock - > next = net_activeSockets ;
net_activeSockets = sock ;
2017-09-17 02:12:53 +00:00
sock - > isvirtual = false ;
2010-02-15 23:26:55 +00:00
sock - > disconnected = false ;
sock - > connecttime = net_time ;
2017-09-17 02:12:53 +00:00
Q_strcpy ( sock - > trueaddress , " UNSET ADDRESS " ) ;
Q_strcpy ( sock - > maskedaddress , " UNSET ADDRESS " ) ;
2010-02-15 23:26:55 +00:00
sock - > driver = net_driverlevel ;
sock - > socket = 0 ;
sock - > driverdata = NULL ;
sock - > canSend = true ;
sock - > sendNext = false ;
sock - > lastMessageTime = net_time ;
sock - > ackSequence = 0 ;
sock - > sendSequence = 0 ;
sock - > unreliableSendSequence = 0 ;
sock - > sendMessageLength = 0 ;
sock - > receiveSequence = 0 ;
sock - > unreliableReceiveSequence = 0 ;
sock - > receiveMessageLength = 0 ;
2017-09-17 02:12:53 +00:00
sock - > pending_max_datagram = 1024 ;
sock - > proquake_angle_hack = false ;
2010-02-15 23:26:55 +00:00
return sock ;
}
void NET_FreeQSocket ( qsocket_t * sock )
{
qsocket_t * s ;
// remove it from active list
if ( sock = = net_activeSockets )
net_activeSockets = net_activeSockets - > next ;
else
{
for ( s = net_activeSockets ; s ; s = s - > next )
2010-06-21 10:41:34 +00:00
{
2010-02-15 23:26:55 +00:00
if ( s - > next = = sock )
{
s - > next = sock - > next ;
break ;
}
2010-06-21 10:41:34 +00:00
}
2010-02-15 23:26:55 +00:00
if ( ! s )
2010-06-21 12:27:30 +00:00
Sys_Error ( " NET_FreeQSocket: not active " ) ;
2010-02-15 23:26:55 +00:00
}
// add it to free list
sock - > next = net_freeSockets ;
net_freeSockets = sock ;
sock - > disconnected = true ;
}
2017-09-17 02:12:53 +00:00
int NET_QSocketGetSequenceIn ( const qsocket_t * s )
{ //returns the last unreliable sequence that was received
return s - > unreliableReceiveSequence - 1 ;
}
int NET_QSocketGetSequenceOut ( const qsocket_t * s )
{ //returns the next unreliable sequence that will be sent
return s - > unreliableSendSequence ;
}
2015-04-01 09:30:10 +00:00
double NET_QSocketGetTime ( const qsocket_t * s )
2012-04-18 20:33:12 +00:00
{
return s - > connecttime ;
}
2017-09-17 02:12:53 +00:00
const char * NET_QSocketGetTrueAddressString ( const qsocket_t * s )
{
return s - > trueaddress ;
}
const char * NET_QSocketGetMaskedAddressString ( const qsocket_t * s )
2012-04-18 20:33:12 +00:00
{
2017-09-17 02:12:53 +00:00
return s - > maskedaddress ;
}
qboolean NET_QSocketGetProQuakeAngleHack ( const qsocket_t * s )
{
if ( s & & ! s - > disconnected )
return s - > proquake_angle_hack ;
else
return false ; //happens with demos
}
void NET_QSocketSetMSS ( qsocket_t * s , int mss )
{
s - > pending_max_datagram = mss ;
2012-04-18 20:33:12 +00:00
}
2010-02-15 23:26:55 +00:00
static void NET_Listen_f ( void )
{
if ( Cmd_Argc ( ) ! = 2 )
{
2010-06-21 10:41:34 +00:00
Con_Printf ( " \" listen \" is \" %d \" \n " , listening ? 1 : 0 ) ;
2010-02-15 23:26:55 +00:00
return ;
}
listening = Q_atoi ( Cmd_Argv ( 1 ) ) ? true : false ;
2010-06-21 10:41:34 +00:00
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
2010-02-15 23:26:55 +00:00
{
if ( net_drivers [ net_driverlevel ] . initialized = = false )
continue ;
dfunc . Listen ( listening ) ;
}
}
static void MaxPlayers_f ( void )
{
2010-06-21 10:41:34 +00:00
int n ;
2010-02-15 23:26:55 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
2010-06-21 10:41:34 +00:00
Con_Printf ( " \" maxplayers \" is \" %d \" \n " , svs . maxclients ) ;
2010-02-15 23:26:55 +00:00
return ;
}
if ( sv . active )
{
Con_Printf ( " maxplayers can not be changed while a server is running. \n " ) ;
return ;
}
n = Q_atoi ( Cmd_Argv ( 1 ) ) ;
if ( n < 1 )
n = 1 ;
if ( n > svs . maxclientslimit )
{
n = svs . maxclientslimit ;
2010-06-21 10:41:34 +00:00
Con_Printf ( " \" maxplayers \" set to \" %d \" \n " , n ) ;
2010-02-15 23:26:55 +00:00
}
if ( ( n = = 1 ) & & listening )
Cbuf_AddText ( " listen 0 \n " ) ;
if ( ( n > 1 ) & & ( ! listening ) )
Cbuf_AddText ( " listen 1 \n " ) ;
svs . maxclients = n ;
if ( n = = 1 )
Cvar_Set ( " deathmatch " , " 0 " ) ;
else
2011-12-27 08:27:52 +00:00
Cvar_Set ( " deathmatch " , " 1 " ) ;
2010-02-15 23:26:55 +00:00
}
static void NET_Port_f ( void )
{
2010-06-21 10:41:34 +00:00
int n ;
2010-02-15 23:26:55 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
2010-06-21 10:41:34 +00:00
Con_Printf ( " \" port \" is \" %d \" \n " , net_hostport ) ;
2010-02-15 23:26:55 +00:00
return ;
}
n = Q_atoi ( Cmd_Argv ( 1 ) ) ;
if ( n < 1 | | n > 65534 )
{
Con_Printf ( " Bad value, must be between 1 and 65534 \n " ) ;
return ;
}
DEFAULTnet_hostport = n ;
net_hostport = n ;
if ( listening )
{
// force a change to the new port
Cbuf_AddText ( " listen 0 \n " ) ;
Cbuf_AddText ( " listen 1 \n " ) ;
}
}
static void PrintSlistHeader ( void )
{
Con_Printf ( " Server Map Users \n " ) ;
Con_Printf ( " --------------- --------------- ----- \n " ) ;
slistLastShown = 0 ;
}
static void PrintSlist ( void )
{
2017-09-17 02:12:53 +00:00
size_t n ;
2010-02-15 23:26:55 +00:00
for ( n = slistLastShown ; n < hostCacheCount ; n + + )
{
if ( hostcache [ n ] . maxusers )
Con_Printf ( " %-15.15s %-15.15s %2u/%2u \n " , hostcache [ n ] . name , hostcache [ n ] . map , hostcache [ n ] . users , hostcache [ n ] . maxusers ) ;
else
Con_Printf ( " %-15.15s %-15.15s \n " , hostcache [ n ] . name , hostcache [ n ] . map ) ;
}
slistLastShown = n ;
}
static void PrintSlistTrailer ( void )
{
if ( hostCacheCount )
Con_Printf ( " == end list == \n \n " ) ;
else
Con_Printf ( " No Quake servers found. \n \n " ) ;
}
void NET_Slist_f ( void )
{
if ( slistInProgress )
return ;
if ( ! slistSilent )
{
Con_Printf ( " Looking for Quake servers... \n " ) ;
PrintSlistHeader ( ) ;
}
slistInProgress = true ;
2017-09-17 02:12:53 +00:00
slistActiveTime = slistStartTime = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
SchedulePollProcedure ( & slistSendProcedure , 0.0 ) ;
SchedulePollProcedure ( & slistPollProcedure , 0.1 ) ;
hostCacheCount = 0 ;
}
2012-04-18 20:33:12 +00:00
void NET_SlistSort ( void )
{
if ( hostCacheCount > 1 )
{
2017-09-17 02:12:53 +00:00
size_t i , j ;
2012-04-18 20:33:12 +00:00
hostcache_t temp ;
for ( i = 0 ; i < hostCacheCount ; i + + )
{
for ( j = i + 1 ; j < hostCacheCount ; j + + )
{
if ( strcmp ( hostcache [ j ] . name , hostcache [ i ] . name ) < 0 )
{
memcpy ( & temp , & hostcache [ j ] , sizeof ( hostcache_t ) ) ;
memcpy ( & hostcache [ j ] , & hostcache [ i ] , sizeof ( hostcache_t ) ) ;
memcpy ( & hostcache [ i ] , & temp , sizeof ( hostcache_t ) ) ;
}
}
}
}
}
2017-09-17 02:12:53 +00:00
const char * NET_SlistPrintServer ( size_t idx )
2012-04-18 20:33:12 +00:00
{
static char string [ 64 ] ;
2017-09-17 02:12:53 +00:00
if ( idx > = hostCacheCount )
2012-04-18 20:33:12 +00:00
return " " ;
if ( hostcache [ idx ] . maxusers )
{
q_snprintf ( string , sizeof ( string ) , " %-15.15s %-15.15s %2u/%2u \n " ,
hostcache [ idx ] . name , hostcache [ idx ] . map ,
hostcache [ idx ] . users , hostcache [ idx ] . maxusers ) ;
}
else
{
q_snprintf ( string , sizeof ( string ) , " %-15.15s %-15.15s \n " ,
hostcache [ idx ] . name , hostcache [ idx ] . map ) ;
}
return string ;
}
2017-09-17 02:12:53 +00:00
const char * NET_SlistPrintServerName ( size_t idx )
2012-04-18 20:33:12 +00:00
{
2017-09-17 02:12:53 +00:00
if ( idx > = hostCacheCount )
2012-04-18 20:33:12 +00:00
return " " ;
return hostcache [ idx ] . cname ;
}
2010-08-24 10:29:19 +00:00
static void Slist_Send ( void * unused )
2010-02-15 23:26:55 +00:00
{
2010-06-21 10:41:34 +00:00
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
if ( slistScope ! = SLIST_LOOP & & IS_LOOP_DRIVER ( net_driverlevel ) )
2010-02-15 23:26:55 +00:00
continue ;
if ( net_drivers [ net_driverlevel ] . initialized = = false )
continue ;
dfunc . SearchForHosts ( true ) ;
}
2011-12-12 16:01:01 +00:00
if ( ( Sys_DoubleTime ( ) - slistStartTime ) < 0.5 )
2010-02-15 23:26:55 +00:00
SchedulePollProcedure ( & slistSendProcedure , 0.75 ) ;
}
2010-08-24 10:29:19 +00:00
static void Slist_Poll ( void * unused )
2010-02-15 23:26:55 +00:00
{
2010-06-21 10:41:34 +00:00
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
if ( slistScope ! = SLIST_LOOP & & IS_LOOP_DRIVER ( net_driverlevel ) )
2010-02-15 23:26:55 +00:00
continue ;
if ( net_drivers [ net_driverlevel ] . initialized = = false )
continue ;
2017-09-17 02:12:53 +00:00
if ( dfunc . SearchForHosts ( false ) )
slistActiveTime = Sys_DoubleTime ( ) ; //something was sent, reset the timer.
2010-02-15 23:26:55 +00:00
}
if ( ! slistSilent )
PrintSlist ( ) ;
2017-09-17 02:12:53 +00:00
if ( ( Sys_DoubleTime ( ) - slistActiveTime ) < 1.5 )
2010-02-15 23:26:55 +00:00
{
SchedulePollProcedure ( & slistPollProcedure , 0.1 ) ;
return ;
}
if ( ! slistSilent )
PrintSlistTrailer ( ) ;
slistInProgress = false ;
slistSilent = false ;
2017-09-17 02:12:53 +00:00
slistScope = SLIST_LOOP ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
NET_Connect
= = = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
size_t hostCacheCount = 0 ;
2010-02-15 23:26:55 +00:00
hostcache_t hostcache [ HOSTCACHESIZE ] ;
2010-08-29 02:22:55 +00:00
qsocket_t * NET_Connect ( const char * host )
2010-02-15 23:26:55 +00:00
{
qsocket_t * ret ;
2017-09-17 02:12:53 +00:00
size_t n ;
2010-02-15 23:26:55 +00:00
int numdrivers = net_numdrivers ;
SetNetTime ( ) ;
if ( host & & * host = = 0 )
host = NULL ;
if ( host )
{
2013-09-25 17:01:40 +00:00
if ( q_strcasecmp ( host , " local " ) = = 0 )
2010-02-15 23:26:55 +00:00
{
numdrivers = 1 ;
goto JustDoIt ;
}
if ( hostCacheCount )
{
for ( n = 0 ; n < hostCacheCount ; n + + )
2013-09-25 17:01:40 +00:00
if ( q_strcasecmp ( host , hostcache [ n ] . name ) = = 0 )
2010-02-15 23:26:55 +00:00
{
host = hostcache [ n ] . cname ;
break ;
}
if ( n < hostCacheCount )
goto JustDoIt ;
}
}
slistSilent = host ? true : false ;
NET_Slist_f ( ) ;
2010-06-21 10:41:34 +00:00
while ( slistInProgress )
2010-02-15 23:26:55 +00:00
NET_Poll ( ) ;
if ( host = = NULL )
{
if ( hostCacheCount ! = 1 )
return NULL ;
host = hostcache [ 0 ] . cname ;
Con_Printf ( " Connecting to... \n %s @ %s \n \n " , hostcache [ 0 ] . name , host ) ;
}
if ( hostCacheCount )
2010-06-21 10:41:34 +00:00
{
2010-02-15 23:26:55 +00:00
for ( n = 0 ; n < hostCacheCount ; n + + )
2010-06-21 10:41:34 +00:00
{
2013-09-25 17:01:40 +00:00
if ( q_strcasecmp ( host , hostcache [ n ] . name ) = = 0 )
2010-02-15 23:26:55 +00:00
{
host = hostcache [ n ] . cname ;
break ;
}
2010-06-21 10:41:34 +00:00
}
}
2010-02-15 23:26:55 +00:00
JustDoIt :
2010-06-21 10:41:34 +00:00
for ( net_driverlevel = 0 ; net_driverlevel < numdrivers ; net_driverlevel + + )
2010-02-15 23:26:55 +00:00
{
if ( net_drivers [ net_driverlevel ] . initialized = = false )
continue ;
ret = dfunc . Connect ( host ) ;
if ( ret )
return ret ;
}
if ( host )
{
Con_Printf ( " \n " ) ;
PrintSlistHeader ( ) ;
PrintSlist ( ) ;
PrintSlistTrailer ( ) ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = =
NET_CheckNewConnections
= = = = = = = = = = = = = = = = = = =
*/
qsocket_t * NET_CheckNewConnections ( void )
{
qsocket_t * ret ;
SetNetTime ( ) ;
2010-06-21 10:41:34 +00:00
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
2010-02-15 23:26:55 +00:00
{
if ( net_drivers [ net_driverlevel ] . initialized = = false )
continue ;
2011-09-20 18:05:51 +00:00
if ( ! IS_LOOP_DRIVER ( net_driverlevel ) & & listening = = false )
2010-02-15 23:26:55 +00:00
continue ;
ret = dfunc . CheckNewConnections ( ) ;
if ( ret )
{
return ret ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = =
NET_Close
= = = = = = = = = = = = = = = = = = =
*/
void NET_Close ( qsocket_t * sock )
{
if ( ! sock )
return ;
if ( sock - > disconnected )
return ;
SetNetTime ( ) ;
// call the driver_Close function
sfunc . Close ( sock ) ;
NET_FreeQSocket ( sock ) ;
}
/*
= = = = = = = = = = = = = = = = =
NET_GetMessage
If there is a complete message , return it in net_message
returns 0 if no data is waiting
returns 1 if a message was received
returns - 1 if connection is invalid
= = = = = = = = = = = = = = = = =
*/
int NET_GetMessage ( qsocket_t * sock )
{
int ret ;
if ( ! sock )
return - 1 ;
if ( sock - > disconnected )
{
Con_Printf ( " NET_GetMessage: disconnected socket \n " ) ;
return - 1 ;
}
SetNetTime ( ) ;
ret = sfunc . QGetMessage ( sock ) ;
// see if this connection has timed out
2011-09-20 18:05:51 +00:00
if ( ret = = 0 & & ! IS_LOOP_DRIVER ( sock - > driver ) )
2010-02-15 23:26:55 +00:00
{
if ( net_time - sock - > lastMessageTime > net_messagetimeout . value )
{
NET_Close ( sock ) ;
return - 1 ;
}
}
if ( ret > 0 )
{
2011-09-20 18:05:51 +00:00
if ( ! IS_LOOP_DRIVER ( sock - > driver ) )
2010-02-15 23:26:55 +00:00
{
sock - > lastMessageTime = net_time ;
if ( ret = = 1 )
messagesReceived + + ;
else if ( ret = = 2 )
unreliableMessagesReceived + + ;
}
}
return ret ;
}
2017-09-17 02:12:53 +00:00
/*
= = = = = = = = = = = = = = = = =
NET_GetServerMessage
If there is a complete message , return it in net_message
returns the qsocket that the message was meant to be for .
= = = = = = = = = = = = = = = = =
*/
qsocket_t * NET_GetServerMessage ( void )
{
qsocket_t * s ;
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
{
if ( ! net_drivers [ net_driverlevel ] . initialized )
continue ;
s = net_drivers [ net_driverlevel ] . QGetAnyMessage ( ) ;
if ( s )
return s ;
}
return NULL ;
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
NET_SendMessage
Try to send a complete length + message unit over the reliable stream .
returns 0 if the message cannot be delivered reliably , but the connection
is still considered valid
returns 1 if the message was sent properly
returns - 1 if the connection died
= = = = = = = = = = = = = = = = = =
*/
int NET_SendMessage ( qsocket_t * sock , sizebuf_t * data )
{
int r ;
if ( ! sock )
return - 1 ;
if ( sock - > disconnected )
{
Con_Printf ( " NET_SendMessage: disconnected socket \n " ) ;
return - 1 ;
}
SetNetTime ( ) ;
r = sfunc . QSendMessage ( sock , data ) ;
2011-09-20 18:05:51 +00:00
if ( r = = 1 & & ! IS_LOOP_DRIVER ( sock - > driver ) )
2010-02-15 23:26:55 +00:00
messagesSent + + ;
return r ;
}
int NET_SendUnreliableMessage ( qsocket_t * sock , sizebuf_t * data )
{
int r ;
if ( ! sock )
return - 1 ;
if ( sock - > disconnected )
{
Con_Printf ( " NET_SendMessage: disconnected socket \n " ) ;
return - 1 ;
}
SetNetTime ( ) ;
r = sfunc . SendUnreliableMessage ( sock , data ) ;
2011-09-20 18:05:51 +00:00
if ( r = = 1 & & ! IS_LOOP_DRIVER ( sock - > driver ) )
2010-02-15 23:26:55 +00:00
unreliableMessagesSent + + ;
return r ;
}
/*
= = = = = = = = = = = = = = = = = =
NET_CanSendMessage
Returns true or false if the given qsocket can currently accept a
message to be transmitted .
= = = = = = = = = = = = = = = = = =
*/
qboolean NET_CanSendMessage ( qsocket_t * sock )
{
if ( ! sock )
return false ;
if ( sock - > disconnected )
return false ;
SetNetTime ( ) ;
2010-06-21 10:41:34 +00:00
return sfunc . CanSendMessage ( sock ) ;
2010-02-15 23:26:55 +00:00
}
2010-06-20 15:00:57 +00:00
int NET_SendToAll ( sizebuf_t * data , double blocktime )
2010-02-15 23:26:55 +00:00
{
double start ;
int i ;
int count = 0 ;
2010-06-21 10:41:34 +00:00
qboolean msg_init [ MAX_SCOREBOARD ] ; /* did we write the message to the client's connection */
qboolean msg_sent [ MAX_SCOREBOARD ] ; /* did the msg arrive its destination (canSend state). */
2010-02-15 23:26:55 +00:00
2010-06-20 15:00:57 +00:00
for ( i = 0 , host_client = svs . clients ; i < svs . maxclients ; i + + , host_client + + )
2010-02-15 23:26:55 +00:00
{
2010-06-20 15:00:57 +00:00
/*
2010-02-15 23:26:55 +00:00
if ( ! host_client - > netconnection )
continue ;
if ( host_client - > active )
2010-06-20 15:00:57 +00:00
*/
if ( host_client - > netconnection & & host_client - > active )
2010-02-15 23:26:55 +00:00
{
2011-09-20 18:05:51 +00:00
if ( IS_LOOP_DRIVER ( host_client - > netconnection - > driver ) )
2010-02-15 23:26:55 +00:00
{
NET_SendMessage ( host_client - > netconnection , data ) ;
2010-06-20 15:00:57 +00:00
msg_init [ i ] = true ;
msg_sent [ i ] = true ;
2010-02-15 23:26:55 +00:00
continue ;
}
count + + ;
2010-06-20 15:00:57 +00:00
msg_init [ i ] = false ;
msg_sent [ i ] = false ;
2010-02-15 23:26:55 +00:00
}
else
{
2010-06-20 15:00:57 +00:00
msg_init [ i ] = true ;
msg_sent [ i ] = true ;
2010-02-15 23:26:55 +00:00
}
}
2011-12-12 16:01:01 +00:00
start = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
while ( count )
{
count = 0 ;
2010-06-21 10:41:34 +00:00
for ( i = 0 , host_client = svs . clients ; i < svs . maxclients ; i + + , host_client + + )
2010-02-15 23:26:55 +00:00
{
2010-06-20 15:00:57 +00:00
if ( ! msg_init [ i ] )
2010-02-15 23:26:55 +00:00
{
if ( NET_CanSendMessage ( host_client - > netconnection ) )
{
2010-06-20 15:00:57 +00:00
msg_init [ i ] = true ;
2010-02-15 23:26:55 +00:00
NET_SendMessage ( host_client - > netconnection , data ) ;
}
else
{
NET_GetMessage ( host_client - > netconnection ) ;
}
count + + ;
continue ;
}
2010-06-20 15:00:57 +00:00
if ( ! msg_sent [ i ] )
2010-02-15 23:26:55 +00:00
{
if ( NET_CanSendMessage ( host_client - > netconnection ) )
{
2010-06-20 15:00:57 +00:00
msg_sent [ i ] = true ;
2010-02-15 23:26:55 +00:00
}
else
{
NET_GetMessage ( host_client - > netconnection ) ;
}
count + + ;
continue ;
}
}
2011-12-12 16:01:01 +00:00
if ( ( Sys_DoubleTime ( ) - start ) > blocktime )
2010-02-15 23:26:55 +00:00
break ;
}
return count ;
}
//=============================================================================
/*
= = = = = = = = = = = = = = = = = = = =
NET_Init
= = = = = = = = = = = = = = = = = = = =
*/
void NET_Init ( void )
{
int i ;
qsocket_t * s ;
i = COM_CheckParm ( " -port " ) ;
if ( ! i )
i = COM_CheckParm ( " -udpport " ) ;
if ( ! i )
i = COM_CheckParm ( " -ipxport " ) ;
2011-09-20 18:05:51 +00:00
2010-02-15 23:26:55 +00:00
if ( i )
{
if ( i < com_argc - 1 )
DEFAULTnet_hostport = Q_atoi ( com_argv [ i + 1 ] ) ;
else
Sys_Error ( " NET_Init: you must specify a number after -port " ) ;
}
net_hostport = DEFAULTnet_hostport ;
net_numsockets = svs . maxclientslimit ;
if ( cls . state ! = ca_dedicated )
net_numsockets + + ;
2011-09-20 18:05:51 +00:00
if ( COM_CheckParm ( " -listen " ) | | cls . state = = ca_dedicated )
listening = true ;
2010-02-15 23:26:55 +00:00
SetNetTime ( ) ;
for ( i = 0 ; i < net_numsockets ; i + + )
{
s = ( qsocket_t * ) Hunk_AllocName ( sizeof ( qsocket_t ) , " qsocket " ) ;
s - > next = net_freeSockets ;
net_freeSockets = s ;
s - > disconnected = true ;
}
// allocate space for network message buffer
SZ_Alloc ( & net_message , NET_MAXMESSAGE ) ;
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & net_messagetimeout ) ;
2017-09-17 02:12:53 +00:00
Cvar_RegisterVariable ( & net_connecttimeout ) ;
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & hostname ) ;
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " slist " , NET_Slist_f ) ;
Cmd_AddCommand ( " listen " , NET_Listen_f ) ;
Cmd_AddCommand ( " maxplayers " , MaxPlayers_f ) ;
Cmd_AddCommand ( " port " , NET_Port_f ) ;
// initialize all the drivers
2010-06-20 15:33:45 +00:00
for ( i = net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
{
2010-06-21 10:50:21 +00:00
if ( net_drivers [ net_driverlevel ] . Init ( ) = = - 1 )
2010-02-15 23:26:55 +00:00
continue ;
2010-06-20 15:33:45 +00:00
i + + ;
2010-02-15 23:26:55 +00:00
net_drivers [ net_driverlevel ] . initialized = true ;
if ( listening )
net_drivers [ net_driverlevel ] . Listen ( true ) ;
2010-06-20 15:33:45 +00:00
}
2011-09-20 18:05:51 +00:00
/* Loop_Init() returns -1 for dedicated server case,
* therefore the i = = 0 check is correct */
if ( i = = 0
& & cls . state = = ca_dedicated
)
{
2010-06-20 15:33:45 +00:00
Sys_Error ( " Network not available! " ) ;
2011-09-20 18:05:51 +00:00
}
2010-02-15 23:26:55 +00:00
if ( * my_ipx_address )
2011-09-20 18:05:51 +00:00
{
2010-02-15 23:26:55 +00:00
Con_DPrintf ( " IPX address %s \n " , my_ipx_address ) ;
2011-09-20 18:05:51 +00:00
}
2017-09-17 02:12:53 +00:00
if ( * my_ipv4_address )
{
Con_DPrintf ( " IPv4 address %s \n " , my_ipv4_address ) ;
}
if ( * my_ipv6_address )
2011-09-20 18:05:51 +00:00
{
2017-09-17 02:12:53 +00:00
Con_DPrintf ( " IPv6 address %s \n " , my_ipv6_address ) ;
2011-09-20 18:05:51 +00:00
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = =
NET_Shutdown
= = = = = = = = = = = = = = = = = = = =
*/
2010-06-21 10:41:34 +00:00
void NET_Shutdown ( void )
2010-02-15 23:26:55 +00:00
{
qsocket_t * sock ;
SetNetTime ( ) ;
for ( sock = net_activeSockets ; sock ; sock = sock - > next )
NET_Close ( sock ) ;
//
// shutdown the drivers
//
for ( net_driverlevel = 0 ; net_driverlevel < net_numdrivers ; net_driverlevel + + )
{
if ( net_drivers [ net_driverlevel ] . initialized = = true )
{
net_drivers [ net_driverlevel ] . Shutdown ( ) ;
net_drivers [ net_driverlevel ] . initialized = false ;
}
}
}
static PollProcedure * pollProcedureList = NULL ;
void NET_Poll ( void )
{
PollProcedure * pp ;
SetNetTime ( ) ;
for ( pp = pollProcedureList ; pp ; pp = pp - > next )
{
if ( pp - > nextTime > net_time )
break ;
pollProcedureList = pp - > next ;
pp - > procedure ( pp - > arg ) ;
}
}
void SchedulePollProcedure ( PollProcedure * proc , double timeOffset )
{
PollProcedure * pp , * prev ;
2011-12-12 16:01:01 +00:00
proc - > nextTime = Sys_DoubleTime ( ) + timeOffset ;
2010-02-15 23:26:55 +00:00
for ( pp = pollProcedureList , prev = NULL ; pp ; pp = pp - > next )
{
if ( pp - > nextTime > = proc - > nextTime )
break ;
prev = pp ;
}
if ( prev = = NULL )
{
proc - > next = pollProcedureList ;
pollProcedureList = proc ;
return ;
}
proc - > next = pp ;
prev - > next = proc ;
}
2010-06-21 10:41:34 +00:00