context: //
  // System.Net.IPAddress.cs
  //
  // Author:
  //   Miguel de Icaza (miguel@ximian.com)
  //   Lawrence Pit (loz@cable.a2000.nl)
  //
  // (C) Ximian, Inc.  http://www.ximian.com
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.Globalization;
  using System.Net.Sockets;
  using System.Runtime.InteropServices;
  
  namespace System.Net {
  
  	/// <remarks>
  	///   Encapsulates an IP Address.
  	/// </remarks>
  	[Serializable]
  	public class IPAddress {
  		// Don't change the name of this field without also
  		// changing socket-io.c in the runtime
  		// The IP address is stored in little-endian order inside the int, 
  		// meaning the lower order bytes contain the netid
  		private long m_Address;
  		private AddressFamily m_Family;
  		private ushort[] m_Numbers;	/// ip6 Stored in network order (as ip4)
  		private long m_ScopeId;
  
  		public static readonly IPAddress Any = new IPAddress(0);
  		public static readonly IPAddress Broadcast = IPAddress.Parse ("255.255.255.255");
  		public static readonly IPAddress Loopback = IPAddress.Parse ("127.0.0.1");
  		public static readonly IPAddress None = IPAddress.Parse ("255.255.255.255");
  		public static readonly IPAddress IPv6Any = IPAddress.ParseIPV6 ("::");
  		public static readonly IPAddress IPv6Loopback = IPAddress.ParseIPV6 ("::1");
  		public static readonly IPAddress IPv6None = IPAddress.ParseIPV6 ("::");
  
  		private static short SwapShort (short number)
  		{
  			return (short) ( ((number >> 8) & 0xFF) | ((number << 8) & 0xFF00) );
  		}
  
  		private static int SwapInt (int number)
  		{
  			return (((number >> 24) & 0xFF)
  				  | ((number >> 08) & 0xFF00)
  				  | ((number << 08) & 0xFF0000)
  				  | ((number << 24)));
  		}
  
  		private static long SwapLong(long number)
  		{
  			return (((number >> 56) & 0xFF)
  				  | ((number >> 40) & 0xFF00)
  				  | ((number >> 24) & 0xFF0000)
  				  | ((number >> 08) & 0xFF000000)
  				  | ((number << 08) & 0xFF00000000)
  				  | ((number << 24) & 0xFF0000000000)
  				  | ((number << 40) & 0xFF000000000000)
  				  | ((number << 56)));
  		}
  
  		public static short HostToNetworkOrder(short host) {
  			if (!BitConverter.IsLittleEndian)
  				return(host);
  
  			return SwapShort (host);
  		}
  
  		public static int HostToNetworkOrder(int host) {
  			if (!BitConverter.IsLittleEndian)
  				return(host);
  
  			return SwapInt (host);
  		}
  		
  		public static long HostToNetworkOrder(long host) {
  			if (!BitConverter.IsLittleEndian)
  				return(host);
  
  			return SwapLong (host);
  		}
  
  		public static short NetworkToHostOrder(short network) {
  			if (!BitConverter.IsLittleEndian)
  				return(network);
  
  			return SwapShort (network);
  		}
  
  		public static int NetworkToHostOrder(int network) {
  			if (!BitConverter.IsLittleEndian)
  				return(network);
  
  			return SwapInt (network);
  		}
  
  		public static long NetworkToHostOrder(long network) {
  			if (!BitConverter.IsLittleEndian)
  				return(network);
  
  			return SwapLong (network);
  		}
  		
  		/// <summary>
  		///   Constructor from a 32-bit constant with the address bytes in
  		///   little-endian order (the lower order bytes contain the netid)
  		/// </summary>
  		public IPAddress (long newAddress)
  		{
  			m_Address = newAddress;
  			m_Family = AddressFamily.InterNetwork;
  		}
  
  		public IPAddress (byte[] address)
  		{
  			if (address == null)
  				throw new ArgumentNullException ("address");
  
  			int len = address.Length;
  
  			if (len != 16 && len != 4)
  				throw new ArgumentException ("An invalid IP address was specified.",
  					"address");
  
  			if (len == 16) {
  				m_Numbers = new ushort [8];
  				Buffer.BlockCopy(address, 0, m_Numbers, 0, 16);
  				m_Family = AddressFamily.InterNetworkV6;
  				m_ScopeId = 0;
  			} else {
  				m_Address = ((uint) address [3] << 24) + (address [2] << 16) +
  					(address [1] << 8) + address [0];
  				m_Family = AddressFamily.InterNetwork;
  			}
  		}
  
  		public IPAddress(byte[] address, long scopeid)
  		{
  			if (address == null)
  				throw new ArgumentNullException ("address");
  
  			if (address.Length != 16)
  				throw new ArgumentException ("An invalid IP address was specified.",
  					"address");
  
  			m_Numbers = new ushort [8];
  			Buffer.BlockCopy(address, 0, m_Numbers, 0, 16);
  			m_Family = AddressFamily.InterNetworkV6;
  			m_ScopeId = scopeid;
  		}
  
  		internal IPAddress(ushort[] address, long scopeId)
  		{
  			m_Numbers = address;
  
  			for(int i=0; i<8; i++)
  				m_Numbers[i] = (ushort)HostToNetworkOrder((short)m_Numbers[i]);
  
  			m_Family = AddressFamily.InterNetworkV6;
  			m_ScopeId = scopeId;
  		}
  
  		public static IPAddress Parse (string ipString)
  		{
  			IPAddress ret;
  			if (TryParse (ipString, out ret))
  				return ret;
  			throw new FormatException ("An invalid IP address was specified.");
  		}
  
  		public static bool TryParse (string ipString, out IPAddress address)
  		{
  			if (ipString == null)
  				throw new ArgumentNullException ("ipString");
  
  			if ((address = ParseIPV4 (ipString)) == null)
  				if ((address = ParseIPV6 (ipString)) == null)
  					return false;
  			return true;
  		}
  
  		private static IPAddress ParseIPV4 (string ip)
  		{
  
  			int pos = ip.IndexOf (' ');
  			if (pos != -1) {
  				string [] nets = ip.Substring (pos + 1).Split (new char [] {'.'});
  				if (nets.Length > 0) {
  					string lastNet = nets [nets.Length - 1];
  					if (lastNet.Length == 0)
  						return null;
  					foreach (char c in lastNet)
  						if (!Uri.IsHexDigit (c))
  							return null;
  				}
  
gt: 				ip = ip.Substring (0, pos);