mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2024-11-25 05:42:45 +01:00
129 lines
3.7 KiB
C#
129 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Threading;
|
|
using DHT.Server.Database;
|
|
using DHT.Utils.Logging;
|
|
using Microsoft.AspNetCore;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace DHT.Server.Service {
|
|
public static class ServerLauncher {
|
|
private static readonly Log Log = Log.ForType(typeof(ServerLauncher));
|
|
|
|
private static IWebHost? Server { get; set; } = null;
|
|
|
|
public static bool IsRunning { get; private set; }
|
|
public static event EventHandler? ServerStatusChanged;
|
|
public static event EventHandler<Exception>? ServerManagementExceptionCaught;
|
|
|
|
private static Thread? ManagementThread { get; set; } = null;
|
|
private static readonly Mutex ManagementThreadLock = new();
|
|
private static readonly BlockingCollection<IMessage> Messages = new(new ConcurrentQueue<IMessage>());
|
|
|
|
private static void EnqueueMessage(IMessage message) {
|
|
ManagementThreadLock.WaitOne();
|
|
|
|
try {
|
|
if (ManagementThread == null) {
|
|
ManagementThread = new Thread(RunManagementThread) {
|
|
Name = "DHT server management thread",
|
|
IsBackground = true
|
|
};
|
|
ManagementThread.Start();
|
|
}
|
|
|
|
Messages.Add(message);
|
|
} finally {
|
|
ManagementThreadLock.ReleaseMutex();
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("ReSharper", "FunctionNeverReturns")]
|
|
private static void RunManagementThread() {
|
|
foreach (IMessage message in Messages.GetConsumingEnumerable()) {
|
|
try {
|
|
switch (message) {
|
|
case IMessage.StartServer start:
|
|
StopServerFromManagementThread();
|
|
StartServerFromManagementThread(start.Port, start.Token, start.Db);
|
|
break;
|
|
case IMessage.StopServer:
|
|
StopServerFromManagementThread();
|
|
break;
|
|
}
|
|
} catch (Exception e) {
|
|
ServerManagementExceptionCaught?.Invoke(null, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void StartServerFromManagementThread(int port, string token, IDatabaseFile db) {
|
|
Log.Info("Starting server on port " + port + "...");
|
|
|
|
void AddServices(IServiceCollection services) {
|
|
services.AddSingleton(typeof(IDatabaseFile), db);
|
|
services.AddSingleton(typeof(ServerParameters), new ServerParameters {
|
|
Token = token
|
|
});
|
|
}
|
|
|
|
void SetKestrelOptions(KestrelServerOptions options) {
|
|
options.Limits.MaxRequestBodySize = null;
|
|
options.Limits.MinResponseDataRate = null;
|
|
options.ListenLocalhost(port, static listenOptions => listenOptions.Protocols = HttpProtocols.Http1);
|
|
}
|
|
|
|
Server = WebHost.CreateDefaultBuilder()
|
|
.ConfigureServices(AddServices)
|
|
.UseKestrel(SetKestrelOptions)
|
|
.UseStartup<Startup>()
|
|
.Build();
|
|
|
|
Server.Start();
|
|
|
|
Log.Info("Server started");
|
|
IsRunning = true;
|
|
ServerStatusChanged?.Invoke(null, EventArgs.Empty);
|
|
}
|
|
|
|
private static void StopServerFromManagementThread() {
|
|
if (Server != null) {
|
|
Log.Info("Stopping server...");
|
|
Server.StopAsync().Wait();
|
|
|
|
Log.Info("Server stopped");
|
|
IsRunning = false;
|
|
ServerStatusChanged?.Invoke(null, EventArgs.Empty);
|
|
Server = null;
|
|
}
|
|
}
|
|
|
|
public static void Relaunch(int port, string token, IDatabaseFile db) {
|
|
EnqueueMessage(new IMessage.StartServer(port, token, db));
|
|
}
|
|
|
|
public static void Stop() {
|
|
EnqueueMessage(new IMessage.StopServer());
|
|
}
|
|
|
|
private interface IMessage {
|
|
public sealed class StartServer : IMessage {
|
|
public int Port { get; }
|
|
public string Token { get; }
|
|
public IDatabaseFile Db { get; }
|
|
|
|
public StartServer(int port, string token, IDatabaseFile db) {
|
|
this.Port = port;
|
|
this.Token = token;
|
|
this.Db = db;
|
|
}
|
|
}
|
|
|
|
public sealed class StopServer : IMessage {}
|
|
}
|
|
}
|
|
}
|