| | | 1 | | using System; |
| | | 2 | | using System.Net; |
| | | 3 | | using System.Net.Sockets; |
| | | 4 | | using System.Threading.Tasks; |
| | | 5 | | |
| | | 6 | | #if FEATURE_DNS_SYNC |
| | | 7 | | #elif FEATURE_DNS_APM |
| | | 8 | | using Renci.SshNet.Common; |
| | | 9 | | #elif FEATURE_DNS_TAP |
| | | 10 | | #elif FEATURE_DEVICEINFORMATION_APM |
| | | 11 | | using System.Collections.Generic; |
| | | 12 | | using System.Linq; |
| | | 13 | | using System.Threading; |
| | | 14 | | using Microsoft.Phone.Net.NetworkInformation; |
| | | 15 | | #elif FEATURE_DATAGRAMSOCKET |
| | | 16 | | using System.Collections.Generic; |
| | | 17 | | using Windows.Networking; |
| | | 18 | | using Windows.Networking.Sockets; |
| | | 19 | | #endif |
| | | 20 | | |
| | | 21 | | namespace Renci.SshNet.Abstractions |
| | | 22 | | { |
| | | 23 | | internal static class DnsAbstraction |
| | | 24 | | { |
| | | 25 | | /// <summary> |
| | | 26 | | /// Returns the Internet Protocol (IP) addresses for the specified host. |
| | | 27 | | /// </summary> |
| | | 28 | | /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param> |
| | | 29 | | /// <returns> |
| | | 30 | | /// An array of type <see cref="IPAddress"/> that holds the IP addresses for the host that |
| | | 31 | | /// is specified by the <paramref name="hostNameOrAddress"/> parameter. |
| | | 32 | | /// </returns> |
| | | 33 | | /// <exception cref="ArgumentNullException"><paramref name="hostNameOrAddress"/> is <see langword="null"/>.</exc |
| | | 34 | | /// <exception cref="SocketException">An error is encountered when resolving <paramref name="hostNameOrAddress"/ |
| | | 35 | | public static IPAddress[] GetHostAddresses(string hostNameOrAddress) |
| | 2730 | 36 | | { |
| | | 37 | | /* TODO Eliminate sync variant, and implement timeout */ |
| | | 38 | | |
| | | 39 | | #if FEATURE_DNS_SYNC |
| | 2730 | 40 | | return Dns.GetHostAddresses(hostNameOrAddress); |
| | | 41 | | #elif FEATURE_DNS_APM |
| | | 42 | | var asyncResult = Dns.BeginGetHostAddresses(hostNameOrAddress, null, null); |
| | | 43 | | if (!asyncResult.AsyncWaitHandle.WaitOne(Session.InfiniteTimeSpan)) |
| | | 44 | | throw new SshOperationTimeoutException("Timeout resolving host name."); |
| | | 45 | | return Dns.EndGetHostAddresses(asyncResult); |
| | | 46 | | #elif FEATURE_DNS_TAP |
| | | 47 | | return Dns.GetHostAddressesAsync(hostNameOrAddress).GetAwaiter().GetResult(); |
| | | 48 | | #else |
| | | 49 | | IPAddress address; |
| | | 50 | | if (IPAddress.TryParse(hostNameOrAddress, out address)) |
| | | 51 | | return new [] { address}; |
| | | 52 | | |
| | | 53 | | #if FEATURE_DEVICEINFORMATION_APM |
| | | 54 | | var resolveCompleted = new ManualResetEvent(false); |
| | | 55 | | NameResolutionResult nameResolutionResult = null; |
| | | 56 | | DeviceNetworkInformation.ResolveHostNameAsync(new DnsEndPoint(hostNameOrAddress, 0), result => |
| | | 57 | | { |
| | | 58 | | nameResolutionResult = result; |
| | | 59 | | resolveCompleted.Set(); |
| | | 60 | | }, null); |
| | | 61 | | |
| | | 62 | | // wait until address is resolved |
| | | 63 | | resolveCompleted.WaitOne(); |
| | | 64 | | |
| | | 65 | | if (nameResolutionResult.NetworkErrorCode == NetworkError.Success) |
| | | 66 | | { |
| | | 67 | | var addresses = new List<IPAddress>(nameResolutionResult.IPEndPoints.Select(p => p.Address).Distinct()); |
| | | 68 | | return addresses.ToArray(); |
| | | 69 | | } |
| | | 70 | | throw new SocketException((int)nameResolutionResult.NetworkErrorCode); |
| | | 71 | | #elif FEATURE_DATAGRAMSOCKET |
| | | 72 | | |
| | | 73 | | // TODO we may need to only return those IP addresses that are supported on the current system |
| | | 74 | | // TODO http://wojciechkulik.pl/csharp/winrt-how-to-detect-supported-ip-versions |
| | | 75 | | |
| | | 76 | | var endpointPairs = DatagramSocket.GetEndpointPairsAsync(new HostName(hostNameOrAddress), "").GetAwaiter().G |
| | | 77 | | var addresses = new List<IPAddress>(); |
| | | 78 | | foreach (var endpointPair in endpointPairs) |
| | | 79 | | { |
| | | 80 | | if (endpointPair.RemoteHostName.Type == HostNameType.Ipv4 || endpointPair.RemoteHostName.Type == HostNam |
| | | 81 | | addresses.Add(IPAddress.Parse(endpointPair.RemoteHostName.CanonicalName)); |
| | | 82 | | } |
| | | 83 | | if (addresses.Count == 0) |
| | | 84 | | throw new SocketException((int) System.Net.Sockets.SocketError.HostNotFound); |
| | | 85 | | return addresses.ToArray(); |
| | | 86 | | #else |
| | | 87 | | throw new NotSupportedException("Resolving hostname to IP address is not implemented."); |
| | | 88 | | #endif // FEATURE_DEVICEINFORMATION_APM |
| | | 89 | | #endif |
| | 2718 | 90 | | } |
| | | 91 | | |
| | | 92 | | /// <summary> |
| | | 93 | | /// Returns the Internet Protocol (IP) addresses for the specified host. |
| | | 94 | | /// </summary> |
| | | 95 | | /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param> |
| | | 96 | | /// <returns> |
| | | 97 | | /// A task with result of an array of type <see cref="IPAddress"/> that holds the IP addresses for the host that |
| | | 98 | | /// is specified by the <paramref name="hostNameOrAddress"/> parameter. |
| | | 99 | | /// </returns> |
| | | 100 | | /// <exception cref="ArgumentNullException"><paramref name="hostNameOrAddress"/> is <see langword="null"/>.</exc |
| | | 101 | | /// <exception cref="SocketException">An error is encountered when resolving <paramref name="hostNameOrAddress"/ |
| | | 102 | | public static Task<IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress) |
| | 8 | 103 | | { |
| | 8 | 104 | | return Dns.GetHostAddressesAsync(hostNameOrAddress); |
| | 8 | 105 | | } |
| | | 106 | | } |
| | | 107 | | } |