diff options
author | Andrey Nazarov <skuller@skuller.net> | 2010-09-07 16:46:20 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2010-09-07 16:46:20 +0000 |
commit | 8f76ac32949a283e000b27f6acd4359aa5de1806 (patch) | |
tree | 39c2088e732aed475e54680eec3ad13733994c26 | |
parent | 9622b711c2b8e4641a778e144cf20ebfc87b12de (diff) |
Re-resolve master servers after one day.
Don't spam server console with ping acks from masters.
Added ‘listmasters’ command for checking IPs and ack times.
Send the first heartbeat soon after server initialization.
-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" ); } } } |