Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WASI] System.Net.NameResolution #107351

Merged
merged 19 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal static partial class Sys

internal static unsafe string GetHostName()
{
#if !TARGET_WASI
const int HOST_NAME_MAX = 255;
const int ArrLength = HOST_NAME_MAX + 1;

Expand All @@ -34,6 +35,9 @@ internal static unsafe string GetHostName()
name[ArrLength - 1] = 0;

return Marshal.PtrToStringUTF8((IntPtr)name)!;
#else
return "localhost";
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal enum GetAddrInfoErrorFlags : int
EAI_BADARG = 6, // One or more input arguments were invalid.
EAI_NOMORE = 7, // No more entries are present in the list.
EAI_MEMORY = 8, // Out of memory.
EAI_SYSTEM = 9, // Other system error; errno is set to indicate the error.
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<PropertyGroup>
<StrongNameKeyId>Microsoft</StrongNameKeyId>
<IncludePlatformAttributes>true</IncludePlatformAttributes>
<!-- WASI until https://github.com/dotnet/runtime/issues/98957 -->
<UnsupportedOSPlatforms>browser;wasi</UnsupportedOSPlatforms>
<UnsupportedOSPlatforms>browser</UnsupportedOSPlatforms>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
<PropertyGroup>
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi' or '$(TargetPlatformIdentifier)' == ''">SR.SystemNetNameResolution_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
<ApiExclusionListPath Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi'">ExcludeApiList.PNSE.Browser.txt</ApiExclusionListPath>
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == ''">SR.SystemNetNameResolution_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
<ApiExclusionListPath Condition="'$(TargetPlatformIdentifier)' == 'browser'">ExcludeApiList.PNSE.Browser.txt</ApiExclusionListPath>
<DefineConstants Condition="'$(TargetPlatformIdentifier)' == 'wasi'">$(DefineConstants);TARGET_WASI</DefineConstants>
</PropertyGroup>

<ItemGroup Condition="'$(GeneratePlatformNotSupportedAssemblyMessage)' == ''">
<Compile Include="System\Net\Dns.cs" />
<Compile Include="System\Net\IPHostEntry.cs" />
<Compile Include="System\Net\NetEventSource.NameResolution.cs" />
<Compile Include="System\Net\NameResolutionMetrics.cs" />
<Compile Include="System\Net\NameResolutionTelemetry.cs" />
<Compile Include="System\Net\NetEventSource.NameResolution.cs" Condition="'$(TargetPlatformIdentifier)' != 'wasi'" />
<Compile Include="System\Net\NameResolutionMetrics.cs" Condition="'$(TargetPlatformIdentifier)' != 'wasi'" />
<Compile Include="System\Net\NameResolutionTelemetry.cs" Condition="'$(TargetPlatformIdentifier)' != 'wasi'" />
<!-- Logging -->
<Compile Include="$(CommonPath)System\Net\Logging\NetEventSource.Common.cs"
Link="Common\System\Net\Logging\NetEventSource.Common.cs" />
Expand Down Expand Up @@ -96,10 +97,43 @@
Link="Common\Interop\Unix\System.Native\Interop.SocketAddress.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi'">
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'browser'">
<Compile Include="System\Net\Dns.Browser.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'wasi'">
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetHostName.cs"
Link="Common\Interop\Unix\System.Native\Interop.GetHostName.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.ErrNo.cs"
Link="Common\Interop\Unix\System.Native\Interop.ErrNo.cs"/>

<Compile Include="System\Net\NameResolutionTelemetry.Wasi.cs" />

<Compile Include="System\Net\NameResolutionPal.Unix.cs" />
<Compile Include="$(CommonPath)System\Net\InteropIPAddressExtensions.Unix.cs"
Link="Common\System\Net\InteropIPAddressExtensions.Unix.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddressPal.Unix.cs"
Link="Common\System\Net\Internals\SocketAddressPal.Unix.cs" />
<Compile Include="$(CommonPath)System\Net\SocketProtocolSupportPal.Unix.cs"
Link="Common\System\Net\SocketProtocolSupportPal.Unix" />
<Compile Include="$(CommonPath)Interop\Unix\Interop.Errors.cs"
Link="Common\Interop\CoreLib\Unix\Interop.Errors.cs" />
<Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
Link="Common\Interop\Unix\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Close.cs"
Link="Common\Interop\Unix\System.Native\Interop.Close.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetNameInfo.cs"
Link="Common\Interop\Unix\System.Native\Interop.GetNameInfo.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.HostEntry.cs"
Link="Common\Interop\Unix\System.Native\Interop.HostEntries.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.IPAddress.cs"
Link="Common\Interop\Unix\System.Native\Interop.IPAddress.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Socket.cs"
Link="Common\Interop\Unix\System.Native\Interop.Socket.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.SocketAddress.cs"
Link="Common\Interop\Unix\System.Native\Interop.SocketAddress.cs" />
</ItemGroup>

<ItemGroup>
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="System.Collections" />
Expand Down
47 changes: 47 additions & 0 deletions src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Versioning;

namespace System.Net
{
Expand Down Expand Up @@ -37,6 +38,9 @@ public static string GetHostName()

public static IPHostEntry GetHostEntry(IPAddress address)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(address);

if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
Expand Down Expand Up @@ -68,6 +72,7 @@ public static IPHostEntry GetHostEntry(string hostNameOrAddress, AddressFamily f

// See if it's an IP Address.
IPHostEntry ipHostEntry;
#if !TARGET_WASI
if (IPAddress.TryParse(hostNameOrAddress, out IPAddress? address))
{
if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
Expand All @@ -79,6 +84,7 @@ public static IPHostEntry GetHostEntry(string hostNameOrAddress, AddressFamily f
ipHostEntry = GetHostEntryCore(address, family);
}
else
#endif // TARGET_WASI
{
ipHostEntry = GetHostEntryCore(hostNameOrAddress, family);
}
Expand Down Expand Up @@ -147,6 +153,9 @@ public static Task<IPHostEntry> GetHostEntryAsync(string hostNameOrAddress, Addr

public static Task<IPHostEntry> GetHostEntryAsync(IPAddress address)
{
#if TARGET_WASI
throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#else
ArgumentNullException.ThrowIfNull(address);

if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
Expand All @@ -160,6 +169,7 @@ public static Task<IPHostEntry> GetHostEntryAsync(IPAddress address)
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info((IPAddress)s, $"{ipHostEntry} with {ipHostEntry.AddressList.Length} entries");
return ipHostEntry;
}, address, CancellationToken.None);
#endif // TARGET_WASI
}

public static IAsyncResult BeginGetHostEntry(IPAddress address, AsyncCallback? requestCallback, object? stateObject) =>
Expand All @@ -170,6 +180,9 @@ public static IAsyncResult BeginGetHostEntry(string hostNameOrAddress, AsyncCall

public static IPHostEntry EndGetHostEntry(IAsyncResult asyncResult)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(asyncResult);

return TaskToAsyncResult.End<IPHostEntry>(asyncResult);
Expand All @@ -192,6 +205,7 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress, AddressFami

// See if it's an IP Address.
IPAddress[] addresses;
#if !TARGET_WASI
if (IPAddress.TryParse(hostNameOrAddress, out IPAddress? address))
{
if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
Expand All @@ -203,6 +217,7 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress, AddressFami
addresses = (family == AddressFamily.Unspecified || address.AddressFamily == family) ? new IPAddress[] { address } : Array.Empty<IPAddress>();
}
else
#endif // TARGET_WASI
{
addresses = GetHostAddressesCore(hostNameOrAddress, family);
}
Expand Down Expand Up @@ -244,6 +259,9 @@ public static IAsyncResult BeginGetHostAddresses(string hostNameOrAddress, Async

public static IPAddress[] EndGetHostAddresses(IAsyncResult asyncResult)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(asyncResult);

return TaskToAsyncResult.End<IPAddress[]>(asyncResult);
Expand All @@ -269,6 +287,9 @@ public static IAsyncResult BeginGetHostByName(string hostName, AsyncCallback? re
[Obsolete("EndGetHostByName has been deprecated. Use EndGetHostEntry instead.")]
public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(asyncResult);

return TaskToAsyncResult.End<IPHostEntry>(asyncResult);
Expand All @@ -277,6 +298,9 @@ public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
[Obsolete("GetHostByAddress has been deprecated. Use GetHostEntry instead.")]
public static IPHostEntry GetHostByAddress(string address)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(address);

IPHostEntry ipHostEntry = GetHostEntryCore(IPAddress.Parse(address), AddressFamily.Unspecified);
Expand All @@ -288,6 +312,9 @@ public static IPHostEntry GetHostByAddress(string address)
[Obsolete("GetHostByAddress has been deprecated. Use GetHostEntry instead.")]
public static IPHostEntry GetHostByAddress(IPAddress address)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
ArgumentNullException.ThrowIfNull(address);

IPHostEntry ipHostEntry = GetHostEntryCore(address, AddressFamily.Unspecified);
Expand All @@ -303,6 +330,7 @@ public static IPHostEntry Resolve(string hostName)

// See if it's an IP Address.
IPHostEntry ipHostEntry;
#if !TARGET_WASI
if (IPAddress.TryParse(hostName, out IPAddress? address) &&
(address.AddressFamily != AddressFamily.InterNetworkV6 || SocketProtocolSupportPal.OSSupportsIPv6))
{
Expand All @@ -317,6 +345,7 @@ public static IPHostEntry Resolve(string hostName)
}
}
else
#endif // TARGET_WASI
{
ipHostEntry = GetHostEntryCore(hostName, AddressFamily.Unspecified);
}
Expand All @@ -332,6 +361,9 @@ public static IAsyncResult BeginResolve(string hostName, AsyncCallback? requestC
[Obsolete("EndResolve has been deprecated. Use EndGetHostEntry instead.")]
public static IPHostEntry EndResolve(IAsyncResult asyncResult)
{
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif // TARGET_WASI
IPHostEntry ipHostEntry;

try
Expand Down Expand Up @@ -405,13 +437,16 @@ private static object GetHostEntryOrAddressesCore(string hostName, bool justAddr
return result;
}

[UnsupportedOSPlatform("wasi")]
private static IPHostEntry GetHostEntryCore(IPAddress address, AddressFamily addressFamily, NameResolutionActivity? activityOrDefault = default) =>
(IPHostEntry)GetHostEntryOrAddressesCore(address, justAddresses: false, addressFamily, activityOrDefault);

[UnsupportedOSPlatform("wasi")]
private static IPAddress[] GetHostAddressesCore(IPAddress address, AddressFamily addressFamily, NameResolutionActivity? activityOrDefault = default) =>
(IPAddress[])GetHostEntryOrAddressesCore(address, justAddresses: true, addressFamily, activityOrDefault);

// Does internal IPAddress reverse and then forward lookups (for Legacy and current public methods).
[UnsupportedOSPlatform("wasi")]
private static object GetHostEntryOrAddressesCore(IPAddress address, bool justAddresses, AddressFamily addressFamily, NameResolutionActivity? activityOrDefault = default)
{
// Try to get the data for the host from its address.
Expand Down Expand Up @@ -499,6 +534,7 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR

object asyncState;

#if !TARGET_WASI
// See if it's an IP Address.
if (IPAddress.TryParse(hostName, out IPAddress? ipAddress))
{
Expand All @@ -518,6 +554,7 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
asyncState = family == AddressFamily.Unspecified ? (object)ipAddress : new KeyValuePair<IPAddress, AddressFamily>(ipAddress, family);
}
else
#endif // TARGET_WASI
{
if (NameResolutionPal.SupportsGetAddrInfoAsync)
{
Expand Down Expand Up @@ -558,8 +595,13 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
{
string h => GetHostAddressesCore(h, AddressFamily.Unspecified, activity),
KeyValuePair<string, AddressFamily> t => GetHostAddressesCore(t.Key, t.Value, activity),
#if !TARGET_WASI
IPAddress a => GetHostAddressesCore(a, AddressFamily.Unspecified, activity),
KeyValuePair<IPAddress, AddressFamily> t => GetHostAddressesCore(t.Key, t.Value, activity),
#else
IPAddress => throw new PlatformNotSupportedException(),
KeyValuePair<IPAddress, AddressFamily> => throw new PlatformNotSupportedException(),
#endif // TARGET_WASI
_ => null
}, asyncState, cancellationToken);
}
Expand All @@ -569,8 +611,13 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
{
string h => GetHostEntryCore(h, AddressFamily.Unspecified, activity),
KeyValuePair<string, AddressFamily> t => GetHostEntryCore(t.Key, t.Value, activity),
#if !TARGET_WASI
IPAddress a => GetHostEntryCore(a, AddressFamily.Unspecified, activity),
KeyValuePair<IPAddress, AddressFamily> t => GetHostEntryCore(t.Key, t.Value, activity),
#else
IPAddress => throw new PlatformNotSupportedException(),
KeyValuePair<IPAddress, AddressFamily> => throw new PlatformNotSupportedException(),
#endif // TARGET_WASI
_ => null
}, asyncState, cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ private static SocketError GetSocketErrorForNativeError(int error)
return SocketError.HostNotFound;
case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_MEMORY:
throw new OutOfMemoryException();
case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_SYSTEM:
#if !TARGET_WASI
return SocketError.SocketError;
#else
throw new Exception("ErrNo: " + Interop.Sys.GetErrNo());
#endif
default:
Debug.Fail($"Unexpected error: {error}");
return SocketError.SocketError;
Expand Down Expand Up @@ -146,6 +152,7 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses,

public static unsafe string? TryGetNameInfo(IPAddress addr, out SocketError socketError, out int nativeErrorCode)
{
#if !TARGET_WASI
byte* buffer = stackalloc byte[Interop.Sys.NI_MAXHOST + 1 /*for null*/];

byte isIPv6;
Expand Down Expand Up @@ -178,6 +185,9 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses,
socketError = GetSocketErrorForNativeError(error);
nativeErrorCode = error;
return socketError == SocketError.Success ? Marshal.PtrToStringUTF8((IntPtr)buffer) : null;
#else
throw new PlatformNotSupportedException();
#endif
}

public static string GetHostName() => Interop.Sys.GetHostName();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.Versioning;

namespace System.Net
{
#pragma warning disable IDE0060
#pragma warning disable CA1822
internal sealed class NameResolutionTelemetry : EventSource
{
public static readonly NameResolutionTelemetry Log = new NameResolutionTelemetry();

[NonEvent]
public static bool AnyDiagnosticsEnabled()
{
return false;
}

[NonEvent]
public NameResolutionActivity BeforeResolution(object hostNameOrAddress, long startingTimestamp = 0)
{
return default;
}

[NonEvent]
public void AfterResolution(object hostNameOrAddress, in NameResolutionActivity activity, object? answer, Exception? exception = null)
{
}
}

internal readonly struct NameResolutionActivity
{
public static bool IsTracingEnabled()
{
return false;
}
}
}
Loading
Loading