New tests.
[mono.git] / mcs / class / System / System.Net / Dns.cs
1 // System.Net.Dns.cs
2 //
3 // Author: Mads Pultz (mpultz@diku.dk)
4 // Author: Lawrence Pit (loz@cable.a2000.nl)
5 //
6 // (C) Mads Pultz, 2001
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Net.Sockets;
31 using System.Text;
32 using System.Collections;
33 using System.Threading;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.Remoting.Messaging;
36
37 namespace System.Net {
38 #if NET_2_0
39         public static class Dns {
40 #else
41         public sealed class Dns {
42
43                 private Dns () {}
44 #endif
45
46                 static Dns ()
47                 {
48                         System.Net.Sockets.Socket.CheckProtocolSupport();
49                 }
50
51 #if !MOONLIGHT // global remove of async methods
52
53                 private delegate IPHostEntry GetHostByNameCallback (string hostName);
54                 private delegate IPHostEntry ResolveCallback (string hostName);
55 #if NET_2_0
56                 private delegate IPHostEntry GetHostEntryNameCallback (string hostName);
57                 private delegate IPHostEntry GetHostEntryIPCallback (IPAddress hostAddress);
58                 private delegate IPAddress [] GetHostAddressesCallback (string hostName);
59 #endif
60
61 #if NET_2_0
62                 [Obsolete ("Use BeginGetHostEntry instead")]
63 #endif
64                 public static IAsyncResult BeginGetHostByName (string hostName,
65                         AsyncCallback requestCallback, object stateObject)
66                 {
67                         if (hostName == null)
68                                 throw new ArgumentNullException ("hostName");
69
70                         GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName);
71                         return c.BeginInvoke (hostName, requestCallback, stateObject);
72                 }
73
74 #if NET_2_0
75                 [Obsolete ("Use BeginGetHostEntry instead")]
76 #endif
77                 public static IAsyncResult BeginResolve (string hostName,
78                         AsyncCallback requestCallback, object stateObject)
79                 {
80                         if (hostName == null)
81                                 throw new ArgumentNullException ("hostName");
82
83                         ResolveCallback c = new ResolveCallback (Resolve);
84                         return c.BeginInvoke (hostName, requestCallback, stateObject);
85                 }
86
87 #if NET_2_0
88                 public static IAsyncResult BeginGetHostAddresses (string hostNameOrAddress,
89                         AsyncCallback requestCallback, object stateObject)
90                 {
91                         if (hostNameOrAddress == null)
92                                 throw new ArgumentNullException ("hostName");
93                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
94                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
95                                         "and ::0 (IPv6) are unspecified addresses. You " +
96                                         "cannot use them as target address.",
97                                         "hostNameOrAddress");
98
99                         GetHostAddressesCallback c = new GetHostAddressesCallback (GetHostAddresses);
100                         return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject);
101                 }
102
103                 public static IAsyncResult BeginGetHostEntry (string hostNameOrAddress,
104                         AsyncCallback requestCallback, object stateObject)
105                 {
106                         if (hostNameOrAddress == null)
107                                 throw new ArgumentNullException ("hostName");
108                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
109                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
110                                         "and ::0 (IPv6) are unspecified addresses. You " +
111                                         "cannot use them as target address.",
112                                         "hostNameOrAddress");
113
114                         GetHostEntryNameCallback c = new GetHostEntryNameCallback (GetHostEntry);
115                         return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject);
116                 }
117
118                 public static IAsyncResult BeginGetHostEntry (IPAddress address,
119                         AsyncCallback requestCallback, object stateObject)
120                 {
121                         if (address == null)
122                                 throw new ArgumentNullException ("address");
123
124                         GetHostEntryIPCallback c = new GetHostEntryIPCallback (GetHostEntry);
125                         return c.BeginInvoke (address, requestCallback, stateObject);
126                 }
127 #endif
128
129 #if NET_2_0
130                 [Obsolete ("Use EndGetHostEntry instead")]
131 #endif
132                 public static IPHostEntry EndGetHostByName (IAsyncResult asyncResult) 
133                 {
134                         if (asyncResult == null)
135                                 throw new ArgumentNullException ("asyncResult");
136
137                         AsyncResult async = (AsyncResult) asyncResult;
138                         GetHostByNameCallback cb = (GetHostByNameCallback) async.AsyncDelegate;
139                         return cb.EndInvoke(asyncResult);
140                 }
141
142 #if NET_2_0
143                 [Obsolete ("Use EndGetHostEntry instead")]
144 #endif
145                 public static IPHostEntry EndResolve (IAsyncResult asyncResult) 
146                 {
147                         if (asyncResult == null)
148                                 throw new ArgumentNullException ("asyncResult");
149                         AsyncResult async = (AsyncResult) asyncResult;
150                         ResolveCallback cb = (ResolveCallback) async.AsyncDelegate;
151                         return cb.EndInvoke(asyncResult);
152                 }
153
154 #if NET_2_0
155
156                 public static IPAddress [] EndGetHostAddresses (IAsyncResult asyncResult) 
157                 {
158                         if (asyncResult == null)
159                                 throw new ArgumentNullException ("asyncResult");
160
161                         AsyncResult async = (AsyncResult) asyncResult;
162                         GetHostAddressesCallback cb = (GetHostAddressesCallback) async.AsyncDelegate;
163                         return cb.EndInvoke(asyncResult);
164                 }
165
166                 public static IPHostEntry EndGetHostEntry (IAsyncResult asyncResult) 
167                 {
168                         if (asyncResult == null)
169                                 throw new ArgumentNullException ("asyncResult");
170                         AsyncResult async = (AsyncResult) asyncResult;
171 #if NET_2_0
172                         if (async.AsyncDelegate is GetHostEntryIPCallback)
173                                 return ((GetHostEntryIPCallback) async.AsyncDelegate).EndInvoke (asyncResult);
174 #endif
175                         GetHostEntryNameCallback cb = (GetHostEntryNameCallback) async.AsyncDelegate;
176                         return cb.EndInvoke(asyncResult);
177                 }
178 #endif
179                 
180 #endif // !MOONLIGHT: global remove of async methods
181
182 #if !TARGET_JVM
183                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
184                 private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list);
185
186                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
187                 private extern static bool GetHostByAddr_internal(string addr, out string h_name, out string[] h_aliases, out string[] h_addr_list);
188
189                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
190                 private extern static bool GetHostName_internal(out string h_name);
191 #endif  
192
193                 private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist) 
194                 {
195                         IPHostEntry he = new IPHostEntry();
196                         ArrayList addrlist = new ArrayList();
197
198                         he.HostName = h_name;
199                         he.Aliases = h_aliases;
200                         for(int i=0; i<h_addrlist.Length; i++) {
201                                 try {
202                                         IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
203
204                                         if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
205                                             (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
206                                                 addrlist.Add(newAddress);
207                                 } catch (ArgumentNullException) {
208                                         /* Ignore this, as the
209                                          * internal call might have
210                                          * left some blank entries at
211                                          * the end of the array
212                                          */
213                                 }
214                         }
215
216                         if(addrlist.Count == 0)
217                                 throw new SocketException(11001);
218
219                         he.AddressList = addrlist.ToArray(typeof(IPAddress)) as IPAddress[];
220                         return he;
221                 }
222
223 #if NET_2_0
224                 [Obsolete ("Use GetHostEntry instead")]
225 #endif
226                 public static IPHostEntry GetHostByAddress(IPAddress address)
227                 {
228                         if (address == null)
229                                 throw new ArgumentNullException ("address");
230
231                         return GetHostByAddressFromString (address.ToString (), false);
232                 }
233
234 #if NET_2_0
235                 [Obsolete ("Use GetHostEntry instead")]
236 #endif
237                 public static IPHostEntry GetHostByAddress(string address)
238                 {
239                         if (address == null)
240                                 throw new ArgumentNullException ("address");
241
242                         return GetHostByAddressFromString (address, true);
243                 }
244
245                 static IPHostEntry GetHostByAddressFromString (string address, bool parse)
246                 {
247                         // Undocumented MS behavior: when called with IF_ANY,
248                         // this should return the local host
249                         if (address.Equals ("0.0.0.0")) {
250                                 address = "127.0.0.1";
251                                 parse = false;
252                         }
253
254                         // Must check the IP format, might send an exception if invalid string.
255                         if (parse)
256                                 IPAddress.Parse (address);
257
258                         string h_name;
259                         string[] h_aliases, h_addrlist;
260 #if TARGET_JVM
261                         h_name = null;
262                         h_aliases = null;
263                         h_addrlist = null;
264                         try {
265                                 java.net.InetAddress[] iaArr = 
266                                         java.net.InetAddress.getAllByName(address);
267                                 if (iaArr != null && iaArr.Length > 0)
268                                     h_name = iaArr[0].getHostName();
269                                 if (iaArr != null && iaArr.Length > 0)
270                                 {
271                                     h_addrlist = new String[iaArr.Length];
272                                     for (int i = 0; i < h_addrlist.Length; i++)
273                                         h_addrlist[i] = iaArr[i].getHostAddress();
274                                 }
275                         } catch (java.net.UnknownHostException jUHE) {
276                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
277                         }
278 #else
279                         bool ret = GetHostByAddr_internal(address, out h_name, out h_aliases, out h_addrlist);
280                         if (!ret)
281                                 throw new SocketException(11001);
282 #endif
283                         return (hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist));
284                         
285                 }
286
287 #if NET_2_0
288                 public
289 #else
290                 internal
291 #endif
292                 static IPHostEntry GetHostEntry (string hostNameOrAddress)
293                 {
294                         if (hostNameOrAddress == null)
295                                 throw new ArgumentNullException ("hostNameOrAddress");
296                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
297                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
298                                         "and ::0 (IPv6) are unspecified addresses. You " +
299                                         "cannot use them as target address.",
300                                         "hostNameOrAddress");
301
302                         IPAddress addr;
303                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
304                                 return GetHostEntry (addr);
305
306                         return GetHostByName (hostNameOrAddress);
307                 }
308
309 #if NET_2_0
310                 public
311 #else
312                 internal
313 #endif
314                 static IPHostEntry GetHostEntry (IPAddress address)
315                 {
316                         if (address == null)
317                                 throw new ArgumentNullException ("address");
318
319                         return GetHostByAddressFromString (address.ToString (), false);
320                 }
321
322 #if NET_2_0
323                 public
324 #else
325                 internal
326 #endif
327                 static IPAddress [] GetHostAddresses (string hostNameOrAddress)
328                 {
329                         if (hostNameOrAddress == null)
330                                 throw new ArgumentNullException ("hostNameOrAddress");
331
332                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
333                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
334                                         "and ::0 (IPv6) are unspecified addresses. You " +
335                                         "cannot use them as target address.",
336                                         "hostNameOrAddress");
337
338                         IPAddress addr;
339                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
340                                 return new IPAddress[1] { addr };
341
342                         return GetHostEntry (hostNameOrAddress).AddressList;
343                 }
344
345 #if NET_2_0
346                 [Obsolete ("Use GetHostEntry instead")]
347 #endif
348                 public static IPHostEntry GetHostByName (string hostName)
349                 {
350                         if (hostName == null)
351                                 throw new ArgumentNullException ("hostName");
352 #if TARGET_JVM
353                         if (hostName.Length == 0)
354                                 hostName = "localhost";
355                         try {
356                                 java.net.InetAddress[] iaArr = java.net.InetAddress.getAllByName(hostName);
357                                 IPHostEntry host = new IPHostEntry();
358                                 if (iaArr != null && iaArr.Length > 0)
359                                 {
360                                         host.HostName = iaArr[0].getHostName();
361                                         IPAddress[] ipArr = new IPAddress[iaArr.Length];
362                                         for (int i = 0; i < iaArr.Length; i++)
363                                                 ipArr[i] = IPAddress.Parse(iaArr[i].getHostAddress());
364
365                                         host.AddressList = ipArr;
366                                 }
367                                 return host;
368                         } catch (java.net.UnknownHostException jUHE) {
369                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
370                         }
371 #else
372                         string h_name;
373                         string[] h_aliases, h_addrlist;
374
375                         bool ret = GetHostByName_internal(hostName, out h_name, out h_aliases, out h_addrlist);
376                         if (ret == false)
377                                 throw new SocketException(11001);
378
379                         return(hostent_to_IPHostEntry(h_name, h_aliases, h_addrlist));
380 #endif
381                 }
382
383                 public static string GetHostName ()
384                 {
385 #if TARGET_JVM
386                         return java.net.InetAddress.getLocalHost ().getHostName ();
387 #else
388                         string hostName;
389
390                         bool ret = GetHostName_internal(out hostName);
391
392                         if (ret == false)
393                                 throw new SocketException(11001);
394
395                         return hostName;
396 #endif
397                 }
398
399 #if NET_2_0
400                 [Obsolete ("Use GetHostEntry instead")]
401 #endif
402                 public static IPHostEntry Resolve(string hostName) 
403                 {
404                         if (hostName == null)
405                                 throw new ArgumentNullException ("hostName");
406
407                         IPHostEntry ret = null;
408
409                         try {
410                                 ret =  GetHostByAddress(hostName);
411                         }
412                         catch{}
413
414                         if(ret == null)
415                                 ret =  GetHostByName(hostName);
416
417                         return ret;
418                 }
419         }
420 }
421