# HG changeset patch # User Adam Kaminski # Date 1630508934 14400 # Wed Sep 01 11:08:54 2021 -0400 # Node ID 6ada262547b9acd007ccae44a90abaa97579b0dd # Parent 12643c2402b85ab198a70f7737fcca090613e828 Fixed packet buffer overflows caused by the server sending map rotations that were too big to fit into a single packet. diff -r 12643c2402b8 -r 6ada262547b9 protocolspec/spec.misc.txt --- a/protocolspec/spec.misc.txt Wed Sep 01 09:56:10 2021 -0400 +++ b/protocolspec/spec.misc.txt Wed Sep 01 11:08:54 2021 -0400 @@ -37,7 +37,7 @@ Command SyncMapRotation ExtendedCommand Struct[] entries - Byte currentPosition + Short currentPosition EndCommand Command ReplaceTextures diff -r 12643c2402b8 -r 6ada262547b9 src/cl_main.cpp --- a/src/cl_main.cpp Wed Sep 01 09:56:10 2021 -0400 +++ b/src/cl_main.cpp Wed Sep 01 11:08:54 2021 -0400 @@ -473,6 +473,9 @@ // Put the game in client mode. NETWORK_SetState( NETSTATE_CLIENT ); + // [AK] Reset the map rotation before we connect to the server. + MAPROTATION_Construct( ); + // Make sure cheats are off. Val.Bool = false; sv_cheats.ForceSet( Val, CVAR_Bool ); @@ -2440,6 +2443,9 @@ if ( M_InServerSetupMenu( )) M_ClearMenus( ); + // [AK] Clear the map rotation when we leave the server. + MAPROTATION_Construct( ); + // Set the network state back to single player. NETWORK_SetState( NETSTATE_SINGLE ); @@ -9267,9 +9273,6 @@ // void ServerCommands::SyncMapRotation::Execute() { - // [AK] Clear the map rotation first before adding the new maps. - MAPROTATION_Construct(); - for ( unsigned int i = 0; i < entries.Size(); i++ ) MAPROTATION_AddMap( entries[i].name, 0, entries[i].minPlayers, entries[i].maxPlayers, true ); @@ -9321,6 +9324,9 @@ if ( M_InServerSetupMenu( )) M_SetMenu( NAME_ZA_RconLoginMenu ); + // [AK] Reset the map rotation before we connect to the server. + MAPROTATION_Construct( ); + // Make sure cheats are off. Val.Bool = false; sv_cheats.ForceSet( Val, CVAR_Bool ); @@ -9408,6 +9414,9 @@ if ( M_InServerSetupMenu( )) M_SetMenu( NAME_ZA_RconLoginMenu ); + // [AK] Reset the map rotation before we reconnect to the server. + MAPROTATION_Construct( ); + // Make sure cheats are off. Val.Bool = false; sv_cheats.ForceSet( Val, CVAR_Bool ); diff -r 12643c2402b8 -r 6ada262547b9 src/sv_commands.cpp --- a/src/sv_commands.cpp Wed Sep 01 09:56:10 2021 -0400 +++ b/src/sv_commands.cpp Wed Sep 01 11:08:54 2021 -0400 @@ -4974,18 +4974,28 @@ return; ServerCommands::SyncMapRotation command; - TArray mapEntries; - mapEntries.Reserve( numEntries ); + command.SetCurrentPosition( MAPROTATION_GetCurrentPosition() ); for ( unsigned int i = 0; i < numEntries; i++ ) { - mapEntries[i].name = MAPROTATION_GetMap( i )->mapname; - mapEntries[i].minPlayers = MAPROTATION_GetPlayerLimits( i, false ); - mapEntries[i].maxPlayers = MAPROTATION_GetPlayerLimits( i, true ); + ServerCommands::MapRotationEntry entry; + entry.name = MAPROTATION_GetMap( i )->mapname; + entry.minPlayers = MAPROTATION_GetPlayerLimits( i, false ); + entry.maxPlayers = MAPROTATION_GetPlayerLimits( i, true ); + + command.PushToEntries( entry ); + + // [AK] If the latest entry won't fit into a single packet, remove it from the list and send out + // what we already have. We'll then send another packet containing this entry and more. + if ( static_cast( command.BuildNetCommand().calcSize() ) + PACKET_HEADER_SIZE >= SERVER_GetMaxPacketSize() ) + { + command.PopFromEntries( entry ); + command.sendCommandToClients( ulPlayerExtra, flags ); + command.ClearEntries(); + command.PushToEntries( entry ); + } } - command.SetEntries( mapEntries ); - command.SetCurrentPosition( MAPROTATION_GetCurrentPosition() ); command.sendCommandToClients( ulPlayerExtra, flags ); }