Unofficial CardLife revival project, pronounced like "celery"
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

162 lignes
5.0KB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Reflection;
  7. using System.Text;
  8. using HarmonyLib;
  9. using Svelto.DataStructures;
  10. namespace CLre_server.WebStatus
  11. {
  12. public class WebServer
  13. {
  14. private const uint DEFAULT_PORT = 5030;
  15. private const string DEFAULT_IP = "localhost";
  16. private readonly HttpListener _httpListener;
  17. public delegate void RequestHandler(HttpListenerContext ctx);
  18. private Dictionary<string, RequestHandler> _handlers = new Dictionary<string, RequestHandler>();
  19. public bool IsRunning
  20. {
  21. get => _httpListener.IsListening;
  22. }
  23. private string _ip_addr;
  24. private uint _port;
  25. public static WebServer MainInstance { get; internal set; }
  26. internal static List<Assembly> _assembliesToCheck = new List<Assembly>(new []{typeof(CLre).Assembly});
  27. public WebServer() : this(DEFAULT_IP, DEFAULT_PORT)
  28. {
  29. }
  30. public WebServer(string ip, uint port)
  31. {
  32. if (!HttpListener.IsSupported)
  33. {
  34. API.Utility.Logging.LogWarning("HTTP Server is unsupported on earlier Windows versions. CLre webserver will fail to start.");
  35. }
  36. _httpListener = new HttpListener();
  37. _httpListener.Prefixes.Add($"http://{ip}:{port}/");
  38. _ip_addr = ip;
  39. _port = port;
  40. }
  41. internal static void Init()
  42. {
  43. if (CLre.Config.web_server || Environment.GetCommandLineArgs().Contains("-web"))
  44. {
  45. API.Utility.Logging.Log("Starting status web server");
  46. StatusEndpoints.Init();
  47. MainInstance = new WebServer();
  48. MainInstance.Start();
  49. }
  50. else
  51. {
  52. API.Utility.Logging.Log("Not starting web server (use CLI argument -web to enable)");
  53. }
  54. }
  55. internal static void Deinit()
  56. {
  57. if (MainInstance != null) MainInstance.Stop();
  58. MainInstance = null;
  59. }
  60. public void Start()
  61. {
  62. LoadHandlers();
  63. try
  64. {
  65. _httpListener.Start();
  66. }
  67. catch (Exception e)
  68. {
  69. API.Utility.Logging.LogWarning(e);
  70. return;
  71. }
  72. HandleAllRequests().Run();
  73. }
  74. public void Stop()
  75. {
  76. try
  77. {
  78. _httpListener.Stop();
  79. _httpListener.Close();
  80. }
  81. catch (Exception e)
  82. {
  83. API.Utility.Logging.LogWarning(e);
  84. return;
  85. }
  86. }
  87. private IEnumerator HandleAllRequests()
  88. {
  89. API.Utility.Logging.MetaLog($"Started HTTP web server at http://{_ip_addr}:{_port}/");
  90. while (_httpListener.IsListening)
  91. {
  92. var awaiter = _httpListener.GetContextAsync();
  93. awaiter.GetAwaiter().OnCompleted(() => DoRequest(awaiter.Result));
  94. yield return null;
  95. }
  96. API.Utility.Logging.MetaLog("Terminated HTTP web server");
  97. }
  98. private void DoRequest(HttpListenerContext ctx)
  99. {
  100. string endpoint = ctx.Request.Url.LocalPath.ToLower();
  101. #if DEBUG
  102. API.Utility.Logging.LogWarning($"Handling HTTP request {endpoint}");
  103. #endif
  104. bool handled = false;
  105. foreach (string path in _handlers.Keys)
  106. {
  107. if (endpoint == path)
  108. {
  109. handled = true;
  110. _handlers[path](ctx);
  111. break;
  112. }
  113. }
  114. if (!handled)
  115. {
  116. AssetEndpoints.Asset404(ctx);
  117. }
  118. //byte[] output = Encoding.UTF8.GetBytes(endpoint);
  119. //ctx.Response.OutputStream.Write(output, 0, output.Length);
  120. ctx.Response.Close();
  121. }
  122. private void LoadHandlers()
  123. {
  124. _handlers = new Dictionary<string, RequestHandler>();
  125. foreach (Assembly asm in _assembliesToCheck.ToArray())
  126. {
  127. foreach (Type t in asm.GetTypes())
  128. {
  129. foreach (MethodInfo m in t.GetMethods(AccessTools.all))
  130. {
  131. WebEndpointAttribute attr = m.GetCustomAttribute<WebEndpointAttribute>();
  132. if (attr != null)
  133. {
  134. // TODO validate that method signature matches that of RequestHandler
  135. string key = attr.GetPath().ToLower();
  136. API.Utility.Logging.MetaLog($"{t.FullName}:{m.Name} is handling {key}");
  137. _handlers.Add(key, (RequestHandler) Delegate.CreateDelegate(typeof(RequestHandler), m));
  138. }
  139. }
  140. }
  141. }
  142. }
  143. }
  144. }