Merge pull request #827 from Rhefew/feature/ip-connection-limit
feat(plugins): implement customizable maximum concurrent connections (cherry picked from commit 0e30df9ae22a265c3486dea1eba259567631eb87)
This commit is contained in:
68
src/GameLogic/PlugIns/MaximumConnectionsPerIpPlugIn.cs
Normal file
68
src/GameLogic/PlugIns/MaximumConnectionsPerIpPlugIn.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
// <copyright file="MaximumConnectionsPerIpPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A plugin that limits the number of simultaneous active player sessions connected from the same IP address.
|
||||
/// </summary>
|
||||
[PlugIn]
|
||||
[Display(Name = "Maximum Connections Per IP", Description = "Limits the maximum number of parallel connections from the same IP address.")]
|
||||
[Guid("2C779F5E-379E-4CE0-BFCC-CA6455D757B3")]
|
||||
public class MaximumConnectionsPerIpPlugIn : IPlayerStateChangingPlugIn, ISupportCustomConfiguration<MaximumConnectionsPerIpPlugInConfiguration>, ISupportDefaultCustomConfiguration, IDisabledByDefault
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public MaximumConnectionsPerIpPlugInConfiguration? Configuration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask PlayerStateChangingAsync(Player player, StateMachine.StateChangeEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.NextState != PlayerState.Authenticated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ipAddress = (player as IHasIpAddress)?.IpAddress;
|
||||
if (string.IsNullOrEmpty(ipAddress))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var config = this.Configuration ?? CreateDefaultConfiguration();
|
||||
var players = await player.GameContext.GetPlayersAsync().ConfigureAwait(false);
|
||||
var sameIpCount = players.Count(p =>
|
||||
(p as IHasIpAddress)?.IpAddress == ipAddress
|
||||
&& p != player
|
||||
&& p.PlayerState.CurrentState != PlayerState.Initial
|
||||
&& p.PlayerState.CurrentState != PlayerState.LoginScreen);
|
||||
|
||||
if (sameIpCount >= config.MaximumConnectionsPerIp)
|
||||
{
|
||||
player.Logger.LogWarning(
|
||||
"Login request for IP '{IpAddress}' was cancelled. It exceeded the maximum connection limit of {Limit}.",
|
||||
ipAddress,
|
||||
config.MaximumConnectionsPerIp);
|
||||
player.LoginResultOverride = Views.Login.LoginResult.ServerIsFull;
|
||||
eventArgs.Cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateDefaultConfig()
|
||||
{
|
||||
return CreateDefaultConfiguration();
|
||||
}
|
||||
|
||||
private static MaximumConnectionsPerIpPlugInConfiguration CreateDefaultConfiguration()
|
||||
{
|
||||
return new MaximumConnectionsPerIpPlugInConfiguration();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// <copyright file="MaximumConnectionsPerIpPlugInConfiguration.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for the <see cref="MaximumConnectionsPerIpPlugIn"/>.
|
||||
/// </summary>
|
||||
public class MaximumConnectionsPerIpPlugInConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of concurrent connections per IP address.
|
||||
/// </summary>
|
||||
public int MaximumConnectionsPerIp { get; set; } = 3;
|
||||
}
|
||||
Reference in New Issue
Block a user