예제 #1
0
static void server_WriteUpdateInfo( BYTESTREAM_s *pByteStream, int iUpdateType )
{
	NETWORK_WriteByte( &g_MessageBuffer.ByteStream, iUpdateType );

	switch ( iUpdateType )
	{
	// Update the player data.
	case SVRCU_PLAYERDATA:

		NETWORK_WriteByte( pByteStream, SERVER_CountPlayers( true ));
		for ( unsigned int i = 0; i < MAXPLAYERS; i++ )
		{
			if ( playeringame[i] )
			{
				FString		fsName;

				fsName.Format( "%s", players[i].userinfo.netname );
				V_RemoveColorCodes( fsName );
				NETWORK_WriteString( pByteStream, fsName );
			}
		}
		break;
	// Update the current map.
	case SVRCU_MAP:

		NETWORK_WriteString( pByteStream, level.mapname );
		break;
	// Update the number of other admins.
	case SVRCU_ADMINCOUNT:

		NETWORK_WriteByte( pByteStream, g_AuthedClients.Size() - 1 );
		break;
	}
}
예제 #2
0
void SERVER_RCON_Print( const char *pszString )
{
	for ( unsigned int i = 0; i < g_AuthedClients.Size( ); i++ )
	{
		NETWORK_ClearBuffer( &g_MessageBuffer );
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_MESSAGE );
		NETWORK_WriteString( &g_MessageBuffer.ByteStream, pszString );
		NETWORK_LaunchPacket( &g_MessageBuffer, g_AuthedClients[i].Address );
	}

	//==========================================
	// Add this to the cache of recent messages.
	//==========================================

	if ( g_RecentConsoleLines.size() >= 32 )
		g_RecentConsoleLines.pop_front();

	FString			fsLogged = pszString;
	time_t			tNow = time(0);
	struct	tm		*pTimeInfo = localtime( &tNow );

	if ( pTimeInfo->tm_hour < 12 )
		fsLogged.Format( "[%02d:%02d:%02d am] %s ", ( pTimeInfo->tm_hour == 0 ) ? 12 : pTimeInfo->tm_hour, pTimeInfo->tm_min, pTimeInfo->tm_sec, pszString );
	else
		fsLogged.Format( "[%02d:%02d:%02d pm] %s", ( pTimeInfo->tm_hour == 12 ) ? 12 : pTimeInfo->tm_hour % 12, pTimeInfo->tm_min, pTimeInfo->tm_sec, pszString );

	g_RecentConsoleLines.push_back( fsLogged );
}
예제 #3
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
//*****************************************************************************
//
void MASTERSERVER_RequestServerVerification( const SERVER_s &Server )
{
	NETWORK_ClearBuffer( &g_MessageBuffer );
	NETWORK_WriteByte( &g_MessageBuffer.ByteStream, MASTER_SERVER_VERIFICATION );
	NETWORK_WriteString( &g_MessageBuffer.ByteStream, Server.MasterBanlistVerificationString.c_str() );
	NETWORK_WriteLong( &g_MessageBuffer.ByteStream, Server.ServerVerificationInt );
	NETWORK_LaunchPacket( &g_MessageBuffer, Server.Address );
}
예제 #4
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
	void startPacket ( ) {
		NETWORK_ClearBuffer( &_netBuffer );
		NETWORK_WriteByte( &_netBuffer.ByteStream, MASTER_SERVER_BANLISTPART );
		NETWORK_WriteString( &_netBuffer.ByteStream, _destServer.MasterBanlistVerificationString.c_str() );
		NETWORK_WriteByte( &_netBuffer.ByteStream, _ulPacketNum );
		_ulSizeOfPacket = 2 + _destServer.MasterBanlistVerificationString.length();
		++_ulPacketNum;
	}
예제 #5
0
//*****************************************************************************
//
void SERVER_AUTH_Negotiate ( const char *Username, const unsigned int ClientSessionID )
{
	NETWORK_ClearBuffer( &g_AuthServerBuffer );
	NETWORK_WriteLong( &g_AuthServerBuffer.ByteStream, SERVER_AUTH_NEGOTIATE );
	NETWORK_WriteByte( &g_AuthServerBuffer.ByteStream, AUTH_PROTOCOL_VERSION );
	NETWORK_WriteLong( &g_AuthServerBuffer.ByteStream, ClientSessionID);
	NETWORK_WriteString( &g_AuthServerBuffer.ByteStream, Username );
	NETWORK_LaunchPacket( &g_AuthServerBuffer, g_AuthServerAddress );
}
예제 #6
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
//*****************************************************************************
//
void MASTERSERVER_SendBanlistToServer( const SERVER_s &Server )
{
	// [BB] If the server supports it, potentially split the ban list over multiple packets.
	if ( Server.iServerRevision >= 2907 )
	{
		BanlistPacketSender sender ( Server );
		sender.start();

		// Write all the bans.
		for ( unsigned int i = 0; i < g_BannedIPs.size( ); ++i )
			sender.writeBanEntry ( g_BannedIPs.getEntryAsString( i, false, false, false ).c_str( ), MSB_BAN );

		// Write all the exceptions.
		for ( unsigned int i = 0; i < g_BannedIPExemptions.size( ); ++i )
			sender.writeBanEntry ( g_BannedIPExemptions.getEntryAsString( i, false, false, false ).c_str( ), MSB_BANEXEMPTION );

		sender.end();
	}
	else
	{
		NETWORK_ClearBuffer( &g_MessageBuffer );
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, MASTER_SERVER_BANLIST );
		// [BB] If the server sent us a verification string, send it along with the ban list.
		// This allows the server to verify that the list actually was sent from our master
		// (and is not just a packet with forged source IP).
		if ( Server.MasterBanlistVerificationString.size() )
			NETWORK_WriteString( &g_MessageBuffer.ByteStream, Server.MasterBanlistVerificationString.c_str() );

		// Write all the bans.
		NETWORK_WriteLong( &g_MessageBuffer.ByteStream, g_BannedIPs.size( ));
		for ( ULONG i = 0; i < g_BannedIPs.size( ); i++ )
			NETWORK_WriteString( &g_MessageBuffer.ByteStream, g_BannedIPs.getEntryAsString( i, false, false, false ).c_str( ));

		// Write all the exceptions.
		NETWORK_WriteLong( &g_MessageBuffer.ByteStream, g_BannedIPExemptions.size( ));
		for ( ULONG i = 0; i < g_BannedIPExemptions.size( ); i++ )
			NETWORK_WriteString( &g_MessageBuffer.ByteStream, g_BannedIPExemptions.getEntryAsString( i, false, false, false ).c_str( ));

		NETWORK_LaunchPacket( &g_MessageBuffer, Server.Address );
	}
	Server.bHasLatestBanList = true;
	Server.bVerifiedLatestBanList = false;
	printf( "-> Banlist sent to %s.\n", NETWORK_AddressToString( Server.Address ));
}
예제 #7
0
static void server_rcon_HandleNewConnection( NETADDRESS_s Address,  int iProtocolVersion )
{
	// Banned client? Notify him, ignore him, and get out of here.
	if ( SERVERBAN_IsIPBanned( Address ))
	{
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_BANNED );
		NETWORK_LaunchPacket( &g_MessageBuffer, Address );
		g_BadRequestFloodQueue.addAddress( Address, gametic / 1000 );
		return;
	}

	// Old protocol version? Notify, ignore, and quit.
	if ( iProtocolVersion < MIN_PROTOCOL_VERSION )
	{
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_OLDPROTOCOL );
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, PROTOCOL_VERSION );
		NETWORK_WriteString( &g_MessageBuffer.ByteStream, DOTVERSIONSTR );
		NETWORK_LaunchPacket( &g_MessageBuffer, Address );
		g_BadRequestFloodQueue.addAddress( Address, gametic / 1000 );
		return;
	}

	// Check if there's already a user at this address. Remove him if so (must be reconnecting).
	// This ensures that each address never has more than one entry (since this is the only function that gives out new candidate slots).
	int iIndex = server_rcon_FindCandidate( Address );
	if ( iIndex != -1 )
		g_Candidates.Delete( iIndex );
	iIndex = server_rcon_FindClient( Address );
	if ( iIndex != -1 )
		g_AuthedClients.Delete( iIndex );

	// Create a slot for him, and request his password.
	RCONCANDIDATE_s		Candidate;
	Candidate.iLastMessageTic = gametic;
	Candidate.Address = Address;
	server_rcon_CreateSalt( Candidate.szSalt );
	g_Candidates.Push( Candidate );

	NETWORK_ClearBuffer( &g_MessageBuffer );
	NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_SALT );
	NETWORK_WriteString( &g_MessageBuffer.ByteStream, Candidate.szSalt );
	NETWORK_LaunchPacket( &g_MessageBuffer, Address );
}
예제 #8
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
	void writeBanEntry ( const char *BanEntry, const int EntryType )
	{
		const unsigned long ulCommandSize = 1 + strlen ( BanEntry );

		// [BB] If this command doesn't fit into the current packet, start a new one.
		if ( _ulSizeOfPacket + ulCommandSize > _ulMaxPacketSize - 1 )
			finishCurrentAndStartNewPacket();

		NETWORK_WriteByte( &_netBuffer.ByteStream, EntryType );
		NETWORK_WriteString( &_netBuffer.ByteStream, BanEntry );
		_ulSizeOfPacket += ulCommandSize;
	}
예제 #9
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
static void main_SendPassword( const char *pszSalt )
{
	char	szString[512];

	main_UpdateStatusbar( "Authenticating..." );
	FString fsString, fsHash;
	fsString.Format( "%s%s", pszSalt, g_szPassword );
	CMD5Checksum::GetMD5( reinterpret_cast<const BYTE *>(fsString.GetChars()), fsString.Len(), fsHash );

	NETWORK_ClearBuffer( &g_MessageBuffer );
	NETWORK_WriteByte( &g_MessageBuffer.ByteStream, CLRC_PASSWORD );
	NETWORK_WriteString( &g_MessageBuffer.ByteStream, fsHash.GetChars() );
	NETWORK_LaunchPacket( &g_MessageBuffer, g_ServerAddress );
	time( &g_tLastSentCommand );
}
예제 #10
0
//*****************************************************************************
//
void SERVER_MASTER_SendServerInfo( netadr_t Address, ULONG ulFlags, ULONG ulTime )
{
	UCVarValue	Val;
	char		szAddress[4][4];
	ULONG		ulIdx;
	ULONG		ulBits;
	ULONG		ulNumPWADs;

	// Let's just use the master server buffer! It gets cleared again when we need it anyway!
	NETWORK_ClearBuffer( &g_MasterServerBuffer );

	// First, check to see if we've been queried by this address recently.
	if ( g_lStoredQueryIPHead != g_lStoredQueryIPTail )
	{
		ulIdx = g_lStoredQueryIPHead;
		while ( ulIdx != (ULONG)g_lStoredQueryIPTail )
		{
			// Check to see if this IP exists in our stored query IP list. If it does, then
			// ignore it, since it queried us less than 10 seconds ago.
			if ( NETWORK_CompareAddress( Address, g_StoredQueryIPs[ulIdx].Address, true ))
			{
				// Write our header.
				NETWORK_WriteLong( &g_MasterServerBuffer, SERVER_LAUNCHER_IGNORING );

				// Send the time the launcher sent to us.
				NETWORK_WriteLong( &g_MasterServerBuffer, ulTime );

				// Send the packet.
//				NETWORK_LaunchPacket( &g_MasterServerBuffer, Address, true );
				NETWORK_LaunchPacket( &g_MasterServerBuffer, Address );

				if ( sv_showlauncherqueries )
					Printf( "Ignored IP launcher challenge.\n" );

				// Nothing more to do here.
				return;
			}

			ulIdx++;
			ulIdx = ulIdx % MAX_STORED_QUERY_IPS;
		}
	}

	// Now, check to see if this IP has been banend from this server.
	itoa( Address.ip[0], szAddress[0], 10 );
	itoa( Address.ip[1], szAddress[1], 10 );
	itoa( Address.ip[2], szAddress[2], 10 );
	itoa( Address.ip[3], szAddress[3], 10 );
	if (( sv_enforcebans ) && ( SERVERBAN_IsIPBanned( szAddress[0], szAddress[1], szAddress[2], szAddress[3] )))
	{
		// Write our header.
		NETWORK_WriteLong( &g_MasterServerBuffer, SERVER_LAUNCHER_BANNED );

		// Send the time the launcher sent to us.
		NETWORK_WriteLong( &g_MasterServerBuffer, ulTime );

		// Send the packet.
		NETWORK_LaunchPacket( &g_MasterServerBuffer, Address );

		if ( sv_showlauncherqueries )
			Printf( "Denied BANNED IP launcher challenge.\n" );

		// Nothing more to do here.
		return;
	}

	// This IP didn't exist in the list. and it wasn't banned.
	// So, add it, and keep it there for 10 seconds.
	g_StoredQueryIPs[g_lStoredQueryIPTail].Address = Address;
	g_StoredQueryIPs[g_lStoredQueryIPTail].lNextAllowedGametic = gametic + ( TICRATE * ( sv_queryignoretime ));

	g_lStoredQueryIPTail++;
	g_lStoredQueryIPTail = g_lStoredQueryIPTail % MAX_STORED_QUERY_IPS;
	if ( g_lStoredQueryIPTail == g_lStoredQueryIPHead )
		Printf( "SERVER_MASTER_SendServerInfo: WARNING! g_lStoredQueryIPTail == g_lStoredQueryIPHead\n" );

	// Write our header.
	NETWORK_WriteLong( &g_MasterServerBuffer, SERVER_LAUNCHER_CHALLENGE );

	// Send the time the launcher sent to us.
	NETWORK_WriteLong( &g_MasterServerBuffer, ulTime );

	// Send our version.
	NETWORK_WriteString( &g_MasterServerBuffer, DOTVERSIONSTR );

	// Send the information about the data that will be sent.
	ulBits = ulFlags;

	// If the launcher desires to know the team damage, but we're not in a game mode where
	// team damage applies, then don't send back team damage information.
	if (( teamplay || teamgame || teamlms || teampossession || teamcoop || (( deathmatch == false ) && ( teamgame == false ))) == false )
	{
		if ( ulBits & SQF_TEAMDAMAGE )
			ulBits &= ~SQF_TEAMDAMAGE;
	}

	// If the launcher desires to know the team score, but we're not in a game mode where
	// teams have scores, then don't send back team score information.
	if (( teamplay || teamgame || teamlms || teampossession || teamcoop ) == false )
	{
		if ( ulBits & SQF_TEAMSCORES )
			ulBits &= ~SQF_TEAMSCORES;
	}

	// If the launcher wants to know player data, then we have to tell them how many players
	// are in the server.
	if ( ulBits & SQF_PLAYERDATA )
		ulBits |= SQF_NUMPLAYERS;

	NETWORK_WriteLong( &g_MasterServerBuffer, ulBits );

	// Send the server name.
	if ( ulBits & SQF_NAME )
	{
		Val = sv_hostname.GetGenericRep( CVAR_String );
		NETWORK_WriteString( &g_MasterServerBuffer, Val.String );
	}

	// Send the website URL.
	if ( ulBits & SQF_URL )
	{
		Val = sv_website.GetGenericRep( CVAR_String );
		NETWORK_WriteString( &g_MasterServerBuffer, Val.String );
	}

	// Send the host's e-mail address.
	if ( ulBits & SQF_EMAIL )
	{
		Val = sv_hostemail.GetGenericRep( CVAR_String );
		NETWORK_WriteString( &g_MasterServerBuffer, Val.String );
	}

	if ( ulBits & SQF_MAPNAME )
		NETWORK_WriteString( &g_MasterServerBuffer, level.mapname );

	if ( ulBits & SQF_MAXCLIENTS )
		NETWORK_WriteByte( &g_MasterServerBuffer, sv_maxclients );

	if ( ulBits & SQF_MAXPLAYERS )
		NETWORK_WriteByte( &g_MasterServerBuffer, sv_maxplayers );

	// Send out the PWAD information.
	if ( ulBits & SQF_PWADS )
	{
		ulNumPWADs = 0;
		for ( ulIdx = 0; Wads.GetWadName( ulIdx ) != NULL; ulIdx++ )
		{
			// Skip the IWAD file index, skulltag.wad/pk3, and files that were automatically
			// loaded from subdirectories (such as skin files).
			if (( ulIdx == FWadCollection::IWAD_FILENUM ) ||
				( stricmp( Wads.GetWadName( ulIdx ), "scoredoomst.wad" ) == 0 ) ||
				( stricmp( Wads.GetWadName( ulIdx ), "scoredoomst.pk3" ) == 0 ) ||
				( Wads.GetLoadedAutomatically( ulIdx )))
			{
				continue;
			}

			ulNumPWADs++;
		}

		NETWORK_WriteByte( &g_MasterServerBuffer, ulNumPWADs );
		for ( ulIdx = 0; Wads.GetWadName( ulIdx ) != NULL; ulIdx++ )
		{
			// Skip the IWAD file index, skulltag.wad/pk3, and files that were automatically
			// loaded from subdirectories (such as skin files).
			if (( ulIdx == FWadCollection::IWAD_FILENUM ) ||
				( stricmp( Wads.GetWadName( ulIdx ), "scoredoomst.wad" ) == 0 ) ||
				( stricmp( Wads.GetWadName( ulIdx ), "scoredoomst.pk3" ) == 0 ) ||
				( Wads.GetLoadedAutomatically( ulIdx )))
			{
				continue;
			}

			NETWORK_WriteString( &g_MasterServerBuffer, (char *)Wads.GetWadName( ulIdx ));
		}
	}

	if ( ulBits & SQF_GAMETYPE )
	{
		NETWORK_WriteByte( &g_MasterServerBuffer, GAME_GetGameType( ));
		NETWORK_WriteByte( &g_MasterServerBuffer, instagib );
		NETWORK_WriteByte( &g_MasterServerBuffer, buckshot );
	}

	if ( ulBits & SQF_GAMENAME )
		NETWORK_WriteString( &g_MasterServerBuffer, SERVER_MASTER_GetGameName( ));

	if ( ulBits & SQF_IWAD )
		NETWORK_WriteString( &g_MasterServerBuffer, (char *)Wads.GetWadName( FWadCollection::IWAD_FILENUM ));

	if ( ulBits & SQF_FORCEPASSWORD )
		NETWORK_WriteByte( &g_MasterServerBuffer, sv_forcepassword );

	if ( ulBits & SQF_FORCEJOINPASSWORD )
		NETWORK_WriteByte( &g_MasterServerBuffer, sv_forcejoinpassword );

	if ( ulBits & SQF_GAMESKILL )
		NETWORK_WriteByte( &g_MasterServerBuffer, gameskill );

	if ( ulBits & SQF_BOTSKILL )
		NETWORK_WriteByte( &g_MasterServerBuffer, botskill );

	if ( ulBits & SQF_DMFLAGS )
	{
		NETWORK_WriteLong( &g_MasterServerBuffer, dmflags );
		NETWORK_WriteLong( &g_MasterServerBuffer, dmflags2 );
		NETWORK_WriteLong( &g_MasterServerBuffer, compatflags );
	}

	if ( ulBits & SQF_LIMITS )
	{
		NETWORK_WriteShort( &g_MasterServerBuffer, fraglimit );
		NETWORK_WriteShort( &g_MasterServerBuffer, (SHORT)timelimit );
		if ( timelimit )
		{
			LONG	lTimeLeft;

			lTimeLeft = (LONG)( timelimit - ( level.totaltime / ( TICRATE * 60 ))); //ghk
			if ( lTimeLeft < 0 )
				lTimeLeft = 0;
			NETWORK_WriteShort( &g_MasterServerBuffer, lTimeLeft );
		}
		NETWORK_WriteShort( &g_MasterServerBuffer, duellimit );
		NETWORK_WriteLong( &g_MasterServerBuffer, pointlimit ); //ghk writelong
		NETWORK_WriteShort( &g_MasterServerBuffer, winlimit );
	}

	// Send the team damage scale.
	if ( teamplay || teamgame || teamlms || teampossession || teamcoop || (( deathmatch == false ) && ( teamgame == false )))
	{
		if ( ulBits & SQF_TEAMDAMAGE )
			NETWORK_WriteFloat( &g_MasterServerBuffer, teamdamage );
	}

	// Send the team scores.
	if ( teamplay || teamgame || teamlms || teampossession || teamcoop )
	{
		if ( ulBits & SQF_TEAMSCORES )
		{
			for ( ulIdx = 0; ulIdx < NUM_TEAMS; ulIdx++ )
			{
				if ( teamplay )
					NETWORK_WriteShort( &g_MasterServerBuffer, TEAM_GetFragCount( ulIdx ));
				else if ( teamlms )
					NETWORK_WriteShort( &g_MasterServerBuffer, TEAM_GetWinCount( ulIdx ));
				else
					NETWORK_WriteShort( &g_MasterServerBuffer, TEAM_GetScore( ulIdx )); //ghk writelong?
			}
		}
	}

	if ( ulBits & SQF_NUMPLAYERS )
		NETWORK_WriteByte( &g_MasterServerBuffer, SERVER_CalcNumPlayers( ));

	if ( ulBits & SQF_PLAYERDATA )
	{
		for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ )
		{
			if ( playeringame[ulIdx] == false )
				continue;

			NETWORK_WriteString( &g_MasterServerBuffer, players[ulIdx].userinfo.netname );
			if ( teamgame || possession || teampossession || cooperative || teamcoop )
				NETWORK_WriteLong( &g_MasterServerBuffer, players[ulIdx].lPointCount );//ghk writelong
			else if ( deathmatch )
				NETWORK_WriteLong( &g_MasterServerBuffer, players[ulIdx].fragcount ); //ghk writelong
			else
				NETWORK_WriteLong( &g_MasterServerBuffer, players[ulIdx].killcount ); //ghk writelong

			NETWORK_WriteShort( &g_MasterServerBuffer, players[ulIdx].ulPing );
			NETWORK_WriteByte( &g_MasterServerBuffer, PLAYER_IsTrueSpectator( &players[ulIdx] ));
			NETWORK_WriteByte( &g_MasterServerBuffer, players[ulIdx].bIsBot );

			if ( teamplay || teamgame || teamlms || teampossession || teamcoop )
			{
				if ( players[ulIdx].bOnTeam == false )
					NETWORK_WriteByte( &g_MasterServerBuffer, 255 );
				else
					NETWORK_WriteByte( &g_MasterServerBuffer, players[ulIdx].ulTeam );
			}

			NETWORK_WriteByte( &g_MasterServerBuffer, players[ulIdx].ulTime / ( TICRATE * 60 ));
		}
	}

//	NETWORK_LaunchPacket( &g_MasterServerBuffer, Address, true );
	NETWORK_LaunchPacket( &g_MasterServerBuffer, Address );
}
예제 #11
0
static void server_rcon_HandleLogin( int iCandidateIndex, const char *pszHash )
{
	// If there's no slot, the candidate must have timed out, or is hacking. Bye!
	if ( iCandidateIndex == -1 )
		return;

	// Combine the salt and password, and hash it.
	FString fsString, fsCorrectHash;
	fsString.Format( "%s%s", g_Candidates[iCandidateIndex].szSalt, sv_rconpassword.GetGenericRep(CVAR_String).String );	
	CMD5Checksum::GetMD5( reinterpret_cast<const BYTE *>(fsString.GetChars()), fsString.Len(), fsCorrectHash );

	// Compare that to what he sent us.
	// Printf("Mine: %s\nTheirs: %s\n", fsCorrectHash, pszHash );
	NETWORK_ClearBuffer( &g_MessageBuffer );
	// [BB] Do not allow the server to let anybody use RCON in case sv_rconpassword is empty.
	if ( fsCorrectHash.Compare( pszHash ) || ( strlen( sv_rconpassword.GetGenericRep(CVAR_String).String ) == 0 ) )
	{
		// Wrong password.
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_INVALIDPASSWORD );
		NETWORK_LaunchPacket( &g_MessageBuffer, g_Candidates[iCandidateIndex].Address ); // [RC] Note: Be sure to finish any packets before calling Printf(). Otherwise SERVER_RCON_Print will clear your buffer.

		// To prevent mass password flooding, ignore the IP for a few seconds.
		g_BadRequestFloodQueue.addAddress( g_Candidates[iCandidateIndex].Address, gametic / 1000 );

		Printf( "Failed RCON login from %s. Ignoring IP for 10 seconds...\n", NETWORK_AddressToString( g_Candidates[iCandidateIndex].Address ));
	}
	else
	{		
		// [BB] Since we log when RCON clients disconnect, we should also log when they connect.
		// Do this before we do anything else so that this message is sent to the new RCON client
		// with the console history.
		Printf( "RCON client at %s connected.\n", NETWORK_AddressToString( g_Candidates[iCandidateIndex].Address ));

		// Correct password. Promote him to an authed client.
		RCONCLIENT_s Client;
		Client.Address = g_Candidates[iCandidateIndex].Address;
		Client.iLastMessageTic = gametic;
		g_AuthedClients.Push( Client );

		NETWORK_ClearBuffer( &g_MessageBuffer );
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_LOGGEDIN );

		// Tell him some info about the server.
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, PROTOCOL_VERSION );
		NETWORK_WriteString( &g_MessageBuffer.ByteStream, sv_hostname.GetGenericRep( CVAR_String ).String );
		
		// Send updates.
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, NUM_RCON_UPDATES );
		for ( int i = 0; i < NUM_RCON_UPDATES; i++ )
			server_WriteUpdateInfo( &g_MessageBuffer.ByteStream, i );

		// Send the console history.
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, g_RecentConsoleLines.size() );
		for( std::list<FString>::iterator i = g_RecentConsoleLines.begin(); i != g_RecentConsoleLines.end(); ++i )
			NETWORK_WriteString( &g_MessageBuffer.ByteStream, *i );

		NETWORK_LaunchPacket( &g_MessageBuffer, g_Candidates[iCandidateIndex].Address );
		SERVER_RCON_UpdateInfo( SVRCU_ADMINCOUNT );
	}

	// Remove his temporary slot.	
	g_Candidates.Delete( iCandidateIndex );
}
예제 #12
0
void SERVER_RCON_ParseMessage( NETADDRESS_s Address, LONG lMessage, BYTESTREAM_s *pByteStream )
{
	int iIndex = -1;

	switch ( lMessage )
	{
	case CLRC_BEGINCONNECTION:

		server_rcon_HandleNewConnection( Address, NETWORK_ReadByte( pByteStream ));
		break;
	case CLRC_PASSWORD:

		server_rcon_HandleLogin( server_rcon_FindCandidate( Address ), NETWORK_ReadString( pByteStream ));
		break;	
	case CLRC_PONG:

		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )	
			g_AuthedClients[iIndex].iLastMessageTic = gametic;
		break;
	case CLRC_COMMAND:

		// Execute the command (if this came from an admin).
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )
		{
			const char *szCommand = NETWORK_ReadString( pByteStream );
			// [BB] Log the command before adding it. If we don't have a server GUI, the command
			// is executed immediately and may cause Skulltag to exit before the command is logged.
			Printf( "-> %s (RCON by %s)\n", szCommand, NETWORK_AddressToString( Address ) );
			SERVER_AddCommand( szCommand );
			g_AuthedClients[iIndex].iLastMessageTic = gametic;
		}
		break;
	case CLRC_DISCONNECT:
		
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )	
		{
			g_AuthedClients.Delete( iIndex );
			SERVER_RCON_UpdateInfo( SVRCU_ADMINCOUNT );
			Printf( "RCON client at %s disconnected.\n", NETWORK_AddressToString( Address ));
		}
		break;
	case CLRC_TABCOMPLETE:

		// [TP] RCON client wishes to tab-complete
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )
		{
			const char* part = NETWORK_ReadString( pByteStream );
			TArray<FString> list = C_GetTabCompletes( part );
			NETWORK_ClearBuffer( &g_MessageBuffer );

			// [TP] Let's not send too many of these though
			if ( list.Size() < 50 )
			{
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_TABCOMPLETE );
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, list.Size() );

				for ( unsigned i = 0; i < list.Size(); ++i )
					NETWORK_WriteString( &g_MessageBuffer.ByteStream, list[i] );
			}
			else
			{
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_TOOMANYTABCOMPLETES );
				NETWORK_WriteShort( &g_MessageBuffer.ByteStream, list.Size() );
			}

			NETWORK_LaunchPacket( &g_MessageBuffer, g_AuthedClients[iIndex].Address );
		}
		break;
	}
}
예제 #13
0
파일: main.cpp 프로젝트: WChrisK/Zandronum
BOOL CALLBACK main_RCONDialogCallback( HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam )
{
	char	szBuffer[128];

	switch ( Message )
	{
	case WM_CTLCOLORSTATIC:

		switch ( GetDlgCtrlID( (HWND) lParam ))
		{
		// Paint these two labels (and the disconnct button's background) white.
		case IDCANCEL:
		case IDC_STATUS:
		case IDC_SERVERSUBINFO:

			return (LRESULT) g_hWhiteBrush;
		// Ignore everything else.
		default:

			return NULL;
		}
		break;
	case WM_PAINT:
		{
			// Paint the top of the form white.
			PAINTSTRUCT Ps;
			RECT r;
			r.left = 0;
			r.top = 0;
			r.bottom = 48;
			r.right = 800;
			main_PaintRectangle( BeginPaint(hDlg, &Ps), &r, RGB(255, 255, 255));
		}
		break;
	case WM_INITDIALOG:
		
		// Hide the old dialog, and take its place.
		ShowWindow( g_hDlg, SW_HIDE );
		g_hDlg = hDlg;		

		SendDlgItemMessage( hDlg, IDC_CONSOLEBOX, EM_SETLIMITTEXT, 4096, 0 );
		SendDlgItemMessage( hDlg, IDC_INPUTBOX, EM_SETLIMITTEXT, 256, 0 );
		SetWindowText( hDlg, g_szHostname );
		main_SetState( STATE_CONNECTED );
		Printf( "\nMap: %s\n", g_szMapname );

		// Fill the console with the received history.
		sprintf( szBuffer, "Connected to \"%s\".", g_szHostname );
		SetDlgItemText( hDlg, IDC_CONSOLEBOX, szBuffer );
		SetDlgItemText( hDlg, IDC_STATUS, szBuffer );
		main_UpdateTrayTooltip( szBuffer );
		Printf_NoTimestamp( "\n" );
		for( std::list<FString>::iterator i = g_RecentConsoleHistory.begin(); i != g_RecentConsoleHistory.end(); ++i )
			Printf_NoTimestamp( "%s", *i );
		g_RecentConsoleHistory.clear();

		// Set up the top, white section.
		SendMessage( GetDlgItem( g_hDlg, IDC_STATUS ), WM_SETFONT, (WPARAM) CreateFont( 13, 0, 0, 0, 600, 0, 0, 0, 0, 0, 0, 0, 0, "Tahoma" ), (LPARAM) 1 );
		LOGBRUSH LogBrush;
		LogBrush.lbStyle = BS_SOLID;
		LogBrush.lbColor = RGB( 255, 255, 255 );
		g_hWhiteBrush = CreateBrushIndirect( &LogBrush );
		main_UpdateServerStatus( );

		// Set up the player list
		LVCOLUMN	ColumnData;
		ColumnData.mask = LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
		ColumnData.fmt = LVCFMT_LEFT;
		ColumnData.cx = 192;
		ColumnData.pszText = "Name";
		ColumnData.cchTextMax = 64;
		ColumnData.iSubItem = 0;
		SendDlgItemMessage( hDlg, IDC_PLAYERLIST, LVM_INSERTCOLUMN, COLUMN_NAME, (LPARAM)&ColumnData );

		// Add the cached list of players.
		LVITEM		Item;
		Item.mask = LVIF_TEXT;
		Item.iSubItem = COLUMN_NAME;
		Item.iItem = MAXPLAYERS;
		while ( g_InitialPlayers.size( ) )
		{
			Item.pszText = (LPSTR) g_InitialPlayers.front( ).GetChars( );
			g_InitialPlayers.pop_front( );
			SendDlgItemMessage( g_hDlg, IDC_PLAYERLIST, LVM_INSERTITEM, 0, (LPARAM)&Item ) ;
		}

		// Load the icon.
		SendMessage( hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) (HICON) LoadImage( g_hInst,	MAKEINTRESOURCE( AAA_MAIN_ICON ), IMAGE_ICON, 16, 16, LR_SHARED ));
		SendMessage( hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)LoadIcon( g_hInst, MAKEINTRESOURCE( AAA_MAIN_ICON )));

		// Set up the status bar.
		g_hDlgStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, (LPCTSTR)NULL, hDlg, IDC_STATIC);

		g_bRCONDialogVisible = true;
		break;
	case WM_COMMAND:

			switch ( LOWORD( wParam ))
			{

			// This also occurs when esc is pressed.
			case IDCANCEL:

				main_Quit( );
				break;

			// "Send" button.
			case IDC_SEND:
			
				char	szCommand[256];

				GetDlgItemText( hDlg, IDC_INPUTBOX, szCommand, sizeof( szCommand ));
				NETWORK_ClearBuffer( &g_MessageBuffer );
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, CLRC_COMMAND );

				if ( szCommand[0] == ':' ) // If the text in the send buffer begins with a :, the admin is just talking.
				{
					char	szBuffer2[256 + 4];

					sprintf( szBuffer2, "say %s", szCommand + 1 );
					NETWORK_WriteString( &g_MessageBuffer.ByteStream, szBuffer2 );
					break;
				}
				else if ( szCommand[0] == '/' ) // If the text in the send buffer begins with a slash, error out -- Skulltag used to require you to do this to send commands.
				{
					Printf( "You longer have to prefix commands with a / to send them.\n" );
					SetDlgItemText( hDlg, IDC_INPUTBOX, szCommand + 1 );
					SendMessage( GetDlgItem( hDlg, IDC_INPUTBOX ), EM_SETSEL, strlen( szCommand ) - 1, strlen( szCommand ) - 1 );
					break;
				}
				else
					NETWORK_WriteString( &g_MessageBuffer.ByteStream, szCommand );				
				
				NETWORK_LaunchPacket( &g_MessageBuffer, g_ServerAddress );
				time( &g_tLastSentCommand );
				SetDlgItemText( hDlg, IDC_INPUTBOX, "" );
				break;
			}
			break;
	case WM_SYSCOMMAND:

		// Hide the window when minimized.
		if ( wParam == SC_MINIMIZE )
			ShowWindow( hDlg, SW_HIDE );
		else
			DefWindowProc( hDlg, Message, wParam, lParam );
		break;
	case WM_CLOSE:

		main_Quit( );
		break;
	case WM_DESTROY:

		Shell_NotifyIcon( NIM_DELETE, &g_NotifyIconData );
		PostQuitMessage( 0 );
		break;
	case UWM_TRAY_TRAYID:

		return main_TrayIconClicked( hDlg, lParam );	
	default:

		return FALSE;
	}

	return TRUE; // If this is false, minimizing the window won't hide it.
}