//
// System.Net.IPAddress.cs
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
// Lawrence Pit (loz@cable.a2000.nl)
//
// (C) Ximian, Inc. http://www.ximian.com
//
//
// Note: the address is stored in host order
using System;
using System.Globalization;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace System.Net {
///
/// Encapsulates an IP Address.
///
[Serializable]
public class IPAddress {
// Don't change the name of this field without also
// changing socket-io.c in the runtime
private long address;
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");
private static short SwapShort (short number)
{
return (short) ( ((number >> 8) & 0xFF) + ((number << 8) & 0xFF00) );
}
private static int SwapInt (int number)
{
byte b0 = (byte) ((number >> 24) & 0xFF);
byte b1 = (byte) ((number >> 16) & 0xFF);
byte b2 = (byte) ((number >> 8) & 0xFF);
byte b3 = (byte) (number & 0xFF);
return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24);
}
private static long SwapLong (long number)
{
byte b0 = (byte) ((number >> 56) & 0xFF);
byte b1 = (byte) ((number >> 48) & 0xFF);
byte b2 = (byte) ((number >> 40) & 0xFF);
byte b3 = (byte) ((number >> 32) & 0xFF);
byte b4 = (byte) ((number >> 24) & 0xFF);
byte b5 = (byte) ((number >> 16) & 0xFF);
byte b6 = (byte) ((number >> 8) & 0xFF);
byte b7 = (byte) (number & 0xFF);
return (long) b0 + ((long) b1 << 8) + ((long) b2 << 16) + ((long) b3 << 24) + ((long) b4 << 32) + ((long) b5 << 40) + ((long) b6 << 48) + ((long) b7 << 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);
}
///
/// Constructor from a 32-bit constant with its bytes
/// in network order.
///
public IPAddress (long addr)
{
Address = addr;
}
public static IPAddress Parse (string ip)
{
if (ip == null)
throw new ArgumentNullException ("null ip string");
if (ip.Length == 0 || ip [0] == ' ')
return new IPAddress (0);
int pos = ip.IndexOf (' ');
if (pos != -1)
ip = ip.Substring (0, pos);
else if (ip [ip.Length - 1] == '.')
throw new FormatException ("An invalid IP address was specified");
string [] ips = ip.Split (new char [] {'.'});
if (ips.Length > 4)
throw new FormatException ("An invalid IP address was specified");
// Make the number in network order
try {
long a = 0;
byte val = 0;
for (int i = 0; i < ips.Length; i++) {
string subnet = ips [i];
if ((3 <= subnet.Length && subnet.Length <= 4) &&
(subnet [0] == '0') &&
(subnet [1] == 'x' || subnet [2] == 'X')) {
if (subnet.Length == 3)
val = (byte) Uri.FromHex (subnet [2]);
else
val = (byte) ((Uri.FromHex (subnet [2]) << 4) | Uri.FromHex (subnet [3]));
} else if (subnet.Length == 0)
val = 0;
else
val = Byte.Parse (subnet, NumberStyles.None);
if (ips.Length < 4 && i == (ips.Length - 1))
i = 3;
a |= (long) val << (i << 3);
}
return (new IPAddress (a));
} catch (Exception) {
throw new FormatException ("An invalid IP address was specified");
}
}
public long Address {
get {
return address;
}
set {
/* no need to do this test, ms.net accepts any value.
if (value < 0 || value > 0x00000000FFFFFFFF)
throw new ArgumentOutOfRangeException (
"the address must be between 0 and 0xFFFFFFFF");
*/
address = value;
}
}
public AddressFamily AddressFamily {
get {
return(AddressFamily.InterNetwork);
}
}
///
/// Used to tell whether an address is a loopback.
/// All IP addresses of the form 127.X.Y.Z, where X, Y, and Z are in
/// the range 0-255, are loopback addresses.
///
/// Address to compare
///
public static bool IsLoopback (IPAddress addr)
{
return (addr.address & 0xFF) == 127;
}
///
/// Overrides System.Object.ToString to return
/// this object rendered in a quad-dotted notation
///
public override string ToString ()
{
return ToString (address);
}
///
/// Returns this object rendered in a quad-dotted notation
///
static string ToString (long addr)
{
// addr is in network order
return (addr & 0xff).ToString () + "." +
((addr >> 8) & 0xff).ToString () + "." +
((addr >> 16) & 0xff).ToString () + "." +
((addr >> 24) & 0xff).ToString ();
}
///
/// Whether both objects are equal.
///
public override bool Equals (object other)
{
if (other is System.Net.IPAddress){
return Address == ((System.Net.IPAddress) other).Address;
}
return false;
}
public override int GetHashCode ()
{
return (int)Address;
}
}
}