NetUtils.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using STUN.Client;
  2. using System;
  3. using System.Diagnostics;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. namespace STUN.Utils
  7. {
  8. public static class NetUtils
  9. {
  10. #region static method IsPrivateIP
  11. /// <summary>
  12. /// Gets if specified IP address is private LAN IP address. For example 192.168.x.x is private ip.
  13. /// </summary>
  14. /// <param name="ip">IP address to check.</param>
  15. /// <returns>Returns true if IP is private IP.</returns>
  16. /// <exception cref="ArgumentNullException">Is raised when <b>ip</b> is null reference.</exception>
  17. public static bool IsPrivateIP(IPAddress ip)
  18. {
  19. if (ip == null)
  20. {
  21. throw new ArgumentNullException(nameof(ip));
  22. }
  23. if (ip.AddressFamily == AddressFamily.InterNetwork)
  24. {
  25. var ipBytes = ip.GetAddressBytes();
  26. /* Private IPs:
  27. First Octet = 192 AND Second Octet = 168 (Example: 192.168.X.X)
  28. First Octet = 172 AND (Second Octet >= 16 AND Second Octet <= 31) (Example: 172.16.X.X - 172.31.X.X)
  29. First Octet = 10 (Example: 10.X.X.X)
  30. First Octet = 169 AND Second Octet = 254 (Example: 169.254.X.X)
  31. */
  32. if (ipBytes[0] == 192 && ipBytes[1] == 168)
  33. {
  34. return true;
  35. }
  36. if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
  37. {
  38. return true;
  39. }
  40. if (ipBytes[0] == 10)
  41. {
  42. return true;
  43. }
  44. if (ipBytes[0] == 169 && ipBytes[1] == 254)
  45. {
  46. return true;
  47. }
  48. }
  49. return false;
  50. }
  51. #endregion
  52. #region static method CreateSocket
  53. /// <summary>
  54. /// Creates new socket for the specified end point.
  55. /// </summary>
  56. /// <param name="localEP">Local end point.</param>
  57. /// <param name="protocolType">Protocol type.</param>
  58. /// <returns>Return newly created socket.</returns>
  59. /// <exception cref="ArgumentNullException">Is raised when <b>localEP</b> is null reference.</exception>
  60. public static Socket CreateSocket(IPEndPoint localEP, ProtocolType protocolType)
  61. {
  62. if (localEP == null)
  63. {
  64. throw new ArgumentNullException(nameof(localEP));
  65. }
  66. var socketType = SocketType.Stream;
  67. if (protocolType == ProtocolType.Udp)
  68. {
  69. socketType = SocketType.Dgram;
  70. }
  71. if (localEP.AddressFamily == AddressFamily.InterNetwork)
  72. {
  73. var socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
  74. socket.Bind(localEP);
  75. return socket;
  76. }
  77. if (localEP.AddressFamily == AddressFamily.InterNetworkV6)
  78. {
  79. var socket = new Socket(AddressFamily.InterNetworkV6, socketType, protocolType);
  80. socket.Bind(localEP);
  81. return socket;
  82. }
  83. throw new ArgumentException(@"Invalid IPEndPoint address family.");
  84. }
  85. #endregion
  86. public const string DefaultLocalEnd = @"0.0.0.0:0";
  87. public static IPEndPoint ParseEndpoint(string str)
  88. {
  89. //TODO:IPv6
  90. var ipPort = str.Trim().Split(':');
  91. if (ipPort.Length == 2)
  92. {
  93. if (IPAddress.TryParse(ipPort[0], out var ip))
  94. {
  95. if (ushort.TryParse(ipPort[1], out var port))
  96. {
  97. return new IPEndPoint(ip, port);
  98. }
  99. }
  100. }
  101. return null;
  102. }
  103. public static (string, string, string) NatTypeTestCore(string local, string server, ushort port)
  104. {
  105. try
  106. {
  107. if (string.IsNullOrWhiteSpace(server))
  108. {
  109. Debug.WriteLine(@"[ERROR]: Please specify STUN server !");
  110. return (string.Empty, DefaultLocalEnd, string.Empty);
  111. }
  112. using var client = new StunClient3489(server, port, ParseEndpoint(local));
  113. var result = (ClassicStunResult)client.Query();
  114. return (
  115. result.NatType.ToString(),
  116. client.LocalEndPoint.ToString(),
  117. $@"{result.PublicEndPoint}"
  118. );
  119. }
  120. catch (Exception ex)
  121. {
  122. Debug.WriteLine($@"[ERROR]: {ex}");
  123. return (string.Empty, DefaultLocalEnd, string.Empty);
  124. }
  125. }
  126. }
  127. }