Bläddra i källkod

add GlobalListener

陈国伟 3 år sedan
förälder
incheckning
402b7c5f2a

+ 137 - 0
FastGithub.Configuration/GlobalListener.cs

@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.NetworkInformation;
+
+namespace FastGithub.Configuration
+{
+    /// <summary>
+    /// 监听器
+    /// </summary>
+    public static class GlobalListener
+    {
+        private static readonly IPGlobalProperties global = IPGlobalProperties.GetIPGlobalProperties();
+        private static readonly HashSet<int> tcpListenPorts = GetListenPorts(global.GetActiveTcpListeners);
+        private static readonly HashSet<int> udpListenPorts = GetListenPorts(global.GetActiveUdpListeners);
+
+        /// <summary>
+        /// ssh端口
+        /// </summary>
+        public static int SshPort { get; } = GetAvailableTcpPort(22);
+
+        /// <summary>
+        /// git端口
+        /// </summary>
+        public static int GitPort { get; } = GetAvailableTcpPort(9418);
+
+        /// <summary>
+        /// http端口
+        /// </summary>
+        public static int HttpPort { get; } = OperatingSystem.IsWindows() ? GetAvailableTcpPort(80) : GetAvailableTcpPort(3880);
+
+        /// <summary>
+        /// https端口
+        /// </summary>
+        public static int HttpsPort { get; } = OperatingSystem.IsWindows() ? GetAvailableTcpPort(443) : GetAvailableTcpPort(38443);
+
+        /// <summary>
+        /// 获取已监听的端口
+        /// </summary>
+        /// <param name="func"></param>
+        /// <returns></returns>
+        private static HashSet<int> GetListenPorts(Func<IPEndPoint[]> func)
+        {
+            var hashSet = new HashSet<int>();
+            try
+            {
+                foreach (var endpoint in func())
+                {
+                    hashSet.Add(endpoint.Port);
+                }
+            }
+            catch (Exception)
+            {
+            }
+            return hashSet;
+        }
+
+        /// <summary>
+        /// 是可以监听TCP
+        /// </summary>
+        /// <param name="port"></param>
+        /// <returns></returns>
+        public static bool CanListenTcp(int port)
+        {
+            return tcpListenPorts.Contains(port) == false;
+        }
+
+        /// <summary>
+        /// 是可以监听UDP
+        /// </summary>
+        /// <param name="port"></param>
+        /// <returns></returns>
+        public static bool CanListenUdp(int port)
+        {
+            return udpListenPorts.Contains(port) == false;
+        }
+
+        /// <summary>
+        /// 是可以监听TCP和Udp
+        /// </summary>
+        /// <param name="port"></param>
+        /// <returns></returns>
+        public static bool CanListen(int port)
+        {
+            return CanListenTcp(port) && CanListenUdp(port);
+        }
+
+        /// <summary>
+        /// 获取可用的随机Tcp端口
+        /// </summary>
+        /// <param name="minPort"></param> 
+        /// <returns></returns>
+        public static int GetAvailableTcpPort(int minPort)
+        {
+            return GetAvailablePort(CanListenTcp, minPort);
+        }
+
+        /// <summary>
+        /// 获取可用的随机Udp端口
+        /// </summary>
+        /// <param name="minPort"></param> 
+        /// <returns></returns>
+        public static int GetAvailableUdpPort(int minPort)
+        {
+            return GetAvailablePort(CanListenUdp, minPort);
+        }
+
+        /// <summary>
+        /// 获取可用的随机端口
+        /// </summary>
+        /// <param name="minPort"></param> 
+        /// <returns></returns>
+        public static int GetAvailablePort(int minPort)
+        {
+            return GetAvailablePort(CanListen, minPort);
+        }
+
+        /// <summary>
+        /// 获取可用端口
+        /// </summary>
+        /// <param name="canFunc"></param>
+        /// <param name="minPort"></param>
+        /// <returns></returns>
+        /// <exception cref="FastGithubException"></exception>
+        private static int GetAvailablePort(Func<int, bool> canFunc, int minPort)
+        {
+            for (var port = minPort; port < IPEndPoint.MaxPort; port++)
+            {
+                if (canFunc(port) == true)
+                {
+                    return port;
+                }
+            }
+            throw new FastGithubException("当前无可用的端口");
+        }
+    }
+}

+ 0 - 82
FastGithub.Configuration/ReverseProxyPort.cs

@@ -1,82 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.NetworkInformation;
-
-namespace FastGithub.Configuration
-{
-    /// <summary>
-    /// 反向代理端口
-    /// </summary>
-    public static class ReverseProxyPort
-    {
-        /// <summary>
-        /// ssh端口
-        /// </summary>
-        public static int Ssh { get; }
-
-        /// <summary>
-        /// git端口
-        /// </summary>
-        public static int Git { get; }
-
-        /// <summary>
-        /// http端口
-        /// </summary>
-        public static int Http { get; }
-
-        /// <summary>
-        /// https端口
-        /// </summary>
-        public static int Https { get; }
-
-        /// <summary>
-        /// 反向代理端口
-        /// </summary>
-        static ReverseProxyPort()
-        {
-            var ports = new TcpListenerPortCollection();
-            Ssh = ports.GetAvailablePort(22);
-            Git = ports.GetAvailablePort(9418);
-            Http = OperatingSystem.IsWindows() ? ports.GetAvailablePort(80) : ports.GetAvailablePort(3880);
-            Https = OperatingSystem.IsWindows() ? ports.GetAvailablePort(443) : ports.GetAvailablePort(38443);
-        }
-
-        /// <summary>
-        /// 已监听的tcp端口集合
-        /// </summary>
-        private class TcpListenerPortCollection
-        {
-            private readonly HashSet<int> tcpPorts = new();
-
-            /// <summary>
-            /// 已监听的tcp端口集合
-            /// </summary>
-            public TcpListenerPortCollection()
-            {
-                var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
-                foreach (var endpoint in tcpListeners)
-                {
-                    this.tcpPorts.Add(endpoint.Port);
-                }
-            }
-
-            /// <summary>
-            /// 获取可用的随机Tcp端口
-            /// </summary>
-            /// <param name="minValue"></param> 
-            /// <returns></returns>
-            public int GetAvailablePort(int minValue)
-            {
-                for (var port = minValue; port < IPEndPoint.MaxPort; port++)
-                {
-                    if (this.tcpPorts.Contains(port) == false)
-                    {
-                        return port;
-                    }
-                }
-                throw new FastGithubException("当前无可用的端口");
-            }
-        }
-    }
-}

+ 1 - 35
FastGithub.DomainResolve/DnscryptProxy.cs

@@ -1,13 +1,10 @@
 using FastGithub.Configuration;
 using Microsoft.Extensions.Logging;
 using System;
-using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
 using static PInvoke.AdvApi32;
@@ -75,7 +72,7 @@ namespace FastGithub.DomainResolve
         /// <returns></returns>
         private async Task StartCoreAsync(CancellationToken cancellationToken)
         {
-            var port = GetAvailablePort(IPAddress.Loopback.AddressFamily);
+            var port = GlobalListener.GetAvailablePort(5533);
             var localEndPoint = new IPEndPoint(IPAddress.Loopback, port);
 
             await TomlUtil.SetListensAsync(this.tomlFilePath, localEndPoint, cancellationToken);
@@ -129,37 +126,6 @@ namespace FastGithub.DomainResolve
             }
         }
 
-        /// <summary>
-        /// 获取可用的随机端口
-        /// </summary>
-        /// <param name="addressFamily"></param>
-        /// <param name="min">最小值</param>
-        /// <returns></returns>
-        private static int GetAvailablePort(AddressFamily addressFamily, int min = 5533)
-        {
-            var hashSet = new HashSet<int>();
-            var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
-            var udpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners();
-
-            foreach (var endPoint in tcpListeners.Concat(udpListeners))
-            {
-                if (endPoint.AddressFamily == addressFamily)
-                {
-                    hashSet.Add(endPoint.Port);
-                }
-            }
-
-            for (var port = min; port < IPEndPoint.MaxPort; port++)
-            {
-                if (hashSet.Contains(port) == false)
-                {
-                    return port;
-                }
-            }
-
-            throw new FastGithubException("当前无可用的端口");
-        }
-
         /// <summary>
         /// 启动DnscryptProxy进程
         /// </summary> 

+ 2 - 2
FastGithub.HttpServer/HttpProxyMiddleware.cs

@@ -212,13 +212,13 @@ namespace FastGithub.HttpServer
 
             if (targetPort == HTTP_PORT)
             {
-                yield return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Http);
+                yield return new IPEndPoint(IPAddress.Loopback, GlobalListener.HttpPort);
                 yield break;
             }
 
             if (targetPort == HTTPS_PORT)
             {
-                yield return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Https);
+                yield return new IPEndPoint(IPAddress.Loopback, GlobalListener.HttpsPort);
                 yield break;
             }
 

+ 5 - 18
FastGithub.HttpServer/KestrelServerOptionsExtensions.cs

@@ -7,8 +7,6 @@ using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
 using System;
-using System.Linq;
-using System.Net.NetworkInformation;
 
 namespace FastGithub
 {
@@ -37,7 +35,7 @@ namespace FastGithub
             var options = kestrel.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value;
             var httpProxyPort = options.HttpProxyPort;
 
-            if (CanListenTcp(httpProxyPort) == false)
+            if (GlobalListener.CanListenTcp(httpProxyPort) == false)
             {
                 throw new FastGithubException($"tcp端口{httpProxyPort}已经被其它进程占用,请在配置文件更换{nameof(FastGithubOptions.HttpProxyPort)}为其它端口");
             }
@@ -53,7 +51,7 @@ namespace FastGithub
         /// <param name="kestrel"></param>
         public static void ListenSshReverseProxy(this KestrelServerOptions kestrel)
         {
-            var sshPort = ReverseProxyPort.Ssh;
+            var sshPort = GlobalListener.SshPort;
             kestrel.ListenLocalhost(sshPort, listen =>
             {
                 listen.UseFlowAnalyze();
@@ -69,7 +67,7 @@ namespace FastGithub
         /// <param name="kestrel"></param>
         public static void ListenGitReverseProxy(this KestrelServerOptions kestrel)
         {
-            var gitPort = ReverseProxyPort.Git;
+            var gitPort = GlobalListener.GitPort;
             kestrel.ListenLocalhost(gitPort, listen =>
             {
                 listen.UseFlowAnalyze();
@@ -85,7 +83,7 @@ namespace FastGithub
         /// <param name="kestrel"></param>
         public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel)
         {
-            var httpPort = ReverseProxyPort.Http;
+            var httpPort = GlobalListener.HttpPort;
             kestrel.ListenLocalhost(httpPort);
 
             if (OperatingSystem.IsWindows())
@@ -105,7 +103,7 @@ namespace FastGithub
             certService.CreateCaCertIfNotExists();
             certService.InstallAndTrustCaCert();
 
-            var httpsPort = ReverseProxyPort.Https;
+            var httpsPort = GlobalListener.HttpsPort;
             kestrel.ListenLocalhost(httpsPort, listen =>
             {
                 if (OperatingSystem.IsWindows())
@@ -135,16 +133,5 @@ namespace FastGithub
             var loggerFactory = kestrel.ApplicationServices.GetRequiredService<ILoggerFactory>();
             return loggerFactory.CreateLogger($"{nameof(FastGithub)}.{nameof(HttpServer)}");
         }
-
-        /// <summary>
-        /// 是否可以监听指定tcp端口
-        /// </summary>
-        /// <param name="port"></param> 
-        /// <returns></returns>
-        private static bool CanListenTcp(int port)
-        {
-            var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
-            return tcpListeners.Any(item => item.Port == port) == false;
-        }
     }
 }

+ 1 - 1
FastGithub.PacketIntercept/Tcp/GitInterceptor.cs

@@ -15,7 +15,7 @@ namespace FastGithub.PacketIntercept.Tcp
         /// </summary>
         /// <param name="logger"></param>
         public GitInterceptor(ILogger<HttpInterceptor> logger)
-            : base(9418, ReverseProxyPort.Git, logger)
+            : base(9418, GlobalListener.GitPort, logger)
         {
         }
     }

+ 1 - 1
FastGithub.PacketIntercept/Tcp/HttpInterceptor.cs

@@ -15,7 +15,7 @@ namespace FastGithub.PacketIntercept.Tcp
         /// </summary>
         /// <param name="logger"></param>
         public HttpInterceptor(ILogger<HttpInterceptor> logger)
-            : base(80, ReverseProxyPort.Http, logger)
+            : base(80, GlobalListener.HttpPort, logger)
         {
         }
     }

+ 1 - 1
FastGithub.PacketIntercept/Tcp/HttpsInterceptor.cs

@@ -15,7 +15,7 @@ namespace FastGithub.PacketIntercept.Tcp
         /// </summary>
         /// <param name="logger"></param>
         public HttpsInterceptor(ILogger<HttpsInterceptor> logger)
-            : base(443, ReverseProxyPort.Https, logger)
+            : base(443, GlobalListener.HttpsPort, logger)
         {
         }
     }

+ 1 - 1
FastGithub.PacketIntercept/Tcp/SshInterceptor.cs

@@ -15,7 +15,7 @@ namespace FastGithub.PacketIntercept.Tcp
         /// </summary>
         /// <param name="logger"></param>
         public SshInterceptor(ILogger<HttpInterceptor> logger)
-            : base(22, ReverseProxyPort.Ssh, logger)
+            : base(22, GlobalListener.SshPort, logger)
         {
         }
     }