Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 7 additions & 66 deletions src/Renci.SshNet/Abstractions/DnsAbstraction.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,8 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

#if FEATURE_DNS_SYNC
#elif FEATURE_DNS_APM
using Renci.SshNet.Common;
#elif FEATURE_DNS_TAP
#elif FEATURE_DEVICEINFORMATION_APM
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Phone.Net.NetworkInformation;
#elif FEATURE_DATAGRAMSOCKET
using System.Collections.Generic;
using Windows.Networking;
using Windows.Networking.Sockets;
#endif
using System.Threading.Tasks;

namespace Renci.SshNet.Abstractions
{
Expand All @@ -36,72 +22,27 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress)
{
/* TODO Eliminate sync variant, and implement timeout */

#if FEATURE_DNS_SYNC
return Dns.GetHostAddresses(hostNameOrAddress);
#elif FEATURE_DNS_APM
var asyncResult = Dns.BeginGetHostAddresses(hostNameOrAddress, null, null);
if (!asyncResult.AsyncWaitHandle.WaitOne(Session.InfiniteTimeSpan))
throw new SshOperationTimeoutException("Timeout resolving host name.");
return Dns.EndGetHostAddresses(asyncResult);
#elif FEATURE_DNS_TAP
return Dns.GetHostAddressesAsync(hostNameOrAddress).GetAwaiter().GetResult();
#else
IPAddress address;
if (IPAddress.TryParse(hostNameOrAddress, out address))
return new [] { address};

#if FEATURE_DEVICEINFORMATION_APM
var resolveCompleted = new ManualResetEvent(false);
NameResolutionResult nameResolutionResult = null;
DeviceNetworkInformation.ResolveHostNameAsync(new DnsEndPoint(hostNameOrAddress, 0), result =>
{
nameResolutionResult = result;
resolveCompleted.Set();
}, null);

// wait until address is resolved
resolveCompleted.WaitOne();

if (nameResolutionResult.NetworkErrorCode == NetworkError.Success)
{
var addresses = new List<IPAddress>(nameResolutionResult.IPEndPoints.Select(p => p.Address).Distinct());
return addresses.ToArray();
}
throw new SocketException((int)nameResolutionResult.NetworkErrorCode);
#elif FEATURE_DATAGRAMSOCKET

// TODO we may need to only return those IP addresses that are supported on the current system
// TODO http://wojciechkulik.pl/csharp/winrt-how-to-detect-supported-ip-versions

var endpointPairs = DatagramSocket.GetEndpointPairsAsync(new HostName(hostNameOrAddress), "").GetAwaiter().GetResult();
var addresses = new List<IPAddress>();
foreach (var endpointPair in endpointPairs)
{
if (endpointPair.RemoteHostName.Type == HostNameType.Ipv4 || endpointPair.RemoteHostName.Type == HostNameType.Ipv6)
addresses.Add(IPAddress.Parse(endpointPair.RemoteHostName.CanonicalName));
}
if (addresses.Count == 0)
throw new SocketException((int) System.Net.Sockets.SocketError.HostNotFound);
return addresses.ToArray();
#else
throw new NotSupportedException("Resolving hostname to IP address is not implemented.");
#endif // FEATURE_DEVICEINFORMATION_APM
#endif
}

/// <summary>
/// Returns the Internet Protocol (IP) addresses for the specified host.
/// </summary>
/// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
/// <param name="cancellationToken">A cancellation token that can be used to signal the asynchronous operation should be canceled.</param>
/// <returns>
/// A task with result of an array of type <see cref="IPAddress"/> that holds the IP addresses for the host that
/// is specified by the <paramref name="hostNameOrAddress"/> parameter.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="hostNameOrAddress"/> is <see langword="null"/>.</exception>
/// <exception cref="SocketException">An error is encountered when resolving <paramref name="hostNameOrAddress"/>.</exception>
public static Task<IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress)
public static Task<IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress, CancellationToken cancellationToken)
{
#if NET6_0_OR_GREATER
return Dns.GetHostAddressesAsync(hostNameOrAddress, cancellationToken);
#else
return Dns.GetHostAddressesAsync(hostNameOrAddress);
#endif
}
}
}
16 changes: 0 additions & 16 deletions src/Renci.SshNet/Abstractions/SocketAbstraction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public static async Task ConnectAsync(Socket socket, IPEndPoint remoteEndpoint,

private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSpan connectTimeout, bool ownsSocket)
{
#if FEATURE_SOCKET_EAP
var connectCompleted = new ManualResetEvent(initialState: false);
var args = new SocketAsyncEventArgs
{
Expand Down Expand Up @@ -113,19 +112,6 @@ private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSp

// dispose SocketAsyncEventArgs
args.Dispose();
#elif FEATURE_SOCKET_APM
var connectResult = socket.BeginConnect(remoteEndpoint, null, null);
if (!connectResult.AsyncWaitHandle.WaitOne(connectTimeout, false))
throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture,
"Connection failed to establish within {0:F0} milliseconds.", connectTimeout.TotalMilliseconds));
socket.EndConnect(connectResult);
#elif FEATURE_SOCKET_TAP
if (!socket.ConnectAsync(remoteEndpoint).Wait(connectTimeout))
throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture,
"Connection failed to establish within {0:F0} milliseconds.", connectTimeout.TotalMilliseconds));
#else
#error Connecting to a remote endpoint is not implemented.
#endif
}

public static void ClearReadBuffer(Socket socket)
Expand Down Expand Up @@ -391,12 +377,10 @@ public static bool IsErrorResumable(SocketError socketError)
#pragma warning restore IDE0010 // Add missing cases
}

#if FEATURE_SOCKET_EAP
private static void ConnectCompleted(object sender, SocketAsyncEventArgs e)
{
var eventWaitHandle = (ManualResetEvent) e.UserToken;
_ = eventWaitHandle?.Set();
}
#endif // FEATURE_SOCKET_EAP
}
}
2 changes: 1 addition & 1 deletion src/Renci.SshNet/Connection/ConnectorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected async Task<Socket> SocketConnectAsync(string host, int port, Cancellat
{
cancellationToken.ThrowIfCancellationRequested();

var ipAddress = (await DnsAbstraction.GetHostAddressesAsync(host).ConfigureAwait(false))[0];
var ipAddress = (await DnsAbstraction.GetHostAddressesAsync(host, cancellationToken).ConfigureAwait(false))[0];
var ep = new IPEndPoint(ipAddress, port);

DiagnosticAbstraction.Log(string.Format("Initiating connection to '{0}:{1}'.", host, port));
Expand Down
6 changes: 1 addition & 5 deletions src/Renci.SshNet/Renci.SshNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net462' ">
<DefineConstants>$(DefineConstants);FEATURE_BINARY_SERIALIZATION;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_DNS_SYNC;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_RIPEMD160</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_BINARY_SERIALIZATION;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_RIPEMD160</DefineConstants>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0' ">
Expand All @@ -16,8 +16,4 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0' ">
<DefineConstants>$(DefineConstants);FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP</DefineConstants>
</PropertyGroup>
</Project>