X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem%2FSystem.Net%2FDns.cs;h=0ef74b1db930e8b4905e349eab4ca3b46fddacad;hb=6b41703ee1971df9c44309c7b252855d124ba399;hp=726606e68b29abfe365846b6cb977f9407f5fd26;hpb=6242fd93dbf034633f4bbeeb917490f12bc6837e;p=mono.git diff --git a/mcs/class/System/System.Net/Dns.cs b/mcs/class/System/System.Net/Dns.cs index 726606e68b2..0ef74b1db93 100644 --- a/mcs/class/System/System.Net/Dns.cs +++ b/mcs/class/System/System.Net/Dns.cs @@ -1,249 +1,395 @@ // System.Net.Dns.cs // // Author: Mads Pultz (mpultz@diku.dk) +// Author: Lawrence Pit (loz@cable.a2000.nl) // // (C) Mads Pultz, 2001 +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using System.Net.Sockets; using System.Text; using System.Collections; -using System.Runtime.InteropServices; +using System.Threading; +using System.Runtime.CompilerServices; +using System.Runtime.Remoting.Messaging; namespace System.Net { - +#if NET_2_0 + public static class Dns { +#else public sealed class Dns { - - /// - /// This class conforms to the C structure hostent and is used - /// by the Dns class when doing native calls. - /// - [StructLayout(LayoutKind.Sequential)] - private unsafe class Hostent { - public string h_name; /* official name */ - public byte** h_aliases; /* alias list */ - public short h_addrtype; /* address type */ - public short h_length; /* address length */ - public byte** h_addr_list; /* address list */ - } - - public static IAsyncResult BeginGetHostByName(string hostName, - AsyncCallback requestCallback, - object stateObject) { - // TODO - throw new NotImplementedException(); - } - - public static IAsyncResult BeginResolve(string hostName, - AsyncCallback requestCallback, - object stateObject) { - // TODO - throw new NotImplementedException(); - } - - public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult) { - // TODO - throw new NotImplementedException(); - } - - public static IPHostEntry EndResolve(IAsyncResult asyncResult) { - // TODO - throw new NotImplementedException(); - } - - /// - /// IP address in network byte order (e.g. Big-Endian). - /// - /// - /// Length of IP address - /// - /// - /// Type (should be 2, equals AF_INET) - /// - [DllImport("cygwin1", EntryPoint="gethostbyaddr")] - private static extern IntPtr _GetHostByAddress(byte[] hostName, - short length, - short type); - - /// - /// IP address in network byte order (e.g. Big-Endian). - /// - private static IPHostEntry GetHostByAddress(long address) { - short length = 4; - if (address > uint.MaxValue) - length = 8; - byte[] addr = new byte[length]; - for(int i = length - 1, j = 0; i >= 0; --i, ++j) { - byte b = (byte)(address >> i * 8); -// Console.WriteLine(b); - addr[j] = b; - } - IntPtr p = _GetHostByAddress(addr, length, 2); // TODO: set type - if (p == IntPtr.Zero) - throw new SocketException(); // TODO: set error code - Hostent h = new Hostent(); - System.Runtime.InteropServices.Marshal.PtrToStructure(p, h); - return ToIPHostEntry(h); - } - - public static IPHostEntry GetHostByAddress(IPAddress address) { - if (address == null) - throw new ArgumentNullException(); - return GetHostByAddress(IPAddress.HostToNetworkOrder(address.Address)); + + private Dns () {} +#endif + + static Dns () + { + System.Net.Sockets.Socket.CheckProtocolSupport(); } - - public static IPHostEntry GetHostByAddress(string address) { - if (address == null) - throw new ArgumentNullException(); - return GetHostByAddress(CreateAddress(address)); - } - -/* - [DllImport("cygwin1", EntryPoint="h_errno")] - private static extern int _h_errno; -*/ - - [DllImport("cygwin1", EntryPoint="gethostbyname")] - private static extern IntPtr _GetHostByName(string hostName); - - public static IPHostEntry GetHostByName(string hostName) { + + private delegate IPHostEntry GetHostByNameCallback (string hostName); + private delegate IPHostEntry ResolveCallback (string hostName); +#if NET_2_0 + private delegate IPHostEntry GetHostEntryNameCallback (string hostName); + private delegate IPHostEntry GetHostEntryIPCallback (IPAddress hostAddress); + private delegate IPAddress [] GetHostAddressesCallback (string hostName); +#endif + +#if NET_2_0 + [Obsolete ("Use BeginGetHostEntry instead")] +#endif + public static IAsyncResult BeginGetHostByName (string hostName, + AsyncCallback requestCallback, object stateObject) + { if (hostName == null) - throw new ArgumentNullException(); - IntPtr p = _GetHostByName(hostName); - // int errNo = _h_errno; - if (p == IntPtr.Zero) - throw new SocketException(); // TODO: set error code - Hostent h = new Hostent(); - System.Runtime.InteropServices.Marshal.PtrToStructure(p, h); - return ToIPHostEntry(h); - } - - /// - /// This method returns the host name associated with the local host. - /// - public static string GetHostName() { - IPHostEntry h = GetHostByAddress("127.0.0.1"); - return h.HostName; - } - - /// - /// IP address in Little-Endian byte order. - /// - /// - /// IP address in dotted notation form. - /// - public static string IpToString(int address) { - address = IPAddress.HostToNetworkOrder(address); - StringBuilder res = new StringBuilder(); - for(int i = 3; i > 0; --i) { - byte b = (byte)(address >> i * 8); - res.Append(b); - res.Append('.'); - } - res.Append((byte)address); - return res.ToString(); - } - - /// - /// This method resovles a DNS-style host name or IP - /// address. - /// - /// - /// A string containing either a DNS-style host name (e.g. - /// www.go-mono.com) or IP address (e.g. 129.250.184.233). - /// - public static IPHostEntry Resolve(string hostName) { + throw new ArgumentNullException ("hostName"); + + GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName); + return c.BeginInvoke (hostName, requestCallback, stateObject); + } + +#if NET_2_0 + [Obsolete ("Use BeginGetHostEntry instead")] +#endif + public static IAsyncResult BeginResolve (string hostName, + AsyncCallback requestCallback, object stateObject) + { if (hostName == null) - throw new ArgumentNullException(); - try { - long addr = CreateAddress(hostName); - if (addr > uint.MaxValue) - throw new FormatException("Only IP version 4 addresses are supported"); - return GetHostByAddress(addr); - } catch (FormatException) { - return GetHostByName(hostName); + throw new ArgumentNullException ("hostName"); + + ResolveCallback c = new ResolveCallback (Resolve); + return c.BeginInvoke (hostName, requestCallback, stateObject); + } + +#if NET_2_0 + public static IAsyncResult BeginGetHostAddresses (string hostName, + AsyncCallback requestCallback, object stateObject) + { + if (hostName == null) + throw new ArgumentNullException ("hostName"); + + GetHostAddressesCallback c = new GetHostAddressesCallback (GetHostAddresses); + return c.BeginInvoke (hostName, requestCallback, stateObject); + } + + public static IAsyncResult BeginGetHostEntry (string hostNameOrAddress, + AsyncCallback requestCallback, object stateObject) + { + if (hostNameOrAddress == null) + throw new ArgumentNullException ("hostNameOrAddress"); + + GetHostEntryNameCallback c = new GetHostEntryNameCallback (GetHostEntry); + return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject); + } + + public static IAsyncResult BeginGetHostEntry (IPAddress hostAddress, + AsyncCallback requestCallback, object stateObject) + { + if (hostAddress == null) + throw new ArgumentNullException ("hostAddress"); + + GetHostEntryIPCallback c = new GetHostEntryIPCallback (GetHostEntry); + return c.BeginInvoke (hostAddress, requestCallback, stateObject); + } +#endif + +#if NET_2_0 + [Obsolete ("Use EndGetHostEntry instead")] +#endif + public static IPHostEntry EndGetHostByName (IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException ("asyncResult"); + + AsyncResult async = (AsyncResult) asyncResult; + GetHostByNameCallback cb = (GetHostByNameCallback) async.AsyncDelegate; + return cb.EndInvoke(asyncResult); + } + +#if NET_2_0 + [Obsolete ("Use EndGetHostEntry instead")] +#endif + public static IPHostEntry EndResolve (IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException ("asyncResult"); + AsyncResult async = (AsyncResult) asyncResult; + ResolveCallback cb = (ResolveCallback) async.AsyncDelegate; + return cb.EndInvoke(asyncResult); + } + +#if NET_2_0 + + public static IPAddress [] EndGetHostAddresses (IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException ("asyncResult"); + + AsyncResult async = (AsyncResult) asyncResult; + GetHostAddressesCallback cb = (GetHostAddressesCallback) async.AsyncDelegate; + return cb.EndInvoke(asyncResult); + } + + public static IPHostEntry EndGetHostEntry (IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException ("asyncResult"); + AsyncResult async = (AsyncResult) asyncResult; +#if NET_2_0 + if (async.AsyncDelegate is GetHostEntryIPCallback) + return ((GetHostEntryIPCallback) async.AsyncDelegate).EndInvoke (asyncResult); +#endif + GetHostEntryNameCallback cb = (GetHostEntryNameCallback) async.AsyncDelegate; + return cb.EndInvoke(asyncResult); + } +#endif + +#if !TARGET_JVM + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static bool GetHostByAddr_internal(string addr, out string h_name, out string[] h_aliases, out string[] h_addr_list); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static bool GetHostName_internal(out string h_name); +#endif + + private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist) + { + IPHostEntry he = new IPHostEntry(); + ArrayList addrlist = new ArrayList(); + + he.HostName = h_name; + he.Aliases = h_aliases; + for(int i=0; i - /// Utility method. This method converts a Hostent instance to a - /// IPHostEntry instance. - /// - /// - /// Object which should be mapped to a IPHostEntry instance. - /// - private static unsafe IPHostEntry ToIPHostEntry(Hostent h) { - IPHostEntry res = new IPHostEntry(); - - // Set host name - res.HostName = h.h_name; - - // Set IP address list - byte** p = h.h_addr_list; - ArrayList tmp = new ArrayList(1); - while (*p != null) { - tmp.Add(CreateIPAddress(*p, h.h_length)); - ++p; + +#if NET_2_0 + [Obsolete ("Use GetHostEntry instead")] +#endif + public static IPHostEntry GetHostByAddress(IPAddress address) + { + if (address == null) + throw new ArgumentNullException ("address"); + + return GetHostByAddressFromString (address.ToString (), false); + } + +#if NET_2_0 + [Obsolete ("Use GetHostEntry instead")] +#endif + public static IPHostEntry GetHostByAddress(string address) + { + if (address == null) + throw new ArgumentNullException ("address"); + + return GetHostByAddressFromString (address, true); + } + + static IPHostEntry GetHostByAddressFromString (string address, bool parse) + { + // Undocumented MS behavior: when called with IF_ANY, + // this should return the local host + if (address.Equals ("0.0.0.0")) { + address = "127.0.0.1"; + parse = false; } - IPAddress[] addr_list = new IPAddress[tmp.Count]; - for(int i = 0; i < tmp.Count; ++i) - addr_list[i] = (IPAddress)tmp[i]; - res.AddressList = addr_list; + + // Must check the IP format, might send an exception if invalid string. + if (parse) + IPAddress.Parse (address); + + string h_name; + string[] h_aliases, h_addrlist; +#if TARGET_JVM + h_name = null; + h_aliases = null; + h_addrlist = null; + try { + java.net.InetAddress[] iaArr = + java.net.InetAddress.getAllByName(address); + if (iaArr != null && iaArr.Length > 0) + h_name = iaArr[0].getHostName(); + if (iaArr != null && iaArr.Length > 0) + { + h_addrlist = new String[iaArr.Length]; + for (int i = 0; i < h_addrlist.Length; i++) + h_addrlist[i] = iaArr[i].getHostAddress(); + } + } catch (java.net.UnknownHostException jUHE) { + throw new SocketException((int)SocketError.HostNotFound, jUHE.Message); + } +#else + bool ret = GetHostByAddr_internal(address, out h_name, out h_aliases, out h_addrlist); + if (!ret) + throw new SocketException(11001); +#endif + return (hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist)); - // Set IP aliases - p = h.h_aliases; - tmp.Clear(); - while (*p != null) { - tmp.Add(new string((sbyte*)*p)); - ++p; + } + +#if NET_2_0 + public static IPHostEntry GetHostEntry (string hostNameOrAddress) + { + if (hostNameOrAddress == null) + throw new ArgumentNullException ("hostNameOrAddress"); + + if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "") + hostNameOrAddress = "127.0.0.1"; + IPAddress addr; + if (IPAddress.TryParse (hostNameOrAddress, out addr)) + return GetHostEntry (addr); + else + return GetHostByName (hostNameOrAddress); + } + + public static IPHostEntry GetHostEntry (IPAddress address) + { + if (address == null) + throw new ArgumentNullException ("address"); + + return GetHostByAddressFromString (address.ToString (), false); + } + + public static IPAddress [] GetHostAddresses (string hostNameOrAddress) + { + if (hostNameOrAddress == null) + throw new ArgumentNullException ("hostNameOrAddress"); + + if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "") + hostNameOrAddress = "127.0.0.1"; + + IPAddress addr; + if (IPAddress.TryParse (hostNameOrAddress, out addr)) + { + return new IPAddress[1] { addr }; } - string[] aliases = new string[tmp.Count]; - for(int i = 0; i < tmp.Count; ++i) - aliases[i] = (string)tmp[i]; - res.Aliases = aliases; - - return res; - } - - /// - /// Utility method. Convert IP address in dotted notation - /// to IP address. - /// - private static long CreateAddress(string address) { - string[] tokens = address.Split('.'); - if (tokens.Length % 4 != 0) - throw new FormatException("IP address has invalid length"); - long addr = 0; - for(int i = 0, j = tokens.Length - 1; i < tokens.Length; ++i, --j) { - try { - addr = addr | (((long)byte.Parse(tokens[i])) << j * 8); - } catch (OverflowException) { - throw new FormatException("Invalid IP address format"); - } + else + { + + return GetHostEntry (hostNameOrAddress).AddressList; } - return addr; - } - - /// - /// Utility method. This method creates a IP address. - /// - /// - /// IP address in network byte order (e.g. Big-Endian). - /// - /// - /// Length of IP address (4 or 8 bytes). - /// - private static unsafe IPAddress CreateIPAddress(byte* addr, short length) { - byte* p = addr; - long res = 0; - for(int i = 0, j = length - 1; i < length; ++i, --j) { - res += *p << j * 8; - ++p; + } +#endif + +#if NET_2_0 + [Obsolete ("Use GetHostEntry instead")] +#endif + public static IPHostEntry GetHostByName (string hostName) + { + if (hostName == null) + throw new ArgumentNullException (); +#if TARGET_JVM + if (hostName.Length == 0) + hostName = "localhost"; + try { + java.net.InetAddress[] iaArr = java.net.InetAddress.getAllByName(hostName); + IPHostEntry host = new IPHostEntry(); + if (iaArr != null && iaArr.Length > 0) + { + host.HostName = iaArr[0].getHostName(); + IPAddress[] ipArr = new IPAddress[iaArr.Length]; + for (int i = 0; i < iaArr.Length; i++) + ipArr[i] = IPAddress.Parse(iaArr[i].getHostAddress()); + + host.AddressList = ipArr; + } + return host; + } catch (java.net.UnknownHostException jUHE) { + throw new SocketException((int)SocketError.HostNotFound, jUHE.Message); } - if (res > uint.MaxValue) - return new IPAddress(IPAddress.NetworkToHostOrder(res)); - else - return new IPAddress(IPAddress.NetworkToHostOrder((int)res)); +#else + string h_name; + string[] h_aliases, h_addrlist; + + bool ret = GetHostByName_internal(hostName, out h_name, + out h_aliases, + out h_addrlist); + if (ret == false) + throw new SocketException(11001); + + return(hostent_to_IPHostEntry(h_name, h_aliases, + h_addrlist)); +#endif + } + + public static string GetHostName () + { +#if TARGET_JVM + return java.net.InetAddress.getLocalHost ().getHostName (); +#else + string hostName; + + bool ret = GetHostName_internal(out hostName); + + if (ret == false) + throw new SocketException(11001); + + return hostName; +#endif + } + +#if NET_2_0 + [Obsolete ("Use GetHostEntry instead")] +#endif + public static IPHostEntry Resolve(string hostName) + { + if (hostName == null) + throw new ArgumentNullException ("hostName"); + + IPHostEntry ret = null; + + try { + ret = GetHostByAddress(hostName); + } + catch{} + + if(ret == null) + ret = GetHostByName(hostName); + + return ret; } } }