crash ignored players
Otherwise they keep sending all their packets (including positional updates) to the server which costs bandwidth and processing power.
This commit is contained in:
parent
b418331a03
commit
07526a7c38
|
@ -148,30 +148,27 @@ public static class BanLists {
|
||||||
|
|
||||||
public static void Crash(
|
public static void Crash(
|
||||||
Client user,
|
Client user,
|
||||||
bool permanent = false,
|
int delay_ms = 0
|
||||||
bool dispose_user = true,
|
|
||||||
int delay_ms = 0
|
|
||||||
) {
|
) {
|
||||||
user.Ignored = true;
|
user.Ignored = true;
|
||||||
Task.Run(async () => {
|
Task.Run(async () => {
|
||||||
if (delay_ms > 0) {
|
if (delay_ms > 0) {
|
||||||
await Task.Delay(delay_ms);
|
await Task.Delay(delay_ms);
|
||||||
}
|
}
|
||||||
|
bool permanent = user.Banned;
|
||||||
await user.Send(new ChangeStagePacket {
|
await user.Send(new ChangeStagePacket {
|
||||||
Id = (permanent ? "$agogus/ban4lyfe" : "$among$us/cr4sh%"),
|
Id = (permanent ? "$agogus/ban4lyfe" : "$among$us/cr4sh%"),
|
||||||
Stage = (permanent ? "$ejected" : "$agogusStage"),
|
Stage = (permanent ? "$ejected" : "$agogusStage"),
|
||||||
Scenario = (sbyte) (permanent ? 69 : 21),
|
Scenario = (sbyte) (permanent ? 69 : 21),
|
||||||
SubScenarioType = (byte) (permanent ? 21 : 69),
|
SubScenarioType = (byte) (permanent ? 21 : 69),
|
||||||
});
|
});
|
||||||
if (dispose_user) {
|
|
||||||
user.Dispose();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CrashMultiple(string[] args, MUCH much) {
|
private static void CrashMultiple(string[] args, MUCH much) {
|
||||||
foreach (Client user in much(args).toActUpon) {
|
foreach (Client user in much(args).toActUpon) {
|
||||||
Crash(user, true);
|
user.Banned = true;
|
||||||
|
Crash(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,8 +242,9 @@ public static class BanLists {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Client user in res.toActUpon) {
|
foreach (Client user in res.toActUpon) {
|
||||||
|
user.Banned = true;
|
||||||
BanClient(user);
|
BanClient(user);
|
||||||
Crash(user, true);
|
Crash(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
|
|
@ -13,6 +13,7 @@ public class Client : IDisposable {
|
||||||
public readonly ConcurrentDictionary<string, object?> Metadata = new ConcurrentDictionary<string, object?>(); // can be used to store any information about a player
|
public readonly ConcurrentDictionary<string, object?> Metadata = new ConcurrentDictionary<string, object?>(); // can be used to store any information about a player
|
||||||
public bool Connected = false;
|
public bool Connected = false;
|
||||||
public bool Ignored = false;
|
public bool Ignored = false;
|
||||||
|
public bool Banned = false;
|
||||||
public CostumePacket? CurrentCostume = null; // required for proper client sync
|
public CostumePacket? CurrentCostume = null; // required for proper client sync
|
||||||
public string Name {
|
public string Name {
|
||||||
get => Logger.Name;
|
get => Logger.Name;
|
||||||
|
@ -52,6 +53,11 @@ public class Client : IDisposable {
|
||||||
|
|
||||||
PacketAttribute packetAttribute = Constants.PacketMap[typeof(T)];
|
PacketAttribute packetAttribute = Constants.PacketMap[typeof(T)];
|
||||||
try {
|
try {
|
||||||
|
// don't send most packets to ignored players
|
||||||
|
if (Ignored && packetAttribute.Type != PacketType.Init && packetAttribute.Type != PacketType.ChangeStage) {
|
||||||
|
memory.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
Server.FillPacket(new PacketHeader {
|
Server.FillPacket(new PacketHeader {
|
||||||
Id = sender?.Id ?? Id,
|
Id = sender?.Id ?? Id,
|
||||||
Type = packetAttribute.Type,
|
Type = packetAttribute.Type,
|
||||||
|
@ -71,11 +77,16 @@ public class Client : IDisposable {
|
||||||
PacketHeader header = new PacketHeader();
|
PacketHeader header = new PacketHeader();
|
||||||
header.Deserialize(data.Span);
|
header.Deserialize(data.Span);
|
||||||
|
|
||||||
if (!Connected && header.Type is not PacketType.Connect) {
|
if (!Connected && !Ignored && header.Type != PacketType.Connect) {
|
||||||
Server.Logger.Error($"Didn't send {header.Type} to {Id} because they weren't connected yet");
|
Server.Logger.Error($"Didn't send {header.Type} to {Id} because they weren't connected yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't send most packets to ignored players
|
||||||
|
if (Ignored && header.Type != PacketType.Init && header.Type != PacketType.ChangeStage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await Socket!.SendAsync(data[..(Constants.HeaderSize + header.PacketSize)], SocketFlags.None);
|
await Socket!.SendAsync(data[..(Constants.HeaderSize + header.PacketSize)], SocketFlags.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,10 +120,17 @@ void logError(Task x) {
|
||||||
server.PacketHandler = (c, p) => {
|
server.PacketHandler = (c, p) => {
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case GamePacket gamePacket: {
|
case GamePacket gamePacket: {
|
||||||
|
// crash ignored player
|
||||||
|
if (c.Ignored) {
|
||||||
|
c.Logger.Info($"Crashing ignored player after entering stage {gamePacket.Stage}.");
|
||||||
|
BanLists.Crash(c, 500);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// crash player entering a banned stage
|
// crash player entering a banned stage
|
||||||
if (BanLists.Enabled && BanLists.IsStageBanned(gamePacket.Stage)) {
|
if (BanLists.Enabled && BanLists.IsStageBanned(gamePacket.Stage)) {
|
||||||
c.Logger.Warn($"Crashing player for entering banned stage {gamePacket.Stage}.");
|
c.Logger.Warn($"Crashing player for entering banned stage {gamePacket.Stage}.");
|
||||||
BanLists.Crash(c, false, false, 500);
|
BanLists.Crash(c, 500);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +179,11 @@ server.PacketHandler = (c, p) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore all other packets from ignored players
|
||||||
|
case IPacket pack when c.Ignored: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
case TagPacket tagPacket: {
|
case TagPacket tagPacket: {
|
||||||
// c.Logger.Info($"Got tag packet: {tagPacket.IsIt}");
|
// c.Logger.Info($"Got tag packet: {tagPacket.IsIt}");
|
||||||
if ((tagPacket.UpdateType & TagPacket.TagUpdate.State) != 0) c.Metadata["seeking"] = tagPacket.IsIt;
|
if ((tagPacket.UpdateType & TagPacket.TagUpdate.State) != 0) c.Metadata["seeking"] = tagPacket.IsIt;
|
||||||
|
|
|
@ -29,12 +29,6 @@ public class Server {
|
||||||
Socket socket = token.HasValue ? await serverSocket.AcceptAsync(token.Value) : await serverSocket.AcceptAsync();
|
Socket socket = token.HasValue ? await serverSocket.AcceptAsync(token.Value) : await serverSocket.AcceptAsync();
|
||||||
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
||||||
|
|
||||||
// is the IPv4 address banned?
|
|
||||||
if (BanLists.Enabled && BanLists.IsIPv4Banned(((IPEndPoint) socket.RemoteEndPoint!).Address!)) {
|
|
||||||
Logger.Warn($"Ignoring banned IPv4 address {socket.RemoteEndPoint}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Warn($"Accepted connection for client {socket.RemoteEndPoint}");
|
Logger.Warn($"Accepted connection for client {socket.RemoteEndPoint}");
|
||||||
|
|
||||||
// start sub thread to handle client
|
// start sub thread to handle client
|
||||||
|
@ -80,7 +74,7 @@ public class Server {
|
||||||
public delegate void PacketReplacer<in T>(Client from, Client to, T value); // replacer must send
|
public delegate void PacketReplacer<in T>(Client from, Client to, T value); // replacer must send
|
||||||
|
|
||||||
public void BroadcastReplace<T>(T packet, Client sender, PacketReplacer<T> packetReplacer) where T : struct, IPacket {
|
public void BroadcastReplace<T>(T packet, Client sender, PacketReplacer<T> packetReplacer) where T : struct, IPacket {
|
||||||
foreach (Client client in Clients.Where(client => client.Connected && sender.Id != client.Id)) {
|
foreach (Client client in Clients.Where(c => c.Connected && !c.Ignored && sender.Id != c.Id)) {
|
||||||
packetReplacer(sender, client, packet);
|
packetReplacer(sender, client, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +91,7 @@ public class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Broadcast<T>(T packet) where T : struct, IPacket {
|
public Task Broadcast<T>(T packet) where T : struct, IPacket {
|
||||||
return Task.WhenAll(Clients.Where(c => c.Connected).Select(async client => {
|
return Task.WhenAll(Clients.Where(c => c.Connected && !c.Ignored).Select(async client => {
|
||||||
IMemoryOwner<byte> memory = MemoryPool<byte>.Shared.RentZero(Constants.HeaderSize + packet.Size);
|
IMemoryOwner<byte> memory = MemoryPool<byte>.Shared.RentZero(Constants.HeaderSize + packet.Size);
|
||||||
PacketHeader header = new PacketHeader {
|
PacketHeader header = new PacketHeader {
|
||||||
Id = client.Id,
|
Id = client.Id,
|
||||||
|
@ -116,7 +110,7 @@ public class Server {
|
||||||
/// <param name="data">Memory owner to dispose once done</param>
|
/// <param name="data">Memory owner to dispose once done</param>
|
||||||
/// <param name="sender">Optional sender to not broadcast data to</param>
|
/// <param name="sender">Optional sender to not broadcast data to</param>
|
||||||
public async Task Broadcast(IMemoryOwner<byte> data, Client? sender = null) {
|
public async Task Broadcast(IMemoryOwner<byte> data, Client? sender = null) {
|
||||||
await Task.WhenAll(Clients.Where(c => c.Connected && c != sender).Select(client => client.Send(data.Memory, sender)));
|
await Task.WhenAll(Clients.Where(c => c.Connected && !c.Ignored && c != sender).Select(client => client.Send(data.Memory, sender)));
|
||||||
data.Dispose();
|
data.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +120,7 @@ public class Server {
|
||||||
/// <param name="data">Memory to send to the clients</param>
|
/// <param name="data">Memory to send to the clients</param>
|
||||||
/// <param name="sender">Optional sender to not broadcast data to</param>
|
/// <param name="sender">Optional sender to not broadcast data to</param>
|
||||||
public async void Broadcast(Memory<byte> data, Client? sender = null) {
|
public async void Broadcast(Memory<byte> data, Client? sender = null) {
|
||||||
await Task.WhenAll(Clients.Where(c => c.Connected && c != sender).Select(client => client.Send(data, sender)));
|
await Task.WhenAll(Clients.Where(c => c.Connected && !c.Ignored && c != sender).Select(client => client.Send(data, sender)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Client? FindExistingClient(Guid id) {
|
public Client? FindExistingClient(Guid id) {
|
||||||
|
@ -175,10 +169,6 @@ public class Server {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (client.Ignored) {
|
|
||||||
memory.Dispose();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// connection initialization
|
// connection initialization
|
||||||
if (first) {
|
if (first) {
|
||||||
|
@ -195,19 +185,30 @@ public class Server {
|
||||||
client.Id = header.Id;
|
client.Id = header.Id;
|
||||||
client.Name = connect.ClientName;
|
client.Name = connect.ClientName;
|
||||||
|
|
||||||
// is the profile ID banned?
|
// is the IPv4 address banned?
|
||||||
if (BanLists.Enabled && BanLists.IsProfileBanned(client.Id)) {
|
if (BanLists.Enabled && BanLists.IsIPv4Banned(((IPEndPoint) socket.RemoteEndPoint!).Address!)) {
|
||||||
|
Logger.Warn($"Ignoring banned IPv4 address for {client.Name} ({client.Id}/{remote})");
|
||||||
client.Ignored = true;
|
client.Ignored = true;
|
||||||
client.Logger.Warn($"Ignoring banned profile ID {client.Id}");
|
client.Banned = true;
|
||||||
|
}
|
||||||
|
// is the profile ID banned?
|
||||||
|
else if (BanLists.Enabled && BanLists.IsProfileBanned(client.Id)) {
|
||||||
|
client.Logger.Warn($"Ignoring banned profile ID for {client.Name} ({client.Id}/{remote})");
|
||||||
|
client.Ignored = true;
|
||||||
|
client.Banned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send server init (required to crash ignored players later)
|
||||||
|
await client.Send(new InitPacket {
|
||||||
|
MaxPlayers = (client.Ignored ? (ushort) 1 : Settings.Instance.Server.MaxPlayers),
|
||||||
|
});
|
||||||
|
|
||||||
|
// don't init or announce an ignored client to other players any further
|
||||||
|
if (client.Ignored) {
|
||||||
memory.Dispose();
|
memory.Dispose();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send server init
|
|
||||||
await client.Send(new InitPacket {
|
|
||||||
MaxPlayers = Settings.Instance.Server.MaxPlayers,
|
|
||||||
});
|
|
||||||
|
|
||||||
bool wasFirst = connect.ConnectionType == ConnectPacket.ConnectionTypes.FirstConnection;
|
bool wasFirst = connect.ConnectionType == ConnectPacket.ConnectionTypes.FirstConnection;
|
||||||
|
|
||||||
// add client to the set of connected players
|
// add client to the set of connected players
|
||||||
|
|
Loading…
Reference in New Issue