]> git.deb.at Git - rhonda/impostor.git/commitdiff
Prevent clients from creating a second game
authorminiduikboot <mini@duikbo.at>
Tue, 17 Dec 2024 21:05:27 +0000 (22:05 +0100)
committerminiduikboot <mini@duikbo.at>
Sun, 22 Dec 2024 16:02:56 +0000 (17:02 +0100)
Legitimate clients will never create a second game using the same
connection.

Co-Authored-By: js6pak <me@6pak.dev>
src/Impostor.Api/Net/IClient.cs
src/Impostor.Server/Net/ClientBase.cs
src/Impostor.Server/Net/Manager/GameManager.cs

index e4f8100144760f7b3cfefb34b74a09d674dc2212..0732c0ccd9c2469978e9e1e1b74ed6d2466cfdb6 100644 (file)
@@ -8,7 +8,7 @@ namespace Impostor.Api.Net
     /// <summary>
     ///     Represents a connected game client.
     /// </summary>
-    public interface IClient
+    public interface IClient : IEquatable<IClient>
     {
         /// <summary>
         ///     Gets or sets the unique ID of the client.
index b52d51218e28f9ed40ed1ebca1a09cd6c4344b9f..a8945fafc4e67f120ea3e45e697d9c417e7d2463 100644 (file)
@@ -59,5 +59,20 @@ namespace Impostor.Server.Net
         {
             await Connection.CustomDisconnectAsync(reason, message);
         }
+
+        public bool Equals(IClient? other)
+        {
+            return other != null && Id == other.Id;
+        }
+
+        public override bool Equals(object? obj)
+        {
+            return Equals(obj as ClientBase);
+        }
+
+        public override int GetHashCode()
+        {
+            return Id;
+        }
     }
 }
index 4e985214223bb87c11952ae5a3cfb1f495d90872..7de311a919db66bb5c7020e0f85345d6de97c0c0 100644 (file)
@@ -31,6 +31,7 @@ namespace Impostor.Server.Net.Manager
         private readonly IEventManager _eventManager;
         private readonly IGameCodeFactory _gameCodeFactory;
         private readonly ICompatibilityManager _compatibilityManager;
+        private readonly ConcurrentDictionary<IClient, Game?> _gamesCreatedBy;
 
         public GameManager(
             ILogger<GameManager> logger,
@@ -49,6 +50,7 @@ namespace Impostor.Server.Net.Manager
             _games = new ConcurrentDictionary<int, Game>();
             _compatibilityConfig = compatibilityConfig.Value;
             _compatibilityManager = compatibilityManager;
+            _gamesCreatedBy = new ConcurrentDictionary<IClient, Game?>();
         }
 
         IEnumerable<IGame> IGameManager.Games => _games.Select(kv => kv.Value);
@@ -85,6 +87,12 @@ namespace Impostor.Server.Net.Manager
 
         public async ValueTask<IGame?> CreateAsync(IClient? owner, IGameOptions options, GameFilterOptions filterOptions)
         {
+            if (owner != null && !_gamesCreatedBy.TryAdd(owner, null))
+            {
+                _logger.LogWarning("Connection {Name}({ClientId}) has tried to create a second game, blocked", owner.Name, owner.Id);
+                return null;
+            }
+
             var @event = new GameCreationEvent(this, owner);
             await _eventManager.CallAsync(@event);
 
@@ -100,6 +108,11 @@ namespace Impostor.Server.Net.Manager
                 (success, game) = await TryCreateAsync(options, filterOptions, owner);
             }
 
+            if (owner != null)
+            {
+                _gamesCreatedBy[owner] = game;
+            }
+
             if (!success || game == null)
             {
                 throw new ImpostorException("Could not create new game"); // TODO: Fix generic exception.