//***************************************************************************** // void MASTERSERVER_SendServerIPToLauncher( const NETADDRESS_s &Address, BYTESTREAM_s *pByteStream ) { // Tell the launcher the IP of this server on the list. NETWORK_WriteByte( pByteStream, MSC_SERVER ); NETWORK_WriteByte( pByteStream, Address.abIP[0] ); NETWORK_WriteByte( pByteStream, Address.abIP[1] ); NETWORK_WriteByte( pByteStream, Address.abIP[2] ); NETWORK_WriteByte( pByteStream, Address.abIP[3] ); NETWORK_WriteShort( pByteStream, ntohs( Address.usPort )); }
//***************************************************************************** // void ZANDRONUM_QueryMasterServer( void ) { // Clear out the buffer, and write out launcher challenge. NETWORK_ClearBuffer( &g_MessageBuffer ); NETWORK_WriteLong( &g_MessageBuffer.ByteStream, LAUNCHER_MASTER_CHALLENGE ); NETWORK_WriteShort( &g_MessageBuffer.ByteStream, MASTER_SERVER_VERSION ); // Send the master server our packet. NETWORK_LaunchPacket( &g_MessageBuffer, g_AddressMasterServer, true ); }
//***************************************************************************** // void SERVER_AUTH_SRPMessage ( const int MagicNumber, const int SessionID, const TArray<unsigned char> &Bytes ) { NETWORK_ClearBuffer( &g_AuthServerBuffer ); NETWORK_WriteLong( &g_AuthServerBuffer.ByteStream, MagicNumber ); NETWORK_WriteLong( &g_AuthServerBuffer.ByteStream, SessionID ); NETWORK_WriteShort( &g_AuthServerBuffer.ByteStream, Bytes.Size() ); for ( unsigned int i = 0; i < Bytes.Size(); ++i ) NETWORK_WriteByte( &g_AuthServerBuffer.ByteStream, Bytes[i] ); NETWORK_LaunchPacket( &g_AuthServerBuffer, g_AuthServerAddress ); }
//***************************************************************************** // void MASTERSERVER_SendServerIPBlockToLauncher( const NETADDRESS_s &Address, const std::vector<USHORT> &PortList, BYTESTREAM_s *pByteStream ) { if ( PortList.size() == 0 ) return; // Tell the launcher the IP and all ports of the servers on that IP. NETWORK_WriteByte( pByteStream, PortList.size() ); NETWORK_WriteByte( pByteStream, Address.abIP[0] ); NETWORK_WriteByte( pByteStream, Address.abIP[1] ); NETWORK_WriteByte( pByteStream, Address.abIP[2] ); NETWORK_WriteByte( pByteStream, Address.abIP[3] ); for ( unsigned int i = 0; i < PortList.size(); ++i ) NETWORK_WriteShort( pByteStream, ntohs( PortList[i] ) ); }
//***************************************************************************** // void SERVER_MASTER_Tick( void ) { UCVarValue Val; while (( g_lStoredQueryIPHead != g_lStoredQueryIPTail ) && ( gametic >= g_StoredQueryIPs[g_lStoredQueryIPHead].lNextAllowedGametic )) { g_lStoredQueryIPHead++; g_lStoredQueryIPHead = g_lStoredQueryIPHead % MAX_STORED_QUERY_IPS; } // Send an update to the master server every 30 seconds. if ( gametic % ( TICRATE * 30 )) return; // User doesn't wish to update the master server. if ( sv_updatemaster == false ) return; NETWORK_ClearBuffer( &g_MasterServerBuffer ); Val = sv_masterip.GetGenericRep( CVAR_String ); NETWORK_StringToAddress( Val.String, &g_AddressMasterServer ); I_SetPort( g_AddressMasterServer, g_lMasterPort ); // Write to our packet a challenge to the master server. Val = sv_masteroverrideip.GetGenericRep( CVAR_String ); if ( Val.String[0] == '\0' ) NETWORK_WriteLong( &g_MasterServerBuffer, SERVER_MASTER_CHALLENGE ); else { netadr_t OverrideIP; NETWORK_WriteLong( &g_MasterServerBuffer, SERVER_MASTER_CHALLENGE_OVERRIDE ); NETWORK_StringToAddress( Val.String, &OverrideIP ); NETWORK_WriteByte( &g_MasterServerBuffer, OverrideIP.ip[0] ); NETWORK_WriteByte( &g_MasterServerBuffer, OverrideIP.ip[1] ); NETWORK_WriteByte( &g_MasterServerBuffer, OverrideIP.ip[2] ); NETWORK_WriteByte( &g_MasterServerBuffer, OverrideIP.ip[3] ); NETWORK_WriteShort( &g_MasterServerBuffer, NETWORK_GetLocalPort( )); } // Send the master server our packet. // NETWORK_LaunchPacket( &g_MasterServerBuffer, g_AddressMasterServer, true ); NETWORK_LaunchPacket( &g_MasterServerBuffer, g_AddressMasterServer ); }
//***************************************************************************** // 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 ); }
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; } }