PageRenderTime 45ms CodeModel.GetById 25ms app.highlight 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ThirdParty/Lidgren.Network/NetUtility.cs

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