Skip to content

Commit

Permalink
crash ignored players
Browse files Browse the repository at this point in the history
Otherwise they keep sending all their packets (including positional updates) to the server which costs bandwidth and processing power.
  • Loading branch information
Istador authored and Sanae6 committed Apr 27, 2024
1 parent 9511d07 commit 082e480
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 30 deletions.
14 changes: 6 additions & 8 deletions Server/BanLists.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,30 +148,27 @@ private static void Save() {

public static void Crash(
Client user,
bool permanent = false,
bool dispose_user = true,
int delay_ms = 0
int delay_ms = 0
) {
user.Ignored = true;
Task.Run(async () => {
if (delay_ms > 0) {
await Task.Delay(delay_ms);
}
bool permanent = user.Banned;
await user.Send(new ChangeStagePacket {
Id = (permanent ? "$agogus/ban4lyfe" : "$among$us/cr4sh%"),
Stage = (permanent ? "$ejected" : "$agogusStage"),
Scenario = (sbyte) (permanent ? 69 : 21),
SubScenarioType = (byte) (permanent ? 21 : 69),
});
if (dispose_user) {
user.Dispose();
}
});
}

private static void CrashMultiple(string[] args, MUCH much) {
foreach (Client user in much(args).toActUpon) {
Crash(user, true);
user.Banned = true;
Crash(user);
}
}

Expand Down Expand Up @@ -245,8 +242,9 @@ public static string HandleBanCommand(string[] args, MUCH much) {
}

foreach (Client user in res.toActUpon) {
user.Banned = true;
BanClient(user);
Crash(user, true);
Crash(user);
}

Save();
Expand Down
13 changes: 12 additions & 1 deletion Server/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 bool Connected = false;
public bool Ignored = false;
public bool Banned = false;
public CostumePacket? CurrentCostume = null; // required for proper client sync
public string Name {
get => Logger.Name;
Expand Down Expand Up @@ -52,6 +53,11 @@ public async Task Send<T>(T packet, Client? sender = null) where T : struct, IPa

PacketAttribute packetAttribute = Constants.PacketMap[typeof(T)];
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 {
Id = sender?.Id ?? Id,
Type = packetAttribute.Type,
Expand All @@ -71,11 +77,16 @@ public async Task Send(Memory<byte> data, Client? sender) {
PacketHeader header = new PacketHeader();
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");
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);
}

Expand Down
14 changes: 13 additions & 1 deletion Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,17 @@ void logError(Task x) {
server.PacketHandler = (c, p) => {
switch (p) {
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
if (BanLists.Enabled && BanLists.IsStageBanned(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;
}

Expand Down Expand Up @@ -172,6 +179,11 @@ void logError(Task x) {
break;
}

// ignore all other packets from ignored players
case IPacket pack when c.Ignored: {
return false;
}

case TagPacket tagPacket: {
// c.Logger.Info($"Got tag packet: {tagPacket.IsIt}");
if ((tagPacket.UpdateType & TagPacket.TagUpdate.State) != 0) c.Metadata["seeking"] = tagPacket.IsIt;
Expand Down
41 changes: 21 additions & 20 deletions Server/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ public async Task Listen(CancellationToken? token = null) {
Socket socket = token.HasValue ? await serverSocket.AcceptAsync(token.Value) : await serverSocket.AcceptAsync();
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}");

// start sub thread to handle client
Expand Down Expand Up @@ -80,7 +74,7 @@ public static void FillPacket<T>(PacketHeader header, T packet, Memory<byte> mem
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 {
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);
}
}
Expand All @@ -97,7 +91,7 @@ public async Task Broadcast<T>(T packet, Client sender) where T : struct, IPacke
}

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);
PacketHeader header = new PacketHeader {
Id = client.Id,
Expand All @@ -116,7 +110,7 @@ public Task Broadcast<T>(T packet) where T : struct, IPacket {
/// <param name="data">Memory owner to dispose once done</param>
/// <param name="sender">Optional sender to not broadcast data to</param>
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();
}

Expand All @@ -126,7 +120,7 @@ public async Task Broadcast(IMemoryOwner<byte> data, Client? sender = null) {
/// <param name="data">Memory to send to the clients</param>
/// <param name="sender">Optional sender to not broadcast data to</param>
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) {
Expand Down Expand Up @@ -175,10 +169,6 @@ async Task<bool> Read(Memory<byte> readMem, int readSize, int readOffset) {
break;
}
}
if (client.Ignored) {
memory.Dispose();
continue;
}

// connection initialization
if (first) {
Expand All @@ -195,19 +185,30 @@ async Task<bool> Read(Memory<byte> readMem, int readSize, int readOffset) {
client.Id = header.Id;
client.Name = connect.ClientName;

// is the IPv4 address banned?
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.Banned = true;
}
// is the profile ID banned?
if (BanLists.Enabled && BanLists.IsProfileBanned(client.Id)) {
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.Logger.Warn($"Ignoring banned profile ID {client.Id}");
memory.Dispose();
continue;
client.Banned = true;
}

// send server init
// send server init (required to crash ignored players later)
await client.Send(new InitPacket {
MaxPlayers = Settings.Instance.Server.MaxPlayers,
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();
continue;
}

bool wasFirst = connect.ConnectionType == ConnectPacket.ConnectionTypes.FirstConnection;

// add client to the set of connected players
Expand Down

0 comments on commit 082e480

Please sign in to comment.