2002-04-15 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System / System.Net / IPAddress.cs
1 //
2 // System.Net.IPAddress.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System.Net.Sockets;
11 using System.Runtime.InteropServices;
12
13 using System;
14
15 namespace System.Net {
16
17         /// <remarks>
18         ///   Encapsulates an IP Address.
19         /// </remarks>
20         [Serializable]
21         public class IPAddress {
22                 // Don't change the name of this field without also
23                 // changing socket-io.c in the runtime
24                 // This will stored in network order
25                 private long address;
26
27                 public static readonly IPAddress Any=new IPAddress(0);
28                 public static readonly IPAddress Broadcast=new IPAddress(0xffffffff);
29                 public static readonly IPAddress Loopback=new IPAddress(0x7f000001);
30                 public static readonly IPAddress None=new IPAddress(0xffffffff);
31
32                 private static short SwapShort (short number)
33                 {
34                         return (short) ( ((number >> 8) & 0xFF) + ((number << 8) & 0xFF00) );
35                 }
36
37                 private static int SwapInt (int number)
38                 {
39                         byte b0 = (byte) ((number >> 24) & 0xFF);
40                         byte b1 = (byte) ((number >> 16) & 0xFF);
41                         byte b2 = (byte) ((number >> 8) & 0xFF);
42                         byte b3 = (byte) (number & 0xFF);
43                         return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24);
44                 }
45
46                 private static long SwapLong (long number)
47                 {
48                         byte b0 = (byte) ((number >> 56) & 0xFF);
49                         byte b1 = (byte) ((number >> 48) & 0xFF);
50                         byte b2 = (byte) ((number >> 40) & 0xFF);
51                         byte b3 = (byte) ((number >> 32) & 0xFF);
52                         byte b4 = (byte) ((number >> 24) & 0xFF);
53                         byte b5 = (byte) ((number >> 16) & 0xFF);
54                         byte b6 = (byte) ((number >> 8) & 0xFF);
55                         byte b7 = (byte) (number & 0xFF);
56                         return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24) + (b4 << 32) + (b5 << 40) + (b6 << 48) + (b7 << 56);
57                 }
58
59                 public static short HostToNetworkOrder(short host) {
60                         if (!BitConverter.IsLittleEndian)
61                                 return(host);
62
63                         return SwapShort (host);
64                 }
65
66                 public static int HostToNetworkOrder(int host) {
67                         if (!BitConverter.IsLittleEndian)
68                                 return(host);
69
70                         return SwapInt (host);
71                 }
72                 
73                 public static long HostToNetworkOrder(long host) {
74                         if (!BitConverter.IsLittleEndian)
75                                 return(host);
76
77                         return SwapLong (host);
78                 }
79
80                 public static short NetworkToHostOrder(short network) {
81                         if (!BitConverter.IsLittleEndian)
82                                 return(network);
83
84                         return SwapShort (network);
85                 }
86
87                 public static int NetworkToHostOrder(int network) {
88                         if (!BitConverter.IsLittleEndian)
89                                 return(network);
90
91                         return SwapInt (network);
92                 }
93
94                 public static long NetworkToHostOrder(long network) {
95                         if (!BitConverter.IsLittleEndian)
96                                 return(network);
97
98                         return SwapLong (network);
99                 }
100                 
101                 /// <summary>
102                 ///   Constructor from a 32-bit constant with its bytes 
103                 ///   in network order.
104                 /// </summary>
105                 public IPAddress (long addr)
106                 {
107                         Address = addr;
108                 }
109
110                 public static IPAddress Parse(string ip)
111                 {
112                         if(ip == null)
113                                 throw new ArgumentNullException("null ip string");
114
115                         int pos = 0;
116                         int ndots = 0;
117                         char current;
118                         bool prevDigit = false;
119
120                         while (pos < ip.Length) {
121                                 current  = ip [pos++];
122                                 if (Char.IsDigit (current))
123                                         prevDigit = true;
124                                 else
125                                 if (current == '.') {
126                                         // No more than 3 dots. Doesn't allow ending with a dot.
127                                         if (++ndots > 3 || pos == ip.Length || prevDigit == false)
128                                                 throw new FormatException ("the string is not a valid ip");
129
130                                         prevDigit = false;
131                                 }
132                                 else if (!Char.IsDigit (current)) {
133                                         if (!Char.IsWhiteSpace (current))
134                                                 throw new FormatException ("the string is not a valid ip");
135
136                                         // The same as MS does
137                                         if (pos == 1) 
138                                                 return new IPAddress (0);
139
140                                         break;
141                                 }
142                         }
143
144                         if (ndots != 3)
145                                 throw new FormatException ("the string is not a valid ip");
146
147
148                         long a = 0;
149                         string [] ips = ip.Split (new char [] {'.'});
150                         // Make the number in network order
151                         for (int i = ips.Length - 1; i >= 0; i--)
152                                 a = (a << 8) |  (Byte.Parse(ips [i]));
153
154                         return (new IPAddress (a));
155                 }
156                 
157                 public long Address {
158                         get {
159                                 return address;
160                         }
161                         set {
162                         if (value < 0 || value > 0x00000000FFFFFFFF)
163                                 throw new ArgumentOutOfRangeException (
164                                         "the address must be between 0 and 0xFFFFFFFF");
165
166                                 address = value;
167                         }
168                 }
169
170                 public AddressFamily AddressFamily {
171                         get {
172                                 return(AddressFamily.InterNetwork);
173                         }
174                 }
175                 
176                 
177                 /// <summary>
178                 ///   Used to tell whether an address is a loopback.
179                 ///   All IP addresses of the form 127.X.Y.Z, where X, Y, and Z are in 
180                 ///   the range 0-255, are loopback addresses.
181                 /// </summary>
182                 /// <param name="addr">Address to compare</param>
183                 /// <returns></returns>
184                 public static bool IsLoopback (IPAddress addr)
185                 {
186                         return (addr.address & 0xFF) == 127;
187                 }
188
189                 /// <summary>
190                 ///   Overrides System.Object.ToString to return
191                 ///   this object rendered in a quad-dotted notation
192                 /// </summary>
193                 public override string ToString ()
194                 {
195                         return ToString (address);
196                 }
197
198                 /// <summary>
199                 ///   Returns this object rendered in a quad-dotted notation
200                 /// </summary>
201                 static string ToString (long addr)
202                 {
203                         // addr is in network order
204                         return  (addr & 0xff).ToString () + "." +
205                                 ((addr >> 8) & 0xff).ToString () + "." +
206                                 ((addr >> 16) & 0xff).ToString () + "." +
207                                 ((addr >> 24) & 0xff).ToString ();
208                 }
209
210                 /// <returns>
211                 ///   Whether both objects are equal.
212                 /// </returns>
213                 public override bool Equals (object other)
214                 {
215                         if (other is System.Net.IPAddress){
216                                 return Address == ((System.Net.IPAddress) other).Address;
217                         }
218                         return false;
219                 }
220
221                 public override int GetHashCode ()
222                 {
223                         return (int)Address;
224                 }
225         }
226 }