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