PageRenderTime 69ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/ThirdParty/Lidgren.Network/NetUtility.cs

https://github.com/notJUSTguitar/MonoGame
C# | 378 lines | 268 code | 40 blank | 70 comment | 64 complexity | ecbeab32fe0ce9f51d3a8f273045e4c1 MD5 | raw file
  1. /* Copyright (c) 2010 Michael Lidgren
  2. Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  3. and associated documentation files (the "Software"), to deal in the Software without
  4. restriction, including without limitation the rights to use, copy, modify, merge, publish,
  5. distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom
  6. the Software is furnished to do so, subject to the following conditions:
  7. The above copyright notice and this permission notice shall be included in all copies or
  8. substantial portions of the Software.
  9. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  10. INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  11. PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  12. LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  13. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  14. USE OR OTHER DEALINGS IN THE SOFTWARE.
  15. */
  16. #if !ANDROID && !IOS
  17. #define IS_FULL_NET_AVAILABLE
  18. #endif
  19. using System;
  20. using System.Net;
  21. using System.Net.NetworkInformation;
  22. using System.Net.Sockets;
  23. using System.Text;
  24. using System.Text.RegularExpressions;
  25. namespace Lidgren.Network
  26. {
  27. /// <summary>
  28. /// Utility methods
  29. /// </summary>
  30. public static class NetUtility
  31. {
  32. /// <summary>
  33. /// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number
  34. /// </summary>
  35. public static IPEndPoint Resolve(string ipOrHost, int port)
  36. {
  37. IPAddress adr = Resolve(ipOrHost);
  38. return new IPEndPoint(adr, port);
  39. }
  40. /// <summary>
  41. /// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname
  42. /// </summary>
  43. public static IPAddress Resolve(string ipOrHost)
  44. {
  45. if (string.IsNullOrEmpty(ipOrHost))
  46. throw new ArgumentException("Supplied string must not be empty", "ipOrHost");
  47. ipOrHost = ipOrHost.Trim();
  48. IPAddress ipAddress = null;
  49. if (IPAddress.TryParse(ipOrHost, out ipAddress))
  50. {
  51. if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
  52. return ipAddress;
  53. throw new ArgumentException("This method will not currently resolve other than ipv4 addresses");
  54. }
  55. // ok must be a host name
  56. IPHostEntry entry;
  57. try
  58. {
  59. entry = Dns.GetHostEntry(ipOrHost);
  60. if (entry == null)
  61. return null;
  62. // check each entry for a valid IP address
  63. foreach (IPAddress ipCurrent in entry.AddressList)
  64. {
  65. if (ipCurrent.AddressFamily == AddressFamily.InterNetwork)
  66. return ipCurrent;
  67. }
  68. return null;
  69. }
  70. catch (SocketException ex)
  71. {
  72. if (ex.SocketErrorCode == SocketError.HostNotFound)
  73. {
  74. //LogWrite(string.Format(CultureInfo.InvariantCulture, "Failed to resolve host '{0}'.", ipOrHost));
  75. return null;
  76. }
  77. else
  78. {
  79. throw;
  80. }
  81. }
  82. }
  83. #if IS_FULL_NET_AVAILABLE
  84. private static NetworkInterface GetNetworkInterface()
  85. {
  86. //IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
  87. //if (computerProperties == null)
  88. // return null;
  89. NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
  90. if (nics == null || nics.Length < 1)
  91. return null;
  92. NetworkInterface best = null;
  93. foreach (NetworkInterface adapter in nics)
  94. {
  95. if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback || adapter.NetworkInterfaceType == NetworkInterfaceType.Unknown)
  96. continue;
  97. if (!adapter.Supports(NetworkInterfaceComponent.IPv4))
  98. continue;
  99. if (best == null)
  100. best = adapter;
  101. if (adapter.OperationalStatus != OperationalStatus.Up)
  102. continue;
  103. // A computer could have several adapters (more than one network card)
  104. // here but just return the first one for now...
  105. return adapter;
  106. }
  107. return best;
  108. }
  109. /// <summary>
  110. /// Returns the physical (MAC) address for the first usable network interface
  111. /// </summary>
  112. public static PhysicalAddress GetMacAddress()
  113. {
  114. NetworkInterface ni = GetNetworkInterface();
  115. if (ni == null)
  116. return null;
  117. return ni.GetPhysicalAddress();
  118. }
  119. #endif
  120. /// <summary>
  121. /// Create a hex string from an Int64 value
  122. /// </summary>
  123. public static string ToHexString(long data)
  124. {
  125. return ToHexString(BitConverter.GetBytes(data));
  126. }
  127. /// <summary>
  128. /// Create a hex string from an array of bytes
  129. /// </summary>
  130. public static string ToHexString(byte[] data)
  131. {
  132. char[] c = new char[data.Length * 2];
  133. byte b;
  134. for (int i = 0; i < data.Length; ++i)
  135. {
  136. b = ((byte)(data[i] >> 4));
  137. c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
  138. b = ((byte)(data[i] & 0xF));
  139. c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
  140. }
  141. return new string(c);
  142. }
  143. /// <summary>
  144. /// Gets my local IP address (not necessarily external) and subnet mask
  145. /// </summary>
  146. public static IPAddress GetMyAddress(out IPAddress mask)
  147. {
  148. #if IS_FULL_NET_AVAILABLE
  149. NetworkInterface ni = GetNetworkInterface();
  150. if (ni == null)
  151. {
  152. mask = null;
  153. return null;
  154. }
  155. IPInterfaceProperties properties = ni.GetIPProperties();
  156. foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses)
  157. {
  158. if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork)
  159. {
  160. mask = unicastAddress.IPv4Mask;
  161. return unicastAddress.Address;
  162. }
  163. }
  164. #endif
  165. mask = null;
  166. return null;
  167. }
  168. /// <summary>
  169. /// Returns true if the IPEndPoint supplied is on the same subnet as this host
  170. /// </summary>
  171. public static bool IsLocal(IPEndPoint endpoint)
  172. {
  173. if (endpoint == null)
  174. return false;
  175. return IsLocal(endpoint.Address);
  176. }
  177. /// <summary>
  178. /// Returns true if the IPAddress supplied is on the same subnet as this host
  179. /// </summary>
  180. public static bool IsLocal(IPAddress remote)
  181. {
  182. IPAddress mask;
  183. IPAddress local = GetMyAddress(out mask);
  184. if (mask == null)
  185. return false;
  186. uint maskBits = BitConverter.ToUInt32(mask.GetAddressBytes(), 0);
  187. uint remoteBits = BitConverter.ToUInt32(remote.GetAddressBytes(), 0);
  188. uint localBits = BitConverter.ToUInt32(local.GetAddressBytes(), 0);
  189. // compare network portions
  190. return ((remoteBits & maskBits) == (localBits & maskBits));
  191. }
  192. /// <summary>
  193. /// Returns how many bits are necessary to hold a certain number
  194. /// </summary>
  195. [CLSCompliant(false)]
  196. public static int BitsToHoldUInt(uint value)
  197. {
  198. int bits = 1;
  199. while ((value >>= 1) != 0)
  200. bits++;
  201. return bits;
  202. }
  203. /// <summary>
  204. /// Returns how many bytes are required to hold a certain number of bits
  205. /// </summary>
  206. public static int BytesToHoldBits(int numBits)
  207. {
  208. return (numBits + 7) / 8;
  209. }
  210. internal static UInt32 SwapByteOrder(UInt32 value)
  211. {
  212. return
  213. ((value & 0xff000000) >> 24) |
  214. ((value & 0x00ff0000) >> 8) |
  215. ((value & 0x0000ff00) << 8) |
  216. ((value & 0x000000ff) << 24);
  217. }
  218. internal static UInt64 SwapByteOrder(UInt64 value)
  219. {
  220. return
  221. ((value & 0xff00000000000000L) >> 56) |
  222. ((value & 0x00ff000000000000L) >> 40) |
  223. ((value & 0x0000ff0000000000L) >> 24) |
  224. ((value & 0x000000ff00000000L) >> 8) |
  225. ((value & 0x00000000ff000000L) << 8) |
  226. ((value & 0x0000000000ff0000L) << 24) |
  227. ((value & 0x000000000000ff00L) << 40) |
  228. ((value & 0x00000000000000ffL) << 56);
  229. }
  230. internal static bool CompareElements(byte[] one, byte[] two)
  231. {
  232. if (one.Length != two.Length)
  233. return false;
  234. for (int i = 0; i < one.Length; i++)
  235. if (one[i] != two[i])
  236. return false;
  237. return true;
  238. }
  239. /// <summary>
  240. /// Convert a hexadecimal string to a byte array
  241. /// </summary>
  242. public static byte[] ToByteArray(String hexString)
  243. {
  244. byte[] retval = new byte[hexString.Length / 2];
  245. for (int i = 0; i < hexString.Length; i += 2)
  246. retval[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
  247. return retval;
  248. }
  249. /// <summary>
  250. /// Converts a number of bytes to a shorter, more readable string representation
  251. /// </summary>
  252. public static string ToHumanReadable(long bytes)
  253. {
  254. if (bytes < 4000) // 1-4 kb is printed in bytes
  255. return bytes + " bytes";
  256. if (bytes < 1000 * 1000) // 4-999 kb is printed in kb
  257. return Math.Round(((double)bytes / 1000.0), 2) + " kilobytes";
  258. return Math.Round(((double)bytes / (1000.0 * 1000.0)), 2) + " megabytes"; // else megabytes
  259. }
  260. internal static int RelativeSequenceNumber(int nr, int expected)
  261. {
  262. int retval = ((nr + NetConstants.NumSequenceNumbers) - expected) % NetConstants.NumSequenceNumbers;
  263. if (retval > (NetConstants.NumSequenceNumbers / 2))
  264. retval -= NetConstants.NumSequenceNumbers;
  265. return retval;
  266. }
  267. /// <summary>
  268. /// Gets the window size used internally in the library for a certain delivery method
  269. /// </summary>
  270. public static int GetWindowSize(NetDeliveryMethod method)
  271. {
  272. switch (method)
  273. {
  274. case NetDeliveryMethod.Unknown:
  275. return 0;
  276. case NetDeliveryMethod.Unreliable:
  277. case NetDeliveryMethod.UnreliableSequenced:
  278. return NetConstants.UnreliableWindowSize;
  279. case NetDeliveryMethod.ReliableOrdered:
  280. return NetConstants.ReliableOrderedWindowSize;
  281. case NetDeliveryMethod.ReliableSequenced:
  282. case NetDeliveryMethod.ReliableUnordered:
  283. default:
  284. return NetConstants.DefaultWindowSize;
  285. }
  286. }
  287. // shell sort
  288. internal static void SortMembersList(System.Reflection.MemberInfo[] list)
  289. {
  290. int h;
  291. int j;
  292. System.Reflection.MemberInfo tmp;
  293. h = 1;
  294. while (h * 3 + 1 <= list.Length)
  295. h = 3 * h + 1;
  296. while (h > 0)
  297. {
  298. for (int i = h - 1; i < list.Length; i++)
  299. {
  300. tmp = list[i];
  301. j = i;
  302. while (true)
  303. {
  304. if (j >= h)
  305. {
  306. if (string.Compare(list[j - h].Name, tmp.Name, StringComparison.InvariantCulture) > 0)
  307. {
  308. list[j] = list[j - h];
  309. j -= h;
  310. }
  311. else
  312. break;
  313. }
  314. else
  315. break;
  316. }
  317. list[j] = tmp;
  318. }
  319. h /= 3;
  320. }
  321. }
  322. internal static NetDeliveryMethod GetDeliveryMethod(NetMessageType mtp)
  323. {
  324. if (mtp >= NetMessageType.UserReliableOrdered1)
  325. return NetDeliveryMethod.ReliableOrdered;
  326. else if (mtp >= NetMessageType.UserReliableSequenced1)
  327. return NetDeliveryMethod.ReliableSequenced;
  328. else if (mtp >= NetMessageType.UserReliableUnordered)
  329. return NetDeliveryMethod.ReliableUnordered;
  330. else if (mtp >= NetMessageType.UserSequenced1)
  331. return NetDeliveryMethod.UnreliableSequenced;
  332. return NetDeliveryMethod.Unreliable;
  333. }
  334. }
  335. }