|
|
@@ -0,0 +1,80 @@
|
|
|
+using System;
|
|
|
+using System.Net;
|
|
|
+using System.Text;
|
|
|
+using System.Threading;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using Newtonsoft.Json;
|
|
|
+
|
|
|
+namespace IvfTl.ControlHost
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// control 进程内的本地 HTTP 小服务,只监听 127.0.0.1:port。
|
|
|
+ /// 阶段1:/ping、/status。阶段2 扩展 /serial/pause|resume、/shutdown。
|
|
|
+ /// </summary>
|
|
|
+ public class ControlHttpServer
|
|
|
+ {
|
|
|
+ private readonly int _port;
|
|
|
+ private readonly Func<StatusDto> _statusProvider;
|
|
|
+ private readonly Action<string> _log;
|
|
|
+ private HttpListener _listener;
|
|
|
+ private CancellationTokenSource _cts;
|
|
|
+
|
|
|
+ public ControlHttpServer(int port, Func<StatusDto> statusProvider, Action<string> log)
|
|
|
+ {
|
|
|
+ _port = port;
|
|
|
+ _statusProvider = statusProvider;
|
|
|
+ _log = log ?? (_ => { });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Start()
|
|
|
+ {
|
|
|
+ _listener = new HttpListener();
|
|
|
+ _listener.Prefixes.Add($"http://127.0.0.1:{_port}/");
|
|
|
+ _listener.Start();
|
|
|
+ _cts = new CancellationTokenSource();
|
|
|
+ _log($"ControlHttpServer 监听 http://127.0.0.1:{_port}/");
|
|
|
+ Task.Run(() => Loop(_cts.Token));
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task Loop(CancellationToken token)
|
|
|
+ {
|
|
|
+ while (!token.IsCancellationRequested)
|
|
|
+ {
|
|
|
+ HttpListenerContext ctx;
|
|
|
+ try { ctx = await _listener.GetContextAsync(); }
|
|
|
+ catch (Exception ex) { if (!token.IsCancellationRequested) _log("HttpListener 异常:" + ex.Message); break; }
|
|
|
+ try { Handle(ctx); }
|
|
|
+ catch (Exception ex) { _log("处理请求异常:" + ex.Message); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Handle(HttpListenerContext ctx)
|
|
|
+ {
|
|
|
+ string path = ctx.Request.Url.AbsolutePath.TrimEnd('/').ToLowerInvariant();
|
|
|
+ string body;
|
|
|
+ int code = 200;
|
|
|
+ switch (path)
|
|
|
+ {
|
|
|
+ case "/ping":
|
|
|
+ case "/status":
|
|
|
+ body = JsonConvert.SerializeObject(_statusProvider());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ code = 404; body = "{\"ok\":false,\"error\":\"not found\"}";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ byte[] buf = Encoding.UTF8.GetBytes(body);
|
|
|
+ ctx.Response.StatusCode = code;
|
|
|
+ ctx.Response.ContentType = "application/json";
|
|
|
+ ctx.Response.ContentLength64 = buf.Length;
|
|
|
+ ctx.Response.OutputStream.Write(buf, 0, buf.Length);
|
|
|
+ ctx.Response.OutputStream.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Stop()
|
|
|
+ {
|
|
|
+ try { _cts?.Cancel(); _listener?.Stop(); _listener?.Close(); }
|
|
|
+ catch (Exception ex) { _log("ControlHttpServer 停止异常:" + ex.Message); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|