Add proper exit handling

This commit is contained in:
Sanae 2022-02-21 22:05:13 -06:00
parent b3bcf72283
commit 31e70a08b9
2 changed files with 52 additions and 20 deletions

View File

@ -7,7 +7,10 @@ using Timer = System.Timers.Timer;
Server.Server server = new Server.Server(); Server.Server server = new Server.Server();
HashSet<int> shineBag = new HashSet<int>(); HashSet<int> shineBag = new HashSet<int>();
int shineTx = 0; // used for logging // int shineTx = 0; // used for logging
CancellationTokenSource cts = new CancellationTokenSource();
Task listenTask = server.Listen(cts.Token);
Logger consoleLogger = new Logger("Console");
server.ClientJoined += async (c, type) => { server.ClientJoined += async (c, type) => {
c.Metadata["shineSync"] = new ConcurrentBag<int>(); c.Metadata["shineSync"] = new ConcurrentBag<int>();
@ -33,8 +36,8 @@ timer.Start();
bool flipEnabled = Settings.Instance.Flip.EnabledOnStart; bool flipEnabled = Settings.Instance.Flip.EnabledOnStart;
float MarioSize(bool is2d) => is2d ? 180 : 160; float MarioSize(bool is2d) => is2d ? 180 : 160;
server.PacketHandler = (c, p) => { server.PacketHandler = (c, p) => {
Console.WriteLine($"{c.Id} {p}");
switch (p) { switch (p) {
case CostumePacket: case CostumePacket:
ClientSyncShineBag(c); ClientSyncShineBag(c);
@ -141,13 +144,28 @@ CommandHandler.RegisterCommand("savesettings", _ => {
return "Saved settings.json"; return "Saved settings.json";
}); });
Console.CancelKeyPress += (_, e) => {
e.Cancel = true;
consoleLogger.Info("Received Ctrl+C");
cts.Cancel();
};
CommandHandler.RegisterCommand("exit", _ => {
cts.Cancel();
return "Shutting down clients";
});
CommandHandler.RegisterCommand("quit", _ => {
cts.Cancel();
return "Shutting down clients";
});
Task.Run(() => { Task.Run(() => {
Logger logger = new Logger("Console"); consoleLogger.Info("Run help command for valid commands.");
logger.Info("Run help command for valid commands.");
while (true) { while (true) {
string? text = Console.ReadLine(); string? text = Console.ReadLine();
if (text != null) logger.Info(CommandHandler.GetResult(text)); if (text != null) consoleLogger.Info(CommandHandler.GetResult(text));
} }
}); });
await server.Listen(); await listenTask;

View File

@ -15,7 +15,7 @@ public class Server {
public Func<Client, IPacket, bool>? PacketHandler = null!; public Func<Client, IPacket, bool>? PacketHandler = null!;
public event Action<Client, ConnectPacket> ClientJoined = null!; public event Action<Client, ConnectPacket> ClientJoined = null!;
public async Task Listen() { public async Task Listen(CancellationToken? token = null) {
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
serverSocket.Bind(new IPEndPoint(IPAddress.Parse(Settings.Instance.Server.Address), Settings.Instance.Server.Port)); serverSocket.Bind(new IPEndPoint(IPAddress.Parse(Settings.Instance.Server.Address), Settings.Instance.Server.Port));
@ -23,24 +23,38 @@ public class Server {
Logger.Info($"Listening on {serverSocket.LocalEndPoint}"); Logger.Info($"Listening on {serverSocket.LocalEndPoint}");
while (true) { try {
Socket socket = await serverSocket.AcceptAsync(); while (true) {
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); Socket socket = token.HasValue ? await serverSocket.AcceptAsync(token.Value) : await serverSocket.AcceptAsync();
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
Logger.Warn($"Accepted connection for client {socket.RemoteEndPoint}"); Logger.Warn($"Accepted connection for client {socket.RemoteEndPoint}");
try { try {
if (Clients.Count > Constants.MaxClients) { if (Clients.Count > Constants.MaxClients) {
Logger.Warn("Turned away client due to max clients"); Logger.Warn("Turned away client due to max clients");
await socket.DisconnectAsync(false); await socket.DisconnectAsync(false);
continue; continue;
}
Task.Run(() => HandleSocket(socket));
} catch {
// super ignore this
} }
Task.Run(() => HandleSocket(socket));
} catch {
// super ignore this
} }
} catch (OperationCanceledException) {
// ignore the exception, it's just for closing the server
} }
Logger.Info("Server closing");
try {
serverSocket.Shutdown(SocketShutdown.Both);
} catch (Exception) {
// ignore
} finally {
serverSocket.Close();
}
Logger.Info("Server closed");
} }
public static void FillPacket<T>(PacketHeader header, T packet, Memory<byte> memory) where T : struct, IPacket { public static void FillPacket<T>(PacketHeader header, T packet, Memory<byte> memory) where T : struct, IPacket {