示例#1
0
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 );
		}
	}
}
示例#2
0
/*
================
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 );
}