//
// System.Net.IPAddress.cs
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
//
// (C) Ximian, Inc. http://www.ximian.com
//
//
// Note: the address is stored in host order
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System;
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 b0 + (b1 << 8) + (b2 << 16) + (b3 << 24) + (b4 << 32) + (b5 << 40) + (b6 << 48) + (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");
int pos = 0;
int ndots = 0;
char current;
bool prevDigit = false;
while (pos < ip.Length) {
current = ip [pos++];
if (Char.IsDigit (current))
prevDigit = true;
else
if (current == '.') {
// No more than 3 dots. Doesn't allow ending with a dot.
if (++ndots > 3 || pos == ip.Length || prevDigit == false)
throw new FormatException ("the string is not a valid ip");
prevDigit = false;
}
else if (!Char.IsDigit (current)) {
if (!Char.IsWhiteSpace (current))
throw new FormatException ("the string is not a valid ip");
// The same as MS does
if (pos == 1)
return new IPAddress (0);
break;
}
}
if (ndots != 3)
throw new FormatException ("the string is not a valid ip");
int a = 0;
string [] ips = ip.Split (new char [] {'.'});
// Make the number in network order
for (int i = ips.Length - 1; i >= 0; i--)
a = (a << 8) | (Byte.Parse(ips [i]));
return (new IPAddress (a));
}
public long Address {
get {
return address;
}
set {
// FIXME: Temporarily disabled as a workaround for bug #23547
/*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 (NetworkToHostOrder (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;
}
}
}