Bruce Wayne 5 年 前
コミット
9a6833f0a5
4 ファイル変更24 行追加101 行削除
  1. 2 1
      NatTypeTester/Model/StunServer.cs
  2. 18 6
      STUN/Client/StunClient3489.cs
  3. 4 0
      STUN/STUN.csproj
  4. 0 94
      STUN/Utils/NetUtils.cs

+ 2 - 1
NatTypeTester/Model/StunServer.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Net;
 
 namespace NatTypeTester.Model
 {
@@ -17,7 +18,7 @@ namespace NatTypeTester.Model
         {
             var ipPort = str.Trim().Split(':', ':');
             var host = ipPort[0].Trim();
-            if (Uri.CheckHostName(host) != UriHostNameType.Dns)
+            if (Uri.CheckHostName(host) != UriHostNameType.Dns && !IPAddress.TryParse(host, out _))
             {
                 return false;
             }

+ 18 - 6
STUN/Client/StunClient3489.cs

@@ -1,4 +1,4 @@
-using STUN.Client.Enums;
+using STUN.Client.Enums;
 using STUN.Client.Interfaces;
 using STUN.Message;
 using STUN.Message.Enums;
@@ -17,9 +17,16 @@ namespace STUN.Client
     /// </summary>
     public class StunClient3489 : IStunClient
     {
-        private readonly UdpClient _udpClient;
         public IPEndPoint LocalEndPoint => (IPEndPoint)_udpClient.Client.LocalEndPoint;
 
+        public TimeSpan Timeout
+        {
+            get => TimeSpan.FromMilliseconds(_udpClient.Client.ReceiveTimeout);
+            set => _udpClient.Client.ReceiveTimeout = Convert.ToInt32(value.TotalMilliseconds);
+        }
+
+        private readonly UdpClient _udpClient;
+
         private readonly string _server;
         private readonly ushort _port;
 
@@ -40,7 +47,7 @@ namespace STUN.Client
 
             _udpClient = local == null ? new UdpClient() : new UdpClient(local);
 
-            _udpClient.Client.ReceiveTimeout = TimeSpan.FromSeconds(1.6).Milliseconds;
+            Timeout = TimeSpan.FromSeconds(1.6);
         }
 
         public IStunResult Query()
@@ -55,7 +62,12 @@ namespace STUN.Client
             }
             var mappedAddress1 = AttributeExtensions.GetMappedAddressAttribute(response1);
             var changedAddress1 = AttributeExtensions.GetChangedAddressAttribute(response1);
-            if (mappedAddress1 == null || changedAddress1 == null)
+
+            // 某些单 IP 服务器的迷惑操作
+            if (mappedAddress1 == null
+            || changedAddress1 == null
+            || Equals(changedAddress1.Address, remote1.Address)
+            || changedAddress1.Port == remote1.Port)
             {
                 return new ClassicStunResult(NatType.UnsupportedServer, null);
             }
@@ -85,7 +97,7 @@ namespace STUN.Client
             if (response2 != null)
             {
                 // 有些单 IP 服务器并不能测 NAT 类型,比如 Google 的
-                var type = Equals(remote1.Address, remote2.Address) || Equals(remote1.Port, remote2.Port) ? NatType.UnsupportedServer : NatType.FullCone;
+                var type = Equals(remote1.Address, remote2.Address) || remote1.Port == remote2.Port ? NatType.UnsupportedServer : NatType.FullCone;
                 return new ClassicStunResult(type, mappedAddress2);
             }
 
@@ -166,7 +178,7 @@ namespace STUN.Client
             }
             catch (Exception ex)
             {
-                Debug.WriteLine(ex.Message);
+                Debug.WriteLine(ex);
             }
             return (null, null);
         }

+ 4 - 0
STUN/STUN.csproj

@@ -5,4 +5,8 @@
     <LangVersion>latest</LangVersion>
   </PropertyGroup>
 
+  <ItemGroup>
+    <PackageReference Include="System.Memory" Version="4.5.4" />
+  </ItemGroup>
+
 </Project>

+ 0 - 94
STUN/Utils/NetUtils.cs

@@ -2,105 +2,11 @@
 using System;
 using System.Diagnostics;
 using System.Net;
-using System.Net.Sockets;
 
 namespace STUN.Utils
 {
     public static class NetUtils
     {
-        #region static method IsPrivateIP
-
-        /// <summary>
-        /// Gets if specified IP address is private LAN IP address. For example 192.168.x.x is private ip.
-        /// </summary>
-        /// <param name="ip">IP address to check.</param>
-        /// <returns>Returns true if IP is private IP.</returns>
-        /// <exception cref="ArgumentNullException">Is raised when <b>ip</b> is null reference.</exception>
-        public static bool IsPrivateIP(IPAddress ip)
-        {
-            if (ip == null)
-            {
-                throw new ArgumentNullException(nameof(ip));
-            }
-
-            if (ip.AddressFamily == AddressFamily.InterNetwork)
-            {
-                var ipBytes = ip.GetAddressBytes();
-
-                /* Private IPs:
-					First Octet = 192 AND Second Octet = 168 (Example: 192.168.X.X) 
-					First Octet = 172 AND (Second Octet >= 16 AND Second Octet <= 31) (Example: 172.16.X.X - 172.31.X.X)
-					First Octet = 10 (Example: 10.X.X.X)
-					First Octet = 169 AND Second Octet = 254 (Example: 169.254.X.X)
-
-				*/
-
-                if (ipBytes[0] == 192 && ipBytes[1] == 168)
-                {
-                    return true;
-                }
-                if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
-                {
-                    return true;
-                }
-                if (ipBytes[0] == 10)
-                {
-                    return true;
-                }
-                if (ipBytes[0] == 169 && ipBytes[1] == 254)
-                {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        #endregion
-
-        #region static method CreateSocket
-
-        /// <summary>
-        /// Creates new socket for the specified end point.
-        /// </summary>
-        /// <param name="localEP">Local end point.</param>
-        /// <param name="protocolType">Protocol type.</param>
-        /// <returns>Return newly created socket.</returns>
-        /// <exception cref="ArgumentNullException">Is raised when <b>localEP</b> is null reference.</exception>
-        public static Socket CreateSocket(IPEndPoint localEP, ProtocolType protocolType)
-        {
-            if (localEP == null)
-            {
-                throw new ArgumentNullException(nameof(localEP));
-            }
-
-            var socketType = SocketType.Stream;
-            if (protocolType == ProtocolType.Udp)
-            {
-                socketType = SocketType.Dgram;
-            }
-
-            if (localEP.AddressFamily == AddressFamily.InterNetwork)
-            {
-                var socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
-                socket.Bind(localEP);
-
-                return socket;
-            }
-
-            if (localEP.AddressFamily == AddressFamily.InterNetworkV6)
-            {
-                var socket = new Socket(AddressFamily.InterNetworkV6, socketType, protocolType);
-                socket.Bind(localEP);
-
-                return socket;
-            }
-
-            throw new ArgumentException(@"Invalid IPEndPoint address family.");
-        }
-
-        #endregion
-
         public const string DefaultLocalEnd = @"0.0.0.0:0";
 
         public static IPEndPoint ParseEndpoint(string str)