diff --git a/Pilz.Net/Api/ApiServer.cs b/Pilz.Net/Api/ApiServer.cs index d7de09a..ea7ec94 100644 --- a/Pilz.Net/Api/ApiServer.cs +++ b/Pilz.Net/Api/ApiServer.cs @@ -3,17 +3,18 @@ using Pilz.Extensions.Reflection; using System.Diagnostics.CodeAnalysis; using System.Net; using System.Reflection; +using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Web; using static Pilz.Net.Api.IApiServer; namespace Pilz.Net.Api; -public class ApiServer(string apiUrl) : IApiServer +public class ApiServer : IApiServer { protected readonly List handlers = []; protected readonly Dictionary serializers = []; - protected HttpListener httpListener = new(); + protected HttpListener httpListener; protected int restartAttempts = 0; protected DateTime lastRestartAttempt; protected SemaphoreSlim? semaphore; @@ -30,7 +31,7 @@ public class ApiServer(string apiUrl) : IApiServer protected record PrivateApiResult(ApiResult Original, object? ResultContent); - public string ApiUrl { get; } = apiUrl; + public string ApiUrl { get; } public virtual bool EnableAuth { get; set; } @@ -44,12 +45,37 @@ public class ApiServer(string apiUrl) : IApiServer public int StopDelay { get; set; } = 5000; - public int AutoRestartOnError { get; set; } = 5000; + public bool AutoRestartOnError { get; set; } = true; public int MaxAutoRestartsPerMinute { get; set; } = 10; public int MaxConcurentConnections { get; set; } = 5; + public ApiServer(string apiUrl) : this(apiUrl, null) + { + } + + public ApiServer(string apiUrl, HttpListener? httpListener) + { + ApiUrl = apiUrl; + this.httpListener = httpListener ?? CreateDefaultHttpListener(); + } + + protected virtual HttpListener CreateDefaultHttpListener() + { + var httpListener = new HttpListener(); + + httpListener.TimeoutManager.IdleConnection = new TimeSpan(0, 10, 0); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + httpListener.TimeoutManager.RequestQueue = new TimeSpan(0, 10, 0); + httpListener.TimeoutManager.HeaderWait = new TimeSpan(0, 10, 0); + } + + return httpListener; + } + public virtual void Start() { Log.Info("Starting listener"); @@ -90,9 +116,19 @@ public class ApiServer(string apiUrl) : IApiServer protected virtual bool AutoRestart(bool graceful) { + if (AutoRestartOnError) + return false; + if (isAutoRestarting) return true; + var now = DateTime.Now; + if (now - lastRestartAttempt > TimeSpan.FromMinutes(1)) + { + lastRestartAttempt = now; + restartAttempts = 0; + } + if (restartAttempts > MaxAutoRestartsPerMinute) { Log.Fatal("Reached maximum auto-restart attempts"); @@ -100,12 +136,7 @@ public class ApiServer(string apiUrl) : IApiServer return false; } - var now = DateTime.Now; - if (now - lastRestartAttempt > TimeSpan.FromMinutes(1)) - lastRestartAttempt = now; - restartAttempts += 1; - isAutoRestarting = true; Restart(graceful); isAutoRestarting = false;