Skip to content

Commit 65521d0

Browse files
committed
Prevent SV_DropClient() from being called recursively if the client is dropped by a kick or timeout and has too many reliable commands
1 parent 009f520 commit 65521d0

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

code/server/sv_client.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,16 @@ void SV_DropClient( client_t *drop, const char *reason ) {
659659
// Free all allocated data on the client structure
660660
SV_FreeClient(drop);
661661

662+
// Reset the reliable sequence to the currently acknowledged command
663+
// This prevents SV_AddServerCommand() from making another recursive call to SV_DropClient()
664+
// if the client lacks sufficient space for another reliable command
665+
// it also guarantees that the client receives both the print and disconnect commands
666+
drop->reliableSequence = drop->reliableAcknowledge;
667+
// Setting the gamestate message number to -1 ensures that SV_AddServerCommand()
668+
// will not call SV_DropClient() again, even though it is unlikely the client
669+
// will receive many server commands during the drop
670+
drop->gamestateMessageNum = -1;
671+
662672
// tell everyone why they got dropped
663673
SV_SendServerCommand( NULL, "print \"%s" S_COLOR_WHITE " %s\n\"", drop->name, reason );
664674

code/server/sv_main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ void SV_AddServerCommand( client_t *client, const char *cmd ) {
159159
// we check == instead of >= so a broadcast print added by SV_DropClient()
160160
// doesn't cause a recursive drop client
161161
if ( client->reliableSequence - client->reliableAcknowledge == MAX_RELIABLE_COMMANDS + 1 ) {
162+
if ( client->gamestateMessageNum == -1 ) {
163+
// invalid game state message
164+
// this can occur in SV_DropClient() to avoid calling it more than once
165+
return;
166+
}
167+
162168
Com_Printf( "===== pending server commands =====\n" );
163169
for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
164170
Com_Printf( "cmd %5d: %s\n", i, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );

0 commit comments

Comments
 (0)