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; } }
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 ); }
//***************************************************************************** // 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 ); }
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; }
//***************************************************************************** // 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 ); }
//***************************************************************************** // 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 )); }
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 ); }
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; }
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 ); }
//***************************************************************************** // 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 ); }
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 ); }
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; } }
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. }