void SV_MasterHeartbeat( const char *hbname ) { int i; int netenabled; netenabled = Cvar_VariableIntegerValue( "net_enabled" ); // "dedicated 1" is for LAN play, "dedicated 2" is for Internet play if ( !com_dedicated || com_dedicated->integer != 2 || !( netenabled & ( NET_ENABLEV4 | NET_ENABLEV6 ) ) ) { return; // only dedicated servers send heartbeats } // if not time yet, don't send anything if ( svs.time < svs.nextHeartbeatTime ) { return; } svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC; SV_ResolveMasterServers(); // send to group masters for ( i = 0; i < MAX_MASTER_SERVERS; i++ ) { if ( masterServerAddr[ i ].ipv4.type == NA_BAD && masterServerAddr[ i ].ipv6.type == NA_BAD ) { continue; } Com_Printf(_( "Sending heartbeat to %s\n"), sv_master[ i ]->string ); // this command should be changed if the server info / status format // ever incompatibly changes if ( masterServerAddr[ i ].ipv4.type != NA_BAD ) { NET_OutOfBandPrint( NS_SERVER, masterServerAddr[ i ].ipv4, "heartbeat %s\n", hbname ); } if ( masterServerAddr[ i ].ipv6.type != NA_BAD ) { NET_OutOfBandPrint( NS_SERVER, masterServerAddr[ i ].ipv6, "heartbeat %s\n", hbname ); } } }
/* ================ SVC_Info Responds with a short info message that should be enough to determine if a user is interested in a server to do a full status ================ */ void SVC_Info( netadr_t from, const Cmd::Args& args ) { int i, count, botCount; char infostring[ MAX_INFO_STRING ]; if ( args.Argc() < 2 ) { return; } const char *challenge = args.Argv(1).c_str(); /* * Check whether Cmd_Argv(1) has a sane length. This was not done in the original Quake3 version which led * to the Infostring bug discovered by Luigi Auriemma. See http://aluigi.altervista.org/ for the advisory. */ // A maximum challenge length of 128 should be more than plenty. if ( strlen( challenge ) > MAX_CHALLENGE_LEN ) { return; } //bani - bugtraq 12534 if ( !SV_VerifyChallenge( challenge ) ) { return; } SV_ResolveMasterServers(); // don't count privateclients botCount = count = 0; for ( i = sv_privateClients->integer; i < sv_maxclients->integer; i++ ) { if ( svs.clients[ i ].state >= CS_CONNECTED ) { if ( SV_IsBot(&svs.clients[ i ]) ) { ++botCount; } else { ++count; } } } infostring[ 0 ] = 0; // echo back the parameter to status. so servers can use it as a challenge // to prevent timed spoofed reply packets that add ghost servers Info_SetValueForKey( infostring, "challenge", challenge, false ); // If the master server listens on IPv4 and IPv6, we want to send the // most recent challenge received from it over the OTHER protocol for ( i = 0; i < MAX_MASTER_SERVERS; i++ ) { // First, see if the challenge was sent by this master server if ( !NET_CompareBaseAdr( from, masterServerAddr[ i ].ipv4 ) && !NET_CompareBaseAdr( from, masterServerAddr[ i ].ipv6 ) ) { continue; } // It was - if the saved challenge is for the other protocol, send it and record the current one if ( challenges[ i ].type == NA_IP || challenges[ i ].type == NA_IP6 ) { if ( challenges[ i ].type != from.type ) { Info_SetValueForKey( infostring, "challenge2", challenges[ i ].text, false ); challenges[ i ].type = from.type; strcpy( challenges[ i ].text, challenge ); break; } } // Otherwise record the current one regardless and check the next server challenges[ i ].type = from.type; strcpy( challenges[ i ].text, challenge ); } Info_SetValueForKey( infostring, "protocol", va( "%i", PROTOCOL_VERSION ), false ); Info_SetValueForKey( infostring, "hostname", sv_hostname->string, false ); Info_SetValueForKey( infostring, "serverload", va( "%i", svs.serverLoad ), false ); Info_SetValueForKey( infostring, "mapname", sv_mapname->string, false ); Info_SetValueForKey( infostring, "clients", va( "%i", count ), false ); Info_SetValueForKey( infostring, "bots", va( "%i", botCount ), false ); Info_SetValueForKey( infostring, "sv_maxclients", va( "%i", sv_maxclients->integer - sv_privateClients->integer ), false ); Info_SetValueForKey( infostring, "pure", va( "%i", sv_pure->integer ), false ); if ( sv_statsURL->string[0] ) { Info_SetValueForKey( infostring, "stats", sv_statsURL->string, false ); } #ifdef USE_VOIP if ( sv_voip->integer ) { Info_SetValueForKey( infostring, "voip", va( "%i", sv_voip->integer ), false ); } #endif if ( sv_minPing->integer ) { Info_SetValueForKey( infostring, "minPing", va( "%i", sv_minPing->integer ), false ); } if ( sv_maxPing->integer ) { Info_SetValueForKey( infostring, "maxPing", va( "%i", sv_maxPing->integer ), false ); } Info_SetValueForKey( infostring, "gamename", GAMENAME_STRING, false ); // Arnout: to be able to filter out Quake servers NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring ); }