Added /shutdown and /restart commands for server maintenance.

This commit is contained in:
flash 2022-08-30 18:29:11 +00:00
parent e6dffe06e6
commit 6f50ec66a9
3 changed files with 49 additions and 12 deletions

View file

@ -20,6 +20,8 @@ namespace SharpChat {
public DateTimeOffset LastPing { get; set; } = DateTimeOffset.MinValue; public DateTimeOffset LastPing { get; set; } = DateTimeOffset.MinValue;
public ChatUser User { get; set; } public ChatUser User { get; set; }
private static int CloseCode { get; set; } = 1000;
public string TargetName => @"@log"; public string TargetName => @"@log";
@ -27,8 +29,8 @@ namespace SharpChat {
public IPAddress RemoteAddress { public IPAddress RemoteAddress {
get { get {
if (_RemoteAddress == null) { if(_RemoteAddress == null) {
if ((Connection.ConnectionInfo.ClientIpAddress == @"127.0.0.1" || Connection.ConnectionInfo.ClientIpAddress == @"::1") if((Connection.ConnectionInfo.ClientIpAddress == @"127.0.0.1" || Connection.ConnectionInfo.ClientIpAddress == @"::1")
&& Connection.ConnectionInfo.Headers.ContainsKey(@"X-Real-IP")) && Connection.ConnectionInfo.Headers.ContainsKey(@"X-Real-IP"))
_RemoteAddress = IPAddress.Parse(Connection.ConnectionInfo.Headers[@"X-Real-IP"]); _RemoteAddress = IPAddress.Parse(Connection.ConnectionInfo.Headers[@"X-Real-IP"]);
else else
@ -52,14 +54,14 @@ namespace SharpChat {
} }
public void Send(IServerPacket packet) { public void Send(IServerPacket packet) {
if (!Connection.IsAvailable) if(!Connection.IsAvailable)
return; return;
IEnumerable<string> data = packet.Pack(); IEnumerable<string> data = packet.Pack();
if (data != null) if(data != null)
foreach (string line in data) foreach(string line in data)
if (!string.IsNullOrWhiteSpace(line)) if(!string.IsNullOrWhiteSpace(line))
Connection.Send(line); Connection.Send(line);
} }
@ -69,6 +71,9 @@ namespace SharpChat {
public bool HasTimedOut public bool HasTimedOut
=> DateTimeOffset.Now - LastPing > SessionTimeOut; => DateTimeOffset.Now - LastPing > SessionTimeOut;
public void PrepareForRestart()
=> CloseCode = 1012;
public void Dispose() public void Dispose()
=> Dispose(true); => Dispose(true);
@ -76,13 +81,13 @@ namespace SharpChat {
=> Dispose(false); => Dispose(false);
private void Dispose(bool disposing) { private void Dispose(bool disposing) {
if (IsDisposed) if(IsDisposed)
return; return;
IsDisposed = true; IsDisposed = true;
Connection.Close(); Connection.Close(CloseCode);
if (disposing) if(disposing)
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
} }

View file

@ -22,7 +22,7 @@ namespace SharpChat {
Database.ReadConfig(); Database.ReadConfig();
using ManualResetEvent mre = new ManualResetEvent(false); using ManualResetEvent mre = new ManualResetEvent(false);
using SockChatServer scs = new SockChatServer(PORT); using SockChatServer scs = new SockChatServer(mre, PORT);
Console.CancelKeyPress += (s, e) => { e.Cancel = true; mre.Set(); }; Console.CancelKeyPress += (s, e) => { e.Cancel = true; mre.Set(); };
mre.WaitOne(); mre.WaitOne();
} }

View file

@ -11,6 +11,7 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading;
namespace SharpChat { namespace SharpChat {
public class SockChatServer : IDisposable { public class SockChatServer : IDisposable {
@ -58,9 +59,14 @@ namespace SharpChat {
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(@"SharpChat"); HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(@"SharpChat");
} }
public SockChatServer(ushort port) { private ManualResetEvent Shutdown { get; }
private bool IsShuttingDown = false;
public SockChatServer(ManualResetEvent mre, ushort port) {
Logger.Write("Starting Sock Chat server..."); Logger.Write("Starting Sock Chat server...");
Shutdown = mre ?? throw new ArgumentNullException(nameof(mre));
Context = new ChatContext(this); Context = new ChatContext(this);
Context.Channels.Add(new ChatChannel(@"Lounge")); Context.Channels.Add(new ChatChannel(@"Lounge"));
@ -75,6 +81,11 @@ namespace SharpChat {
Server = new SharpChatWebSocketServer($@"ws://0.0.0.0:{port}"); Server = new SharpChatWebSocketServer($@"ws://0.0.0.0:{port}");
Server.Start(sock => { Server.Start(sock => {
if(IsShuttingDown || IsDisposed) {
sock.Close(1013);
return;
}
sock.OnOpen = () => OnOpen(sock); sock.OnOpen = () => OnOpen(sock);
sock.OnClose = () => OnClose(sock); sock.OnClose = () => OnClose(sock);
sock.OnError = err => OnError(sock, err); sock.OnError = err => OnError(sock, err);
@ -821,6 +832,25 @@ namespace SharpChat {
user.Send(new LegacyCommandResponse(LCR.IP_ADDRESS, false, ipUser.Username, ip)); user.Send(new LegacyCommandResponse(LCR.IP_ADDRESS, false, ipUser.Username, ip));
break; break;
case @"shutdown":
case @"restart":
if(user.UserId != 1) {
user.Send(new LegacyCommandResponse(LCR.COMMAND_NOT_ALLOWED, true, $@"/{commandName}"));
break;
}
if(IsShuttingDown)
break;
IsShuttingDown = true;
if(commandName == @"restart")
lock(SessionsLock)
Sessions.ForEach(s => s.PrepareForRestart());
Context.Update();
Shutdown.Set();
break;
default: default:
user.Send(new LegacyCommandResponse(LCR.COMMAND_NOT_FOUND, true, commandName)); user.Send(new LegacyCommandResponse(LCR.COMMAND_NOT_FOUND, true, commandName));
break; break;
@ -840,7 +870,9 @@ namespace SharpChat {
return; return;
IsDisposed = true; IsDisposed = true;
Sessions?.Clear(); lock(SessionsLock)
Sessions.ForEach(s => s.Dispose());
Server?.Dispose(); Server?.Dispose();
Context?.Dispose(); Context?.Dispose();
HttpClient?.Dispose(); HttpClient?.Dispose();