Fix bug #311: On LinkedList.Clear, detach each node instead of dropping them en masse.
[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         public static class Dns {
39                 static Dns ()
40                 {
41                         System.Net.Sockets.Socket.CheckProtocolSupport();
42                 }
43
44 #if !MOONLIGHT // global remove of async methods
45
46                 private delegate IPHostEntry GetHostByNameCallback (string hostName);
47                 private delegate IPHostEntry ResolveCallback (string hostName);
48                 private delegate IPHostEntry GetHostEntryNameCallback (string hostName);
49                 private delegate IPHostEntry GetHostEntryIPCallback (IPAddress hostAddress);
50                 private delegate IPAddress [] GetHostAddressesCallback (string hostName);
51
52                 [Obsolete ("Use BeginGetHostEntry instead")]
53                 public static IAsyncResult BeginGetHostByName (string hostName,
54                         AsyncCallback requestCallback, object stateObject)
55                 {
56                         if (hostName == null)
57                                 throw new ArgumentNullException ("hostName");
58
59                         GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName);
60                         return c.BeginInvoke (hostName, requestCallback, stateObject);
61                 }
62
63                 [Obsolete ("Use BeginGetHostEntry instead")]
64                 public static IAsyncResult BeginResolve (string hostName,
65                         AsyncCallback requestCallback, object stateObject)
66                 {
67                         if (hostName == null)
68                                 throw new ArgumentNullException ("hostName");
69
70                         ResolveCallback c = new ResolveCallback (Resolve);
71                         return c.BeginInvoke (hostName, requestCallback, stateObject);
72                 }
73
74                 public static IAsyncResult BeginGetHostAddresses (string hostNameOrAddress,
75                         AsyncCallback requestCallback, object stateObject)
76                 {
77                         if (hostNameOrAddress == null)
78                                 throw new ArgumentNullException ("hostName");
79                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
80                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
81                                         "and ::0 (IPv6) are unspecified addresses. You " +
82                                         "cannot use them as target address.",
83                                         "hostNameOrAddress");
84
85                         GetHostAddressesCallback c = new GetHostAddressesCallback (GetHostAddresses);
86                         return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject);
87                 }
88
89                 public static IAsyncResult BeginGetHostEntry (string hostNameOrAddress,
90                         AsyncCallback requestCallback, object stateObject)
91                 {
92                         if (hostNameOrAddress == null)
93                                 throw new ArgumentNullException ("hostName");
94                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
95                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
96                                         "and ::0 (IPv6) are unspecified addresses. You " +
97                                         "cannot use them as target address.",
98                                         "hostNameOrAddress");
99
100                         GetHostEntryNameCallback c = new GetHostEntryNameCallback (GetHostEntry);
101                         return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject);
102                 }
103
104                 public static IAsyncResult BeginGetHostEntry (IPAddress address,
105                         AsyncCallback requestCallback, object stateObject)
106                 {
107                         if (address == null)
108                                 throw new ArgumentNullException ("address");
109
110                         GetHostEntryIPCallback c = new GetHostEntryIPCallback (GetHostEntry);
111                         return c.BeginInvoke (address, requestCallback, stateObject);
112                 }
113
114                 [Obsolete ("Use EndGetHostEntry instead")]
115                 public static IPHostEntry EndGetHostByName (IAsyncResult asyncResult) 
116                 {
117                         if (asyncResult == null)
118                                 throw new ArgumentNullException ("asyncResult");
119
120                         AsyncResult async = (AsyncResult) asyncResult;
121                         GetHostByNameCallback cb = (GetHostByNameCallback) async.AsyncDelegate;
122                         return cb.EndInvoke(asyncResult);
123                 }
124
125                 [Obsolete ("Use EndGetHostEntry instead")]
126                 public static IPHostEntry EndResolve (IAsyncResult asyncResult) 
127                 {
128                         if (asyncResult == null)
129                                 throw new ArgumentNullException ("asyncResult");
130                         AsyncResult async = (AsyncResult) asyncResult;
131                         ResolveCallback cb = (ResolveCallback) async.AsyncDelegate;
132                         return cb.EndInvoke(asyncResult);
133                 }
134
135                 public static IPAddress [] EndGetHostAddresses (IAsyncResult asyncResult) 
136                 {
137                         if (asyncResult == null)
138                                 throw new ArgumentNullException ("asyncResult");
139
140                         AsyncResult async = (AsyncResult) asyncResult;
141                         GetHostAddressesCallback cb = (GetHostAddressesCallback) async.AsyncDelegate;
142                         return cb.EndInvoke(asyncResult);
143                 }
144
145                 public static IPHostEntry EndGetHostEntry (IAsyncResult asyncResult) 
146                 {
147                         if (asyncResult == null)
148                                 throw new ArgumentNullException ("asyncResult");
149                         AsyncResult async = (AsyncResult) asyncResult;
150                         if (async.AsyncDelegate is GetHostEntryIPCallback)
151                                 return ((GetHostEntryIPCallback) async.AsyncDelegate).EndInvoke (asyncResult);
152                         GetHostEntryNameCallback cb = (GetHostEntryNameCallback) async.AsyncDelegate;
153                         return cb.EndInvoke(asyncResult);
154                 }
155                 
156 #endif // !MOONLIGHT: global remove of async methods
157
158 #if !TARGET_JVM
159                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
160                 private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list);
161
162                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
163                 private extern static bool GetHostByAddr_internal(string addr, out string h_name, out string[] h_aliases, out string[] h_addr_list);
164
165                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
166                 private extern static bool GetHostName_internal(out string h_name);
167 #endif  
168
169                 private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist) 
170                 {
171                         IPHostEntry he = new IPHostEntry();
172                         ArrayList addrlist = new ArrayList();
173
174                         he.HostName = h_name;
175                         he.Aliases = h_aliases;
176                         for(int i=0; i<h_addrlist.Length; i++) {
177                                 try {
178                                         IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
179
180                                         if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
181                                             (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
182                                                 addrlist.Add(newAddress);
183                                 } catch (ArgumentNullException) {
184                                         /* Ignore this, as the
185                                          * internal call might have
186                                          * left some blank entries at
187                                          * the end of the array
188                                          */
189                                 }
190                         }
191
192                         if(addrlist.Count == 0)
193                                 throw new SocketException(11001);
194
195                         he.AddressList = addrlist.ToArray(typeof(IPAddress)) as IPAddress[];
196                         return he;
197                 }
198
199                 [Obsolete ("Use GetHostEntry instead")]
200                 public static IPHostEntry GetHostByAddress(IPAddress address)
201                 {
202                         if (address == null)
203                                 throw new ArgumentNullException ("address");
204
205                         return GetHostByAddressFromString (address.ToString (), false);
206                 }
207
208                 [Obsolete ("Use GetHostEntry instead")]
209                 public static IPHostEntry GetHostByAddress(string address)
210                 {
211                         if (address == null)
212                                 throw new ArgumentNullException ("address");
213
214                         return GetHostByAddressFromString (address, true);
215                 }
216
217                 static IPHostEntry GetHostByAddressFromString (string address, bool parse)
218                 {
219                         // Undocumented MS behavior: when called with IF_ANY,
220                         // this should return the local host
221                         if (address.Equals ("0.0.0.0")) {
222                                 address = "127.0.0.1";
223                                 parse = false;
224                         }
225
226                         // Must check the IP format, might send an exception if invalid string.
227                         if (parse)
228                                 IPAddress.Parse (address);
229
230                         string h_name;
231                         string[] h_aliases, h_addrlist;
232 #if TARGET_JVM
233                         h_name = null;
234                         h_aliases = null;
235                         h_addrlist = null;
236                         try {
237                                 java.net.InetAddress[] iaArr = 
238                                         java.net.InetAddress.getAllByName(address);
239                                 if (iaArr != null && iaArr.Length > 0)
240                                     h_name = iaArr[0].getHostName();
241                                 if (iaArr != null && iaArr.Length > 0)
242                                 {
243                                     h_addrlist = new String[iaArr.Length];
244                                     for (int i = 0; i < h_addrlist.Length; i++)
245                                         h_addrlist[i] = iaArr[i].getHostAddress();
246                                 }
247                         } catch (java.net.UnknownHostException jUHE) {
248                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
249                         }
250 #else
251                         bool ret = GetHostByAddr_internal(address, out h_name, out h_aliases, out h_addrlist);
252                         if (!ret)
253                                 throw new SocketException(11001);
254 #endif
255                         return (hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist));
256                         
257                 }
258
259                 public static IPHostEntry GetHostEntry (string hostNameOrAddress)
260                 {
261                         if (hostNameOrAddress == null)
262                                 throw new ArgumentNullException ("hostNameOrAddress");
263                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
264                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
265                                         "and ::0 (IPv6) are unspecified addresses. You " +
266                                         "cannot use them as target address.",
267                                         "hostNameOrAddress");
268
269                         IPAddress addr;
270                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
271                                 return GetHostEntry (addr);
272
273                         return GetHostByName (hostNameOrAddress);
274                 }
275
276                 public static IPHostEntry GetHostEntry (IPAddress address)
277                 {
278                         if (address == null)
279                                 throw new ArgumentNullException ("address");
280
281                         return GetHostByAddressFromString (address.ToString (), false);
282                 }
283
284                 public static IPAddress [] GetHostAddresses (string hostNameOrAddress)
285                 {
286                         if (hostNameOrAddress == null)
287                                 throw new ArgumentNullException ("hostNameOrAddress");
288
289                         if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
290                                 throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
291                                         "and ::0 (IPv6) are unspecified addresses. You " +
292                                         "cannot use them as target address.",
293                                         "hostNameOrAddress");
294
295                         IPAddress addr;
296                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
297                                 return new IPAddress[1] { addr };
298
299                         return GetHostEntry (hostNameOrAddress).AddressList;
300                 }
301
302                 [Obsolete ("Use GetHostEntry instead")]
303                 public static IPHostEntry GetHostByName (string hostName)
304                 {
305                         if (hostName == null)
306                                 throw new ArgumentNullException ("hostName");
307 #if TARGET_JVM
308                         if (hostName.Length == 0)
309                                 hostName = "localhost";
310                         try {
311                                 java.net.InetAddress[] iaArr = java.net.InetAddress.getAllByName(hostName);
312                                 IPHostEntry host = new IPHostEntry();
313                                 if (iaArr != null && iaArr.Length > 0)
314                                 {
315                                         host.HostName = iaArr[0].getHostName();
316                                         IPAddress[] ipArr = new IPAddress[iaArr.Length];
317                                         for (int i = 0; i < iaArr.Length; i++)
318                                                 ipArr[i] = IPAddress.Parse(iaArr[i].getHostAddress());
319
320                                         host.AddressList = ipArr;
321                                 }
322                                 return host;
323                         } catch (java.net.UnknownHostException jUHE) {
324                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
325                         }
326 #else
327                         string h_name;
328                         string[] h_aliases, h_addrlist;
329
330                         bool ret = GetHostByName_internal(hostName, out h_name, out h_aliases, out h_addrlist);
331                         if (ret == false)
332                                 throw new SocketException(11001);
333
334                         return(hostent_to_IPHostEntry(h_name, h_aliases, h_addrlist));
335 #endif
336                 }
337
338                 public static string GetHostName ()
339                 {
340 #if TARGET_JVM
341                         return java.net.InetAddress.getLocalHost ().getHostName ();
342 #else
343                         string hostName;
344
345                         bool ret = GetHostName_internal(out hostName);
346
347                         if (ret == false)
348                                 throw new SocketException(11001);
349
350                         return hostName;
351 #endif
352                 }
353
354                 [Obsolete ("Use GetHostEntry instead")]
355                 public static IPHostEntry Resolve(string hostName) 
356                 {
357                         if (hostName == null)
358                                 throw new ArgumentNullException ("hostName");
359
360                         IPHostEntry ret = null;
361
362                         try {
363                                 ret =  GetHostByAddress(hostName);
364                         }
365                         catch{}
366
367                         if(ret == null)
368                                 ret =  GetHostByName(hostName);
369
370                         return ret;
371                 }
372         }
373 }
374