NetUtils.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using NatTypeTester_Console.Net.STUN.Client;
  2. using System;
  3. using System.Diagnostics;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. namespace NatTypeTester_Console.Net
  7. {
  8. public static class NetUtils
  9. {
  10. #region static method CompareArray
  11. /// <summary>
  12. /// Compares if specified array items equals.
  13. /// </summary>
  14. /// <param name="array1">Array 1.</param>
  15. /// <param name="array2">Array 2</param>
  16. /// <returns>Returns true if both arrays are equal.</returns>
  17. public static bool CompareArray(Array array1, Array array2)
  18. {
  19. return CompareArray(array1, array2, array2.Length);
  20. }
  21. /// <summary>
  22. /// Compares if specified array items equals.
  23. /// </summary>
  24. /// <param name="array1">Array 1.</param>
  25. /// <param name="array2">Array 2</param>
  26. /// <param name="array2Count">Number of bytes in array 2 used for compare.</param>
  27. /// <returns>Returns true if both arrays are equal.</returns>
  28. public static bool CompareArray(Array array1, Array array2, int array2Count)
  29. {
  30. if (array1 == null && array2 == null)
  31. {
  32. return true;
  33. }
  34. if (array1 == null)
  35. {
  36. return false;
  37. }
  38. if (array2 == null)
  39. {
  40. return false;
  41. }
  42. if (array1.Length != array2Count)
  43. {
  44. return false;
  45. }
  46. for (var i = 0; i < array1.Length; i++)
  47. {
  48. if (!array1.GetValue(i).Equals(array2.GetValue(i)))
  49. {
  50. return false;
  51. }
  52. }
  53. return true;
  54. }
  55. #endregion
  56. #region static method IsPrivateIP
  57. /// <summary>
  58. /// Gets if specified IP address is private LAN IP address. For example 192.168.x.x is private ip.
  59. /// </summary>
  60. /// <param name="ip">IP address to check.</param>
  61. /// <returns>Returns true if IP is private IP.</returns>
  62. /// <exception cref="ArgumentNullException">Is raised when <b>ip</b> is null reference.</exception>
  63. public static bool IsPrivateIP(IPAddress ip)
  64. {
  65. if (ip == null)
  66. {
  67. throw new ArgumentNullException(nameof(ip));
  68. }
  69. if (ip.AddressFamily == AddressFamily.InterNetwork)
  70. {
  71. var ipBytes = ip.GetAddressBytes();
  72. /* Private IPs:
  73. First Octet = 192 AND Second Octet = 168 (Example: 192.168.X.X)
  74. First Octet = 172 AND (Second Octet >= 16 AND Second Octet <= 31) (Example: 172.16.X.X - 172.31.X.X)
  75. First Octet = 10 (Example: 10.X.X.X)
  76. First Octet = 169 AND Second Octet = 254 (Example: 169.254.X.X)
  77. */
  78. if (ipBytes[0] == 192 && ipBytes[1] == 168)
  79. {
  80. return true;
  81. }
  82. if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
  83. {
  84. return true;
  85. }
  86. if (ipBytes[0] == 10)
  87. {
  88. return true;
  89. }
  90. if (ipBytes[0] == 169 && ipBytes[1] == 254)
  91. {
  92. return true;
  93. }
  94. }
  95. return false;
  96. }
  97. #endregion
  98. #region static method CreateSocket
  99. /// <summary>
  100. /// Creates new socket for the specified end point.
  101. /// </summary>
  102. /// <param name="localEP">Local end point.</param>
  103. /// <param name="protocolType">Protocol type.</param>
  104. /// <returns>Return newly created socket.</returns>
  105. /// <exception cref="ArgumentNullException">Is raised when <b>localEP</b> is null reference.</exception>
  106. public static Socket CreateSocket(IPEndPoint localEP, ProtocolType protocolType)
  107. {
  108. if (localEP == null)
  109. {
  110. throw new ArgumentNullException(nameof(localEP));
  111. }
  112. var socketType = SocketType.Stream;
  113. if (protocolType == ProtocolType.Udp)
  114. {
  115. socketType = SocketType.Dgram;
  116. }
  117. if (localEP.AddressFamily == AddressFamily.InterNetwork)
  118. {
  119. var socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
  120. socket.Bind(localEP);
  121. return socket;
  122. }
  123. if (localEP.AddressFamily == AddressFamily.InterNetworkV6)
  124. {
  125. var socket = new Socket(AddressFamily.InterNetworkV6, socketType, protocolType);
  126. socket.Bind(localEP);
  127. return socket;
  128. }
  129. throw new ArgumentException(@"Invalid IPEndPoint address family.");
  130. }
  131. #endregion
  132. public const string DefaultLocalEnd = @"0.0.0.0:0";
  133. public static IPEndPoint ParseEndpoint(string str)
  134. {
  135. var ipPort = str.Trim().Split(':');
  136. if (ipPort.Length == 2)
  137. {
  138. if (IPAddress.TryParse(ipPort[0], out var ip))
  139. {
  140. if (ushort.TryParse(ipPort[1], out var port))
  141. {
  142. return new IPEndPoint(ip, port);
  143. }
  144. }
  145. }
  146. return null;
  147. }
  148. public static (string, string, string) NatTypeTestCore(string local, string server, int port)
  149. {
  150. try
  151. {
  152. if (string.IsNullOrWhiteSpace(server))
  153. {
  154. Debug.WriteLine(@"[ERROR]: Please specify STUN server !");
  155. return (string.Empty, DefaultLocalEnd, string.Empty);
  156. }
  157. using var socketV4 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  158. var ipe = ParseEndpoint(local) ?? new IPEndPoint(IPAddress.Any, 0);
  159. socketV4.Bind(ipe);
  160. var result = StunClient.Query(server, port, socketV4);
  161. return (
  162. result.NatType.ToString(),
  163. socketV4.LocalEndPoint.ToString(),
  164. result.NatType != NatType.UdpBlocked ? result.PublicEndPoint.ToString() : string.Empty
  165. );
  166. }
  167. catch (Exception ex)
  168. {
  169. Debug.WriteLine($@"[ERROR]: {ex}");
  170. return (string.Empty, DefaultLocalEnd, string.Empty);
  171. }
  172. }
  173. }
  174. }