From fb33b5b5b31ad184ce4085d13e5333c32ae42da3 Mon Sep 17 00:00:00 2001 From: AeonLucid Date: Sat, 26 Sep 2020 19:28:46 +0200 Subject: [PATCH] Split up the NodeProvider into two interfaces --- .../Net/Manager/GameManager.cs | 14 ++-- .../Net/Redirector/ClientManagerRedirector.cs | 6 +- .../Net/Redirector/ClientRedirector.cs | 6 +- .../Net/Redirector/INodeLocator.cs | 11 +++ .../Net/Redirector/INodeProvider.cs | 3 - ...NodeProviderNoOp.cs => NodeLocatorNoOp.cs} | 10 +-- .../Net/Redirector/NodeLocatorRedis.cs | 40 +++++++++++ .../Net/Redirector/NodeProviderConfig.cs | 43 +++++++++++ .../Net/Redirector/NodeProviderRedis.cs | 71 ------------------- src/Impostor.Server/Net/State/Game.cs | 6 +- src/Impostor.Server/Program.cs | 15 +++- src/Impostor.Server/config.json | 4 -- 12 files changed, 127 insertions(+), 102 deletions(-) create mode 100644 src/Impostor.Server/Net/Redirector/INodeLocator.cs rename src/Impostor.Server/Net/Redirector/{NodeProviderNoOp.cs => NodeLocatorNoOp.cs} (66%) create mode 100644 src/Impostor.Server/Net/Redirector/NodeLocatorRedis.cs create mode 100644 src/Impostor.Server/Net/Redirector/NodeProviderConfig.cs delete mode 100644 src/Impostor.Server/Net/Redirector/NodeProviderRedis.cs diff --git a/src/Impostor.Server/Net/Manager/GameManager.cs b/src/Impostor.Server/Net/Manager/GameManager.cs index 7c0db53..515ae5b 100644 --- a/src/Impostor.Server/Net/Manager/GameManager.cs +++ b/src/Impostor.Server/Net/Manager/GameManager.cs @@ -15,14 +15,14 @@ namespace Impostor.Server.Net.Manager internal class GameManager { private readonly ILogger _logger; - private readonly INodeProvider _nodeProvider; + private readonly INodeLocator _nodeLocator; private readonly IPEndPoint _publicIp; private readonly ConcurrentDictionary _games; - public GameManager(ILogger logger, IOptions config, INodeProvider nodeProvider) + public GameManager(ILogger logger, IOptions config, INodeLocator nodeLocator) { _logger = logger; - _nodeProvider = nodeProvider; + _nodeLocator = nodeLocator; _publicIp = new IPEndPoint(IPAddress.Parse(config.Value.PublicIp), config.Value.PublicPort); _games = new ConcurrentDictionary(); } @@ -33,12 +33,12 @@ namespace Impostor.Server.Net.Manager var gameCode = GameCode.GenerateCode(6); var gameCodeStr = GameCode.IntToGameName(gameCode); - var game = new Game(this, _nodeProvider, _publicIp, gameCode, options); + var game = new Game(this, _nodeLocator, _publicIp, gameCode, options); - if (_nodeProvider.Find(gameCodeStr) == null && + if (_nodeLocator.Find(gameCodeStr) == null && _games.TryAdd(gameCode, game)) { - _nodeProvider.Save(gameCodeStr, _publicIp); + _nodeLocator.Save(gameCodeStr, _publicIp); _logger.LogDebug("Created game with code {0} ({1}).", game.CodeStr, gameCode); return game; } @@ -86,7 +86,7 @@ namespace Impostor.Server.Net.Manager public void Remove(int gameCode) { _logger.LogDebug("Remove game with code {0} ({1}).", GameCode.IntToGameName(gameCode), gameCode); - _nodeProvider.Remove(GameCode.IntToGameName(gameCode)); + _nodeLocator.Remove(GameCode.IntToGameName(gameCode)); _games.TryRemove(gameCode, out _); } } diff --git a/src/Impostor.Server/Net/Redirector/ClientManagerRedirector.cs b/src/Impostor.Server/Net/Redirector/ClientManagerRedirector.cs index f22a624..78631dc 100644 --- a/src/Impostor.Server/Net/Redirector/ClientManagerRedirector.cs +++ b/src/Impostor.Server/Net/Redirector/ClientManagerRedirector.cs @@ -9,19 +9,21 @@ namespace Impostor.Server.Net.Redirector { private readonly ILogger _logger; private readonly INodeProvider _nodeProvider; + private readonly INodeLocator _nodeLocator; private readonly HashSet _clients; - public ClientManagerRedirector(ILogger logger, INodeProvider nodeProvider) + public ClientManagerRedirector(ILogger logger, INodeProvider nodeProvider, INodeLocator nodeLocator) { _logger = logger; _nodeProvider = nodeProvider; + _nodeLocator = nodeLocator; _clients = new HashSet(); } public void Create(string name, Connection connection) { _logger.LogInformation("Client connected."); - _clients.Add(new ClientRedirector(name, connection, this, _nodeProvider)); + _clients.Add(new ClientRedirector(name, connection, this, _nodeProvider, _nodeLocator)); } public void Remove(ClientRedirector client) diff --git a/src/Impostor.Server/Net/Redirector/ClientRedirector.cs b/src/Impostor.Server/Net/Redirector/ClientRedirector.cs index ce85758..8bbe605 100644 --- a/src/Impostor.Server/Net/Redirector/ClientRedirector.cs +++ b/src/Impostor.Server/Net/Redirector/ClientRedirector.cs @@ -17,8 +17,9 @@ namespace Impostor.Server.Net.Redirector private readonly Connection _connection; private readonly ClientManagerRedirector _clientManager; private readonly INodeProvider _nodeProvider; + private readonly INodeLocator _nodeLocator; - public ClientRedirector(string name, Connection connection, ClientManagerRedirector clientManager, INodeProvider nodeProvider) + public ClientRedirector(string name, Connection connection, ClientManagerRedirector clientManager, INodeProvider nodeProvider, INodeLocator nodeLocator) { _name = name; _connection = connection; @@ -26,6 +27,7 @@ namespace Impostor.Server.Net.Redirector _connection.Disconnected += OnDisconnected; _clientManager = clientManager; _nodeProvider = nodeProvider; + _nodeLocator = nodeLocator; } private void OnDataReceived(DataReceivedEventArgs e) @@ -74,7 +76,7 @@ namespace Impostor.Server.Net.Redirector using (var packet = MessageWriter.Get(SendOption.Reliable)) { - var endpoint = _nodeProvider.Find(GameCode.IntToGameName(gameCode)); + var endpoint = _nodeLocator.Find(GameCode.IntToGameName(gameCode)); if (endpoint == null) { Message01JoinGame.SerializeError(packet, false, DisconnectReason.GameMissing); diff --git a/src/Impostor.Server/Net/Redirector/INodeLocator.cs b/src/Impostor.Server/Net/Redirector/INodeLocator.cs new file mode 100644 index 0000000..f7dcf57 --- /dev/null +++ b/src/Impostor.Server/Net/Redirector/INodeLocator.cs @@ -0,0 +1,11 @@ +using System.Net; + +namespace Impostor.Server.Net.Redirector +{ + public interface INodeLocator + { + IPEndPoint Find(string gameCode); + void Save(string gameCode, IPEndPoint endPoint); + void Remove(string gameCode); + } +} \ No newline at end of file diff --git a/src/Impostor.Server/Net/Redirector/INodeProvider.cs b/src/Impostor.Server/Net/Redirector/INodeProvider.cs index 37418e6..318fcb2 100644 --- a/src/Impostor.Server/Net/Redirector/INodeProvider.cs +++ b/src/Impostor.Server/Net/Redirector/INodeProvider.cs @@ -5,8 +5,5 @@ namespace Impostor.Server.Net.Redirector internal interface INodeProvider { IPEndPoint Get(); - IPEndPoint Find(string gameCode); - void Save(string gameCode, IPEndPoint endPoint); - void Remove(string gameCode); } } \ No newline at end of file diff --git a/src/Impostor.Server/Net/Redirector/NodeProviderNoOp.cs b/src/Impostor.Server/Net/Redirector/NodeLocatorNoOp.cs similarity index 66% rename from src/Impostor.Server/Net/Redirector/NodeProviderNoOp.cs rename to src/Impostor.Server/Net/Redirector/NodeLocatorNoOp.cs index fa97968..21811c8 100644 --- a/src/Impostor.Server/Net/Redirector/NodeProviderNoOp.cs +++ b/src/Impostor.Server/Net/Redirector/NodeLocatorNoOp.cs @@ -1,15 +1,9 @@ -using System; -using System.Net; +using System.Net; namespace Impostor.Server.Net.Redirector { - public class NodeProviderNoOp : INodeProvider + public class NodeLocatorNoOp : INodeLocator { - public IPEndPoint Get() - { - throw new NotImplementedException(); - } - public IPEndPoint Find(string gameCode) { // Do nothing. diff --git a/src/Impostor.Server/Net/Redirector/NodeLocatorRedis.cs b/src/Impostor.Server/Net/Redirector/NodeLocatorRedis.cs new file mode 100644 index 0000000..1819eac --- /dev/null +++ b/src/Impostor.Server/Net/Redirector/NodeLocatorRedis.cs @@ -0,0 +1,40 @@ +using System; +using System.Net; +using Microsoft.Extensions.Caching.Distributed; + +namespace Impostor.Server.Net.Redirector +{ + public class NodeLocatorRedis : INodeLocator + { + private readonly IDistributedCache _cache; + + public NodeLocatorRedis(IDistributedCache cache) + { + _cache = cache; + } + + public IPEndPoint Find(string gameCode) + { + var entry = _cache.GetString(gameCode); + if (entry == null) + { + return null; + } + + return IPEndPoint.Parse(entry); + } + + public void Save(string gameCode, IPEndPoint endPoint) + { + _cache.SetString(gameCode, endPoint.ToString(), new DistributedCacheEntryOptions + { + SlidingExpiration = TimeSpan.FromHours(1) + }); + } + + public void Remove(string gameCode) + { + _cache.Remove(gameCode); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Server/Net/Redirector/NodeProviderConfig.cs b/src/Impostor.Server/Net/Redirector/NodeProviderConfig.cs new file mode 100644 index 0000000..864a540 --- /dev/null +++ b/src/Impostor.Server/Net/Redirector/NodeProviderConfig.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Net; +using Impostor.Server.Data; +using Microsoft.Extensions.Options; + +namespace Impostor.Server.Net.Redirector +{ + internal class NodeProviderConfig : INodeProvider + { + private readonly List _nodes; + private readonly object _lock; + private int _currentIndex; + + public NodeProviderConfig(IOptions redirectorConfig) + { + _nodes = new List(); + _lock = new object(); + + if (redirectorConfig.Value.Nodes != null) + { + foreach (var node in redirectorConfig.Value.Nodes) + { + _nodes.Add(new IPEndPoint(IPAddress.Parse(node.Ip), node.Port)); + } + } + } + + public IPEndPoint Get() + { + lock (_lock) + { + var node = _nodes[_currentIndex++]; + + if (_currentIndex == _nodes.Count) + { + _currentIndex = 0; + } + + return node; + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Server/Net/Redirector/NodeProviderRedis.cs b/src/Impostor.Server/Net/Redirector/NodeProviderRedis.cs deleted file mode 100644 index ceaec46..0000000 --- a/src/Impostor.Server/Net/Redirector/NodeProviderRedis.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Impostor.Server.Data; -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Options; - -namespace Impostor.Server.Net.Redirector -{ - internal class NodeProviderRedis : INodeProvider - { - private readonly IDistributedCache _cache; - private readonly List _nodes; - private readonly object _lock; - private int _currentIndex; - - public NodeProviderRedis(IOptions redirectorConfig, IDistributedCache cache) - { - _cache = cache; - _nodes = new List(); - _lock = new object(); - - if (redirectorConfig.Value.Nodes != null) - { - foreach (var node in redirectorConfig.Value.Nodes) - { - _nodes.Add(new IPEndPoint(IPAddress.Parse(node.Ip), node.Port)); - } - } - } - - public IPEndPoint Get() - { - lock (_lock) - { - var node = _nodes[_currentIndex++]; - - if (_currentIndex == _nodes.Count) - { - _currentIndex = 0; - } - - return node; - } - } - - public IPEndPoint Find(string gameCode) - { - var entry = _cache.GetString(gameCode); - if (entry == null) - { - return null; - } - - return IPEndPoint.Parse(entry); - } - - public void Save(string gameCode, IPEndPoint endPoint) - { - _cache.SetString(gameCode, endPoint.ToString(), new DistributedCacheEntryOptions - { - SlidingExpiration = TimeSpan.FromHours(1) - }); - } - - public void Remove(string gameCode) - { - _cache.Remove(gameCode); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/Net/State/Game.cs b/src/Impostor.Server/Net/State/Game.cs index bb8ff6a..4ffcb7b 100644 --- a/src/Impostor.Server/Net/State/Game.cs +++ b/src/Impostor.Server/Net/State/Game.cs @@ -18,14 +18,14 @@ namespace Impostor.Server.Net.State private static readonly ILogger Logger = Log.ForContext(); private readonly GameManager _gameManager; - private readonly INodeProvider _nodeProvider; + private readonly INodeLocator _nodeLocator; private readonly ConcurrentDictionary _players; private readonly HashSet _bannedIps; - public Game(GameManager gameManager, INodeProvider nodeProvider, IPEndPoint publicIp, int code, GameOptionsData options) + public Game(GameManager gameManager, INodeLocator nodeLocator, IPEndPoint publicIp, int code, GameOptionsData options) { _gameManager = gameManager; - _nodeProvider = nodeProvider; + _nodeLocator = nodeLocator; _players = new ConcurrentDictionary(); _bannedIps = new HashSet(); diff --git a/src/Impostor.Server/Program.cs b/src/Impostor.Server/Program.cs index fea258a..7a665f1 100644 --- a/src/Impostor.Server/Program.cs +++ b/src/Impostor.Server/Program.cs @@ -64,7 +64,15 @@ namespace Impostor.Server if (redirector.Enabled) { - services.AddSingleton(); + // When joining a game, it retrieves the game server ip from redis. + // When a game has been created on this node, it stores the game code with its ip in redis. + services.AddSingleton(); + + // Use the configuration as source for the list of nodes to provide + // when creating a game. + services.AddSingleton(); + + // Dependency for the NodeLocatorRedis. services.AddStackExchangeRedisCache(options => { options.Configuration = redirector.Redis; @@ -73,12 +81,15 @@ namespace Impostor.Server } else { - services.AddSingleton(); + // Redirector is not enabled but the dependency is still required. + // So we provide one that ignores all calls. + services.AddSingleton(); } if (redirector.Enabled && redirector.Master) { services.AddSingleton(); + // For a master server, we don't need a GameManager. } else { diff --git a/src/Impostor.Server/config.json b/src/Impostor.Server/config.json index 5e9f634..6c8f49a 100644 --- a/src/Impostor.Server/config.json +++ b/src/Impostor.Server/config.json @@ -13,10 +13,6 @@ { "Ip": "127.0.0.1", "Port": 22024 - }, - { - "Ip": "127.0.0.1", - "Port": 22025 } ] } -- 2.39.5