DEADSOFTWARE

net: anti full state spam (by fgsfds)
authorTerminalHash <lyashuk.voxx@gmail.com>
Sat, 11 Mar 2023 09:26:24 +0000 (12:26 +0300)
committerTerminalHash <lyashuk.voxx@gmail.com>
Sat, 11 Mar 2023 09:26:24 +0000 (12:26 +0300)
src/game/g_game.pas
src/game/g_net.pas
src/game/g_netmsg.pas

index 47251204f2b021a78262a60f265d830d63308bda..261d5e9fe19c34c3fc46c193c917ba7b7cee43ce 100644 (file)
@@ -5163,6 +5163,11 @@ begin
 
   if NetMode = NET_SERVER then
   begin
+  // reset full state flags
+    if NetClients <> nil then
+      for I := 0 to High(NetClients) do
+        NetClients[I].FullUpdateSent := False;
+
     MH_SEND_GameEvent(NET_EV_MAPSTART, gGameSettings.GameMode, Map);
 
   // Ìàñòåðñåðâåð
index a743fa1cfad95dbe8791937cb819c12f72a23ff0..3a233da20e47efe7d962b5fb489041afebddda5d 100644 (file)
@@ -103,6 +103,7 @@ type
     Player:   Word;
     RequestedFullUpdate: Boolean;
     WaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request
+    FullUpdateSent: Boolean;
     RCONAuth: Boolean;
     Voted:    Boolean;
     Crimes:   Integer;
@@ -1662,6 +1663,7 @@ begin
   TC^.AuthTime := 0;
   TC^.MsgTime := 0;
   TC^.RequestedFullUpdate := False;
+  TC^.FullUpdateSent := False;
   TC^.WaitForFirstSpawn := False;
   TC^.NetOut[NET_UNRELIABLE].Free();
   TC^.NetOut[NET_RELIABLE].Free();
index 01708c297bf82b1d108efa9c427d892e90a29c08..4c67d12504ef9f21e14efae0f5afffa3d7840049 100644 (file)
@@ -555,6 +555,14 @@ end;
 procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg);
 begin
   //e_LogWritefln('*** client #%u (cid #%u) full state request', [C.ID, C.Player]);
+
+  if C^.FullUpdateSent then
+  begin
+    // FullStateRequest spam?
+    g_Net_Penalize(C, 'duplicate full state request');
+    exit;
+  end;
+
   if gGameOn then
   begin
     MH_SEND_Everything((C^.State = NET_STATE_AUTH), C^.ID)
@@ -894,11 +902,14 @@ procedure MH_SEND_Everything(CreatePlayers: Boolean {= False}; ID: Integer {= NE
 var
   I: Integer;
 begin
-  if (ID >= 0) and (ID < length(NetClients)) then
-  begin
-    e_LogWritefln('*** client #%u (cid #%u) will get everything', [ID, NetClients[ID].Player]);
-    MH_ProcessFirstSpawn(@NetClients[ID]);
-  end;
+  if (ID < 0) or (ID >= Length(NetClients)) then
+    exit; // bogus client, this shouldn't happen
+
+  NetClients[ID].FullUpdateSent := True;
+
+  e_LogWritefln('*** client #%u (cid #%u) will get everything', [ID, NetClients[ID].Player]);
+
+  MH_ProcessFirstSpawn(@NetClients[ID]);
 
   if gPlayers <> nil then
   begin