summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/sv_ccmds.c67
-rw-r--r--source/sv_init.c39
-rw-r--r--source/sv_local.h25
-rw-r--r--source/sv_main.c34
4 files changed, 124 insertions, 41 deletions
diff --git a/source/sv_ccmds.c b/source/sv_ccmds.c
index 329b460..bd20571 100644
--- a/source/sv_ccmds.c
+++ b/source/sv_ccmds.c
@@ -38,8 +38,10 @@ Specify a list of master servers
*/
static void SV_SetMaster_f( void ) {
netadr_t adr;
- int i, j, slot;
+ int i, total;
char *s;
+ master_t *m, *n;
+ size_t len;
#if USE_CLIENT
// only dedicated servers send heartbeats
@@ -49,11 +51,16 @@ static void SV_SetMaster_f( void ) {
}
#endif
- memset( &master_adr, 0, sizeof( master_adr ) );
+ // free old masters
+ FOR_EACH_MASTER_SAFE( m, n ) {
+ Z_Free( m );
+ }
+
+ List_Init( &sv_masterlist );
- slot = 0;
+ total = 0;
for( i = 1; i < Cmd_Argc(); i++ ) {
- if( slot == MAX_MASTERS ) {
+ if( total == MAX_MASTERS ) {
Com_Printf( "Too many masters.\n" );
break;
}
@@ -64,21 +71,26 @@ static void SV_SetMaster_f( void ) {
continue;
}
- s = NET_AdrToString( &adr );
- for( j = 0; j < slot; j++ ) {
- if( NET_IsEqualBaseAdr( &master_adr[j], &adr ) ) {
- Com_Printf( "Ignoring duplicate master at %s.\n", s );
- break;
+ FOR_EACH_MASTER( m ) {
+ if( NET_IsEqualBaseAdr( &m->adr, &adr ) ) {
+ Com_Printf( "Ignoring duplicate master at %s.\n", NET_AdrToString( &adr ) );
+ goto out;
}
}
- if( j == slot ) {
- Com_Printf( "Master server at %s.\n", s );
- master_adr[slot++] = adr;
- }
+ Com_Printf( "Master server at %s.\n", NET_AdrToString( &adr ) );
+ len = strlen( s );
+ m = Z_Malloc( sizeof( *m ) + len );
+ memcpy( m->name, s, len + 1 );
+ m->adr = adr;
+ m->last_ack = 0;
+ m->last_resolved = time( NULL );
+ List_Append( &sv_masterlist, &m->entry );
+ total++;
+out:;
}
- if( slot ) {
+ if( total ) {
// make sure the server is listed public
Cvar_Set( "public", "1" );
@@ -86,6 +98,32 @@ static void SV_SetMaster_f( void ) {
}
}
+static void SV_ListMasters_f( void ) {
+ master_t *m;
+ char buf[16], *adr;
+ unsigned acked;
+
+ if( LIST_EMPTY( &sv_masterlist ) ) {
+ Com_Printf( "There are no masters.\n" );
+ return;
+ }
+
+ Com_Printf( "hostname last ack address\n"
+ "--------------------- -------- ---------------------\n" );
+ FOR_EACH_MASTER( m ) {
+ if( !svs.initialized ) {
+ strcpy( buf, "down" );
+ } else if( !m->last_ack ) {
+ strcpy( buf, "never" );
+ } else {
+ acked = ( svs.realtime - m->last_ack ) / 1000;
+ Com_FormatTime( buf, sizeof( buf ), acked );
+ }
+ adr = m->adr.port ? NET_AdrToString( &m->adr ) : "<unknown>";
+ Com_Printf( "%-21.21s %-8s %-21s\n", m->name, buf, adr );
+ }
+}
+
client_t *SV_GetPlayer( const char *s, qboolean partial ) {
client_t *other, *match;
int i, count;
@@ -1257,6 +1295,7 @@ static const cmdreg_t c_server[] = {
{ "gamemap", SV_GameMap_f, SV_Map_c },
{ "dumpents", SV_DumpEnts_f },
{ "setmaster", SV_SetMaster_f },
+ { "listmasters", SV_ListMasters_f },
{ "killserver", SV_KillServer_f },
{ "sv", SV_ServerCommand_f },
{ "pickclient", SV_PickClient_f },
diff --git a/source/sv_init.c b/source/sv_init.c
index 9c19b01..3f11d6a 100644
--- a/source/sv_init.c
+++ b/source/sv_init.c
@@ -38,7 +38,7 @@ void SV_ClientReset( client_t *client ) {
}
#if USE_FPS
-static void SV_SetFrameTime( void ) {
+static void set_frame_time( void ) {
int i = sv_fps->integer / 10;
clamp( i, 1, 6 );
@@ -50,6 +50,34 @@ static void SV_SetFrameTime( void ) {
}
#endif
+#if !USE_CLIENT
+static void resolve_masters( void ) {
+ master_t *m;
+ time_t now, delta;
+
+ now = time( NULL );
+ FOR_EACH_MASTER( m ) {
+ // re-resolve valid address after one day,
+ // resolve invalid address after three hours
+ delta = m->adr.port ? 24*60*60 : 3*60*60;
+ if( now < m->last_resolved ) {
+ m->last_resolved = now;
+ continue;
+ }
+ if( now - m->last_resolved < delta ) {
+ continue;
+ }
+ if( NET_StringToAdr( m->name, &m->adr, PORT_MASTER ) ) {
+ Com_DPrintf( "Master server at %s.\n", NET_AdrToString( &m->adr ) );
+ } else {
+ Com_WPrintf( "Couldn't resolve master: %s\n", m->name );
+ m->adr.port = 0;
+ }
+ m->last_resolved = now = time( NULL );
+ }
+}
+#endif
+
/*
================
SV_SpawnServer
@@ -93,6 +121,10 @@ static void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint
client->spawncount = sv.spawncount;
}
+#if !USE_CLIENT
+ resolve_masters();
+#endif
+
Q_concat( string, sizeof( string ), "maps/", server, ".bsp", NULL );
sv.cm = *cm;
strcpy( sv.configstrings[CS_MODELS + 1], string );
@@ -112,7 +144,7 @@ static void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint
// spawn the rest of the entities on the map
//
#if USE_FPS
- SV_SetFrameTime();
+ set_frame_time();
#endif
// precache and static commands can be issued during
@@ -267,6 +299,9 @@ void SV_InitGame( qboolean ismvd ) {
SV_RateInit( &svs.ratelimit_badpass, 1, sv_badauth_time->value * 1000 );
SV_RateInit( &svs.ratelimit_badrcon, 1, sv_badauth_time->value * 1000 );
+ // send heartbeat very soon
+ svs.last_heartbeat = -(HEARTBEAT_SECONDS-5)*1000;
+
List_Init( &svs.udp_client_list );
for( i = 0; i < sv_maxclients->integer; i++ ) {
diff --git a/source/sv_local.h b/source/sv_local.h
index 6d3a606..18e9287 100644
--- a/source/sv_local.h
+++ b/source/sv_local.h
@@ -46,9 +46,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//=============================================================================
-#define MAX_MASTERS 8 // max recipients for heartbeat packets
-#define HEARTBEAT_SECONDS 300
-
#define SV_Malloc( size ) Z_TagMalloc( size, TAG_SERVER )
#define SV_Mallocz( size ) Z_TagMallocz( size, TAG_SERVER )
#define SV_CopyString( s ) Z_TagCopyString( s, TAG_SERVER )
@@ -350,6 +347,22 @@ typedef struct {
char string[1];
} filtercmd_t;
+#define MAX_MASTERS 8 // max recipients for heartbeat packets
+#define HEARTBEAT_SECONDS 300
+
+typedef struct {
+ list_t entry;
+ netadr_t adr;
+ unsigned last_ack;
+ time_t last_resolved;
+ char name[1];
+} master_t;
+
+#define FOR_EACH_MASTER( m ) \
+ LIST_FOR_EACH( master_t, m, &sv_masterlist, entry )
+#define FOR_EACH_MASTER_SAFE( m, n ) \
+ LIST_FOR_EACH_SAFE( master_t, m, n, &sv_masterlist, entry )
+
typedef struct server_static_s {
qboolean initialized; // sv_init has completed
unsigned realtime; // always increasing, no clamping, etc
@@ -376,14 +389,10 @@ typedef struct server_static_s {
//=============================================================================
-extern netadr_t master_adr[MAX_MASTERS]; // address of the master server
-
+extern list_t sv_masterlist; // address of the master server
extern list_t sv_banlist;
-extern list_t sv_blacklist;
-
extern list_t sv_cmdlist_connect;
extern list_t sv_cmdlist_begin;
-
extern list_t sv_filterlist;
extern server_static_t svs; // persistant server info
diff --git a/source/sv_main.c b/source/sv_main.c
index 81d2d3f..35760d3 100644
--- a/source/sv_main.c
+++ b/source/sv_main.c
@@ -20,10 +20,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sv_local.h"
-netadr_t master_adr[MAX_MASTERS]; // address of group servers
-
pmoveParams_t sv_pmp;
+LIST_DECL( sv_masterlist ); // address of group servers
LIST_DECL( sv_banlist );
LIST_DECL( sv_cmdlist_connect );
LIST_DECL( sv_cmdlist_begin );
@@ -377,15 +376,16 @@ SVC_Ack
================
*/
static void SVC_Ack( void ) {
- int i;
+ master_t *m;
- for( i = 0; i < MAX_MASTERS; i++ ) {
- if( !master_adr[i].port ) {
+ FOR_EACH_MASTER( m ) {
+ if( !m->adr.port ) {
continue;
}
- if( NET_IsEqualBaseAdr( &master_adr[i], &net_from ) ) {
- Com_Printf( "Ping acknowledge from %s\n",
+ if( NET_IsEqualBaseAdr( &m->adr, &net_from ) ) {
+ Com_DPrintf( "Ping acknowledge from %s\n",
NET_AdrToString( &net_from ) );
+ m->last_ack = svs.realtime;
break;
}
}
@@ -1493,7 +1493,7 @@ let it know we are alive, and log information
static void SV_MasterHeartbeat( void ) {
char buffer[MAX_PACKETLEN_DEFAULT];
size_t len;
- int i;
+ master_t *m;
if( !Com_IsDedicated() )
return; // only dedicated servers send heartbeats
@@ -1514,11 +1514,11 @@ static void SV_MasterHeartbeat( void ) {
len += SV_StatusString( buffer + len );
// send to group master
- for( i = 0; i < MAX_MASTERS; i++ ) {
- if( master_adr[i].port ) {
+ FOR_EACH_MASTER( m ) {
+ if( m->adr.port ) {
Com_DPrintf( "Sending heartbeat to %s\n",
- NET_AdrToString( &master_adr[i] ) );
- NET_SendPacket( NS_SERVER, &master_adr[i], len, buffer );
+ NET_AdrToString( &m->adr ) );
+ NET_SendPacket( NS_SERVER, &m->adr, len, buffer );
}
}
}
@@ -1531,7 +1531,7 @@ Informs all masters that this server is going down
=================
*/
static void SV_MasterShutdown( void ) {
- int i;
+ master_t *m;
if( !Com_IsDedicated() )
return; // only dedicated servers send heartbeats
@@ -1540,11 +1540,11 @@ static void SV_MasterShutdown( void ) {
return; // a private dedicated game
// send to group master
- for( i = 0; i < MAX_MASTERS; i++ ) {
- if( master_adr[i].port ) {
+ FOR_EACH_MASTER( m ) {
+ if( m->adr.port ) {
Com_DPrintf( "Sending shutdown to %s\n",
- NET_AdrToString( &master_adr[i] ) );
- OOB_PRINT( NS_SERVER, &master_adr[i], "shutdown" );
+ NET_AdrToString( &m->adr ) );
+ OOB_PRINT( NS_SERVER, &m->adr, "shutdown" );
}
}
}