EndPointManager.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Net;
  5. using System.Reflection;
  6. using System.Threading.Tasks;
  7. using MediaBrowser.Model.IO;
  8. using MediaBrowser.Model.Logging;
  9. using MediaBrowser.Model.Net;
  10. using SocketHttpListener.Primitives;
  11. namespace SocketHttpListener.Net
  12. {
  13. sealed class EndPointManager
  14. {
  15. // Dictionary<IPAddress, Dictionary<int, EndPointListener>>
  16. static Dictionary<string, Dictionary<int, EndPointListener>> ip_to_endpoints = new Dictionary<string, Dictionary<int, EndPointListener>>();
  17. private EndPointManager()
  18. {
  19. }
  20. public static void AddListener(ILogger logger, HttpListener listener)
  21. {
  22. List<string> added = new List<string>();
  23. try
  24. {
  25. lock (ip_to_endpoints)
  26. {
  27. foreach (string prefix in listener.Prefixes)
  28. {
  29. AddPrefixInternal(logger, prefix, listener);
  30. added.Add(prefix);
  31. }
  32. }
  33. }
  34. catch
  35. {
  36. foreach (string prefix in added)
  37. {
  38. RemovePrefix(logger, prefix, listener);
  39. }
  40. throw;
  41. }
  42. }
  43. public static void AddPrefix(ILogger logger, string prefix, HttpListener listener)
  44. {
  45. lock (ip_to_endpoints)
  46. {
  47. AddPrefixInternal(logger, prefix, listener);
  48. }
  49. }
  50. static void AddPrefixInternal(ILogger logger, string p, HttpListener listener)
  51. {
  52. ListenerPrefix lp = new ListenerPrefix(p);
  53. if (lp.Path.IndexOf('%') != -1)
  54. throw new HttpListenerException(400, "Invalid path.");
  55. if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1) // TODO: Code?
  56. throw new HttpListenerException(400, "Invalid path.");
  57. // listens on all the interfaces if host name cannot be parsed by IPAddress.
  58. EndPointListener epl = GetEPListener(logger, lp.Host, lp.Port, listener, lp.Secure).Result;
  59. epl.AddPrefix(lp, listener);
  60. }
  61. private static IPAddress GetIpAnyAddress(HttpListener listener)
  62. {
  63. return listener.EnableDualMode ? IPAddress.IPv6Any : IPAddress.Any;
  64. }
  65. static async Task<EndPointListener> GetEPListener(ILogger logger, string host, int port, HttpListener listener, bool secure)
  66. {
  67. var networkManager = listener.NetworkManager;
  68. IPAddress addr;
  69. if (host == "*" || host == "+")
  70. addr = GetIpAnyAddress(listener);
  71. else if (IPAddress.TryParse(host, out addr) == false)
  72. {
  73. try
  74. {
  75. var all = (await networkManager.GetHostAddressesAsync(host).ConfigureAwait(false));
  76. addr = (all.Length == 0 ? null : IPAddress.Parse(all[0].Address)) ??
  77. GetIpAnyAddress(listener);
  78. }
  79. catch
  80. {
  81. addr = GetIpAnyAddress(listener);
  82. }
  83. }
  84. Dictionary<int, EndPointListener> p = null; // Dictionary<int, EndPointListener>
  85. if (!ip_to_endpoints.TryGetValue(addr.ToString(), out p))
  86. {
  87. p = new Dictionary<int, EndPointListener>();
  88. ip_to_endpoints[addr.ToString()] = p;
  89. }
  90. EndPointListener epl = null;
  91. if (p.ContainsKey(port))
  92. {
  93. epl = (EndPointListener)p[port];
  94. }
  95. else
  96. {
  97. epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem, listener.EnvironmentInfo);
  98. p[port] = epl;
  99. }
  100. return epl;
  101. }
  102. public static void RemoveEndPoint(EndPointListener epl, IPEndPoint ep)
  103. {
  104. lock (ip_to_endpoints)
  105. {
  106. // Dictionary<int, EndPointListener> p
  107. Dictionary<int, EndPointListener> p;
  108. if (ip_to_endpoints.TryGetValue(ep.Address.ToString(), out p))
  109. {
  110. p.Remove(ep.Port);
  111. if (p.Count == 0)
  112. {
  113. ip_to_endpoints.Remove(ep.Address.ToString());
  114. }
  115. }
  116. epl.Close();
  117. }
  118. }
  119. public static void RemoveListener(ILogger logger, HttpListener listener)
  120. {
  121. lock (ip_to_endpoints)
  122. {
  123. foreach (string prefix in listener.Prefixes)
  124. {
  125. RemovePrefixInternal(logger, prefix, listener);
  126. }
  127. }
  128. }
  129. public static void RemovePrefix(ILogger logger, string prefix, HttpListener listener)
  130. {
  131. lock (ip_to_endpoints)
  132. {
  133. RemovePrefixInternal(logger, prefix, listener);
  134. }
  135. }
  136. static void RemovePrefixInternal(ILogger logger, string prefix, HttpListener listener)
  137. {
  138. ListenerPrefix lp = new ListenerPrefix(prefix);
  139. if (lp.Path.IndexOf('%') != -1)
  140. return;
  141. if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1)
  142. return;
  143. EndPointListener epl = GetEPListener(logger, lp.Host, lp.Port, listener, lp.Secure).Result;
  144. epl.RemovePrefix(lp, listener);
  145. }
  146. }
  147. }