diff options
-rw-r--r-- | source/sv_ccmds.c | 67 | ||||
-rw-r--r-- | source/sv_init.c | 39 | ||||
-rw-r--r-- | source/sv_local.h | 25 | ||||
-rw-r--r-- | source/sv_main.c | 34 |
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" ); } } } |