summaryrefslogtreecommitdiff
path: root/src/sv_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sv_main.c')
-rw-r--r--src/sv_main.c64
1 files changed, 34 insertions, 30 deletions
diff --git a/src/sv_main.c b/src/sv_main.c
index 466efe9..6bbf79a 100644
--- a/src/sv_main.c
+++ b/src/sv_main.c
@@ -28,6 +28,7 @@ LIST_DECL( sv_blacklist );
LIST_DECL( sv_cmdlist_connect );
LIST_DECL( sv_cmdlist_begin );
LIST_DECL( sv_filterlist );
+LIST_DECL( sv_clientlist ); // linked list of non-free clients
client_t *sv_client; // current client
@@ -106,7 +107,8 @@ void SV_RemoveClient( client_t *client ) {
client->netchan = NULL;
}
- // unlink them from active client list
+ // unlink them from active client list, but don't clear the list entry
+ // itself to make code that traverses client list in a loop happy!
List_Remove( &client->entry );
#if USE_MVD_CLIENT
@@ -818,10 +820,8 @@ static void SVC_DirectConnect( void ) {
}
Com_DPrintf( "%s: reconnect\n", NET_AdrToString( &net_from ) );
- newcl = cl;
-
- // NOTE: it's safe to call SV_Remove since we exit the loop
SV_RemoveClient( cl );
+ newcl = cl;
break;
}
}
@@ -980,7 +980,7 @@ static void SVC_DirectConnect( void ) {
}
// add them to the linked list of connected clients
- List_SeqAdd( &svs.client_list, &newcl->entry );
+ List_SeqAdd( &sv_clientlist, &newcl->entry );
Com_DPrintf( "Going from cs_free to cs_assigned for %s\n", newcl->name );
newcl->state = cs_assigned;
@@ -1452,7 +1452,7 @@ static inline qboolean check_paused( void ) {
#if USE_MVD_CLIENT
LIST_EMPTY( &mvd_gtv_list ) &&
#endif
- LIST_SINGLE( &svs.client_list ) )
+ LIST_SINGLE( &sv_clientlist ) )
{
if( !sv_paused->integer ) {
Cvar_Set( "sv_paused", "1" );
@@ -1577,6 +1577,11 @@ Informs all masters that this server is going down
static void SV_MasterShutdown( void ) {
master_t *m;
+ // reset ack times
+ FOR_EACH_MASTER( m ) {
+ m->last_ack = 0;
+ }
+
if( !Com_IsDedicated() )
return; // only dedicated servers send heartbeats
@@ -1981,20 +1986,28 @@ Used by SV_Shutdown to send a final message to all
connected clients before the server goes down. The messages are sent
immediately, not just stuck on the outgoing message list, because the
server is going to totally exit after returning from this function.
+
+Also resposible for freeing all clients.
==================
*/
-static void SV_FinalMessage( const char *message, int cmd ) {
+static void SV_FinalMessage( const char *message, error_type_t type ) {
client_t *client;
netchan_t *netchan;
int i;
+ if( LIST_EMPTY( &sv_clientlist ) )
+ return;
+
if( message ) {
MSG_WriteByte( svc_print );
MSG_WriteByte( PRINT_HIGH );
MSG_WriteString( message );
}
- MSG_WriteByte( cmd );
+ if( type == ERR_RECONNECT )
+ MSG_WriteByte( svc_reconnect );
+ else
+ MSG_WriteByte( svc_disconnect );
// send it twice
// stagger the packets to crutch operating system limited buffers
@@ -2020,6 +2033,8 @@ static void SV_FinalMessage( const char *message, int cmd ) {
}
SV_RemoveClient( client );
}
+
+ List_Init( &sv_clientlist );
}
@@ -2027,37 +2042,28 @@ static void SV_FinalMessage( const char *message, int cmd ) {
================
SV_Shutdown
-Called when each game quits, from Com_Quit or Com_Error
+Called when each game quits, from Com_Quit or Com_Error.
+Should be safe to call even if server is not fully initalized yet.
================
*/
void SV_Shutdown( const char *finalmsg, error_type_t type ) {
- master_t *m;
-
- Cvar_Set( "sv_running", "0" );
- Cvar_Set( "sv_paused", "0" );
-
- if( !svs.initialized ) {
#if USE_MVD_CLIENT
- MVD_Shutdown(); // make sure MVD client is down
-#endif
- return;
+ if( ge != &mvd_ge ) {
+ // shutdown MVD client now if not running the built-in MVD game module,
+ // otherwise SV_ShutdownGameProgs will take care of this
+ MVD_Shutdown();
}
+#endif
#if USE_AC_SERVER
AC_Disconnect();
#endif
#if USE_MVD_SERVER
- // shutdown MVD server
SV_MvdShutdown( type );
#endif
- if( type == ERR_RECONNECT ) {
- SV_FinalMessage( finalmsg, svc_reconnect );
- } else {
- SV_FinalMessage( finalmsg, svc_disconnect );
- }
-
+ SV_FinalMessage( finalmsg, type );
SV_MasterShutdown();
SV_ShutdownGameProgs();
@@ -2074,17 +2080,15 @@ void SV_Shutdown( const char *finalmsg, error_type_t type ) {
#endif
memset( &svs, 0, sizeof( svs ) );
- // reset masters
- FOR_EACH_MASTER( m ) {
- m->last_ack = 0;
- }
-
// reset rate limits
init_rate_limits();
sv_client = NULL;
sv_player = NULL;
+ Cvar_Set( "sv_running", "0" );
+ Cvar_Set( "sv_paused", "0" );
+
#if USE_SYSCON
SV_SetConsoleTitle();
#endif