Skip to content

Commit a833cfb

Browse files
[WASI] System.Net.NameResolution (#107351)
Co-authored-by: Alexander Köplinger <[email protected]>
1 parent 122eb75 commit a833cfb

28 files changed

+352
-504
lines changed

src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ internal static partial class Sys
1414

1515
internal static unsafe string GetHostName()
1616
{
17+
if (OperatingSystem.IsWasi())
18+
{
19+
return "localhost";
20+
}
21+
1722
const int HOST_NAME_MAX = 255;
1823
const int ArrLength = HOST_NAME_MAX + 1;
1924

src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal enum GetAddrInfoErrorFlags : int
2121
EAI_BADARG = 6, // One or more input arguments were invalid.
2222
EAI_NOMORE = 7, // No more entries are present in the list.
2323
EAI_MEMORY = 8, // Out of memory.
24+
EAI_SYSTEM = 9, // Other system error; errno is set to indicate the error.
2425
}
2526

2627
[StructLayout(LayoutKind.Sequential)]

src/libraries/System.Net.NameResolution/Directory.Build.props

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<PropertyGroup>
44
<StrongNameKeyId>Microsoft</StrongNameKeyId>
55
<IncludePlatformAttributes>true</IncludePlatformAttributes>
6-
<!-- WASI until https://github.com/dotnet/runtime/issues/98957 -->
7-
<UnsupportedOSPlatforms>browser;wasi</UnsupportedOSPlatforms>
6+
<UnsupportedOSPlatforms>browser</UnsupportedOSPlatforms>
87
</PropertyGroup>
98
</Project>

src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
1010
<PropertyGroup>
1111
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
12-
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi' or '$(TargetPlatformIdentifier)' == ''">SR.SystemNetNameResolution_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
13-
<ApiExclusionListPath Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi'">ExcludeApiList.PNSE.Browser.txt</ApiExclusionListPath>
12+
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == ''">SR.SystemNetNameResolution_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
13+
<ApiExclusionListPath Condition="'$(TargetPlatformIdentifier)' == 'browser'">ExcludeApiList.PNSE.Browser.txt</ApiExclusionListPath>
1414
</PropertyGroup>
1515

1616
<ItemGroup Condition="'$(GeneratePlatformNotSupportedAssemblyMessage)' == ''">
1717
<Compile Include="System\Net\Dns.cs" />
1818
<Compile Include="System\Net\IPHostEntry.cs" />
19-
<Compile Include="System\Net\NetEventSource.NameResolution.cs" />
19+
<Compile Include="System\Net\NetEventSource.NameResolution.cs" Condition="'$(TargetPlatformIdentifier)' != 'wasi'" />
2020
<Compile Include="System\Net\NameResolutionMetrics.cs" />
2121
<Compile Include="System\Net\NameResolutionTelemetry.cs" />
2222
<!-- Logging -->
@@ -80,6 +80,8 @@
8080
Link="Common\Interop\CoreLib\Unix\Interop.Errors.cs" />
8181
<Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
8282
Link="Common\Interop\Unix\Interop.Libraries.cs" />
83+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.ErrNo.cs"
84+
Link="Common\Interop\Unix\System.Native\Interop.ErrNo.cs"/>
8385
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Close.cs"
8486
Link="Common\Interop\Unix\System.Native\Interop.Close.cs" />
8587
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetHostName.cs"
@@ -96,10 +98,41 @@
9698
Link="Common\Interop\Unix\System.Native\Interop.SocketAddress.cs" />
9799
</ItemGroup>
98100

99-
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'wasi'">
101+
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'browser'">
100102
<Compile Include="System\Net\Dns.Browser.cs" />
101103
</ItemGroup>
102104

105+
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'wasi'">
106+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetHostName.cs"
107+
Link="Common\Interop\Unix\System.Native\Interop.GetHostName.cs" />
108+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.ErrNo.cs"
109+
Link="Common\Interop\Unix\System.Native\Interop.ErrNo.cs"/>
110+
111+
<Compile Include="System\Net\NameResolutionPal.Unix.cs" />
112+
<Compile Include="$(CommonPath)System\Net\InteropIPAddressExtensions.Unix.cs"
113+
Link="Common\System\Net\InteropIPAddressExtensions.Unix.cs" />
114+
<Compile Include="$(CommonPath)System\Net\SocketAddressPal.Unix.cs"
115+
Link="Common\System\Net\Internals\SocketAddressPal.Unix.cs" />
116+
<Compile Include="$(CommonPath)System\Net\SocketProtocolSupportPal.Unix.cs"
117+
Link="Common\System\Net\SocketProtocolSupportPal.Unix" />
118+
<Compile Include="$(CommonPath)Interop\Unix\Interop.Errors.cs"
119+
Link="Common\Interop\CoreLib\Unix\Interop.Errors.cs" />
120+
<Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
121+
Link="Common\Interop\Unix\Interop.Libraries.cs" />
122+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Close.cs"
123+
Link="Common\Interop\Unix\System.Native\Interop.Close.cs" />
124+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetNameInfo.cs"
125+
Link="Common\Interop\Unix\System.Native\Interop.GetNameInfo.cs" />
126+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.HostEntry.cs"
127+
Link="Common\Interop\Unix\System.Native\Interop.HostEntries.cs" />
128+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.IPAddress.cs"
129+
Link="Common\Interop\Unix\System.Native\Interop.IPAddress.cs" />
130+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Socket.cs"
131+
Link="Common\Interop\Unix\System.Native\Interop.Socket.cs" />
132+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.SocketAddress.cs"
133+
Link="Common\Interop\Unix\System.Native\Interop.SocketAddress.cs" />
134+
</ItemGroup>
135+
103136
<ItemGroup>
104137
<Reference Include="Microsoft.Win32.Primitives" />
105138
<Reference Include="System.Collections" />

src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Net.Sockets;
88
using System.Threading;
99
using System.Threading.Tasks;
10+
using System.Runtime.Versioning;
1011

1112
namespace System.Net
1213
{
@@ -37,6 +38,8 @@ public static string GetHostName()
3738

3839
public static IPHostEntry GetHostEntry(IPAddress address)
3940
{
41+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
42+
4043
ArgumentNullException.ThrowIfNull(address);
4144

4245
if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
@@ -68,7 +71,7 @@ public static IPHostEntry GetHostEntry(string hostNameOrAddress, AddressFamily f
6871

6972
// See if it's an IP Address.
7073
IPHostEntry ipHostEntry;
71-
if (IPAddress.TryParse(hostNameOrAddress, out IPAddress? address))
74+
if (NameResolutionPal.SupportsGetNameInfo && IPAddress.TryParse(hostNameOrAddress, out IPAddress? address))
7275
{
7376
if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
7477
{
@@ -147,6 +150,8 @@ public static Task<IPHostEntry> GetHostEntryAsync(string hostNameOrAddress, Addr
147150

148151
public static Task<IPHostEntry> GetHostEntryAsync(IPAddress address)
149152
{
153+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
154+
150155
ArgumentNullException.ThrowIfNull(address);
151156

152157
if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
@@ -156,6 +161,8 @@ public static Task<IPHostEntry> GetHostEntryAsync(IPAddress address)
156161
}
157162

158163
return RunAsync(static (s, activity) => {
164+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
165+
159166
IPHostEntry ipHostEntry = GetHostEntryCore((IPAddress)s, AddressFamily.Unspecified, activity);
160167
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info((IPAddress)s, $"{ipHostEntry} with {ipHostEntry.AddressList.Length} entries");
161168
return ipHostEntry;
@@ -170,6 +177,8 @@ public static IAsyncResult BeginGetHostEntry(string hostNameOrAddress, AsyncCall
170177

171178
public static IPHostEntry EndGetHostEntry(IAsyncResult asyncResult)
172179
{
180+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
181+
173182
ArgumentNullException.ThrowIfNull(asyncResult);
174183

175184
return TaskToAsyncResult.End<IPHostEntry>(asyncResult);
@@ -244,6 +253,8 @@ public static IAsyncResult BeginGetHostAddresses(string hostNameOrAddress, Async
244253

245254
public static IPAddress[] EndGetHostAddresses(IAsyncResult asyncResult)
246255
{
256+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
257+
247258
ArgumentNullException.ThrowIfNull(asyncResult);
248259

249260
return TaskToAsyncResult.End<IPAddress[]>(asyncResult);
@@ -269,6 +280,8 @@ public static IAsyncResult BeginGetHostByName(string hostName, AsyncCallback? re
269280
[Obsolete("EndGetHostByName has been deprecated. Use EndGetHostEntry instead.")]
270281
public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
271282
{
283+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
284+
272285
ArgumentNullException.ThrowIfNull(asyncResult);
273286

274287
return TaskToAsyncResult.End<IPHostEntry>(asyncResult);
@@ -277,6 +290,8 @@ public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
277290
[Obsolete("GetHostByAddress has been deprecated. Use GetHostEntry instead.")]
278291
public static IPHostEntry GetHostByAddress(string address)
279292
{
293+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
294+
280295
ArgumentNullException.ThrowIfNull(address);
281296

282297
IPHostEntry ipHostEntry = GetHostEntryCore(IPAddress.Parse(address), AddressFamily.Unspecified);
@@ -288,6 +303,8 @@ public static IPHostEntry GetHostByAddress(string address)
288303
[Obsolete("GetHostByAddress has been deprecated. Use GetHostEntry instead.")]
289304
public static IPHostEntry GetHostByAddress(IPAddress address)
290305
{
306+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
307+
291308
ArgumentNullException.ThrowIfNull(address);
292309

293310
IPHostEntry ipHostEntry = GetHostEntryCore(address, AddressFamily.Unspecified);
@@ -303,7 +320,7 @@ public static IPHostEntry Resolve(string hostName)
303320

304321
// See if it's an IP Address.
305322
IPHostEntry ipHostEntry;
306-
if (IPAddress.TryParse(hostName, out IPAddress? address) &&
323+
if (NameResolutionPal.SupportsGetNameInfo && IPAddress.TryParse(hostName, out IPAddress? address) &&
307324
(address.AddressFamily != AddressFamily.InterNetworkV6 || SocketProtocolSupportPal.OSSupportsIPv6))
308325
{
309326
try
@@ -332,6 +349,8 @@ public static IAsyncResult BeginResolve(string hostName, AsyncCallback? requestC
332349
[Obsolete("EndResolve has been deprecated. Use EndGetHostEntry instead.")]
333350
public static IPHostEntry EndResolve(IAsyncResult asyncResult)
334351
{
352+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
353+
335354
IPHostEntry ipHostEntry;
336355

337356
try
@@ -414,6 +433,8 @@ private static IPAddress[] GetHostAddressesCore(IPAddress address, AddressFamily
414433
// Does internal IPAddress reverse and then forward lookups (for Legacy and current public methods).
415434
private static object GetHostEntryOrAddressesCore(IPAddress address, bool justAddresses, AddressFamily addressFamily, NameResolutionActivity? activityOrDefault = default)
416435
{
436+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
437+
417438
// Try to get the data for the host from its address.
418439
// We need to call getnameinfo first, because getaddrinfo w/ the ipaddress string
419440
// will only return that address and not the full list.
@@ -500,7 +521,7 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
500521
object asyncState;
501522

502523
// See if it's an IP Address.
503-
if (IPAddress.TryParse(hostName, out IPAddress? ipAddress))
524+
if (NameResolutionPal.SupportsGetNameInfo && IPAddress.TryParse(hostName, out IPAddress? ipAddress))
504525
{
505526
if (throwOnIIPAny && (ipAddress.Equals(IPAddress.Any) || ipAddress.Equals(IPAddress.IPv6Any)))
506527
{

src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
using System.Text;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using System.Runtime.Versioning;
1112

1213
namespace System.Net
1314
{
1415
internal static partial class NameResolutionPal
1516
{
1617
public const bool SupportsGetAddrInfoAsync = false;
1718

19+
[UnsupportedOSPlatformGuard("wasi")]
20+
public static bool SupportsGetNameInfo => !OperatingSystem.IsWasi();
21+
1822
#pragma warning disable IDE0060
1923
internal static Task? GetAddrInfoAsync(string hostName, bool justAddresses, AddressFamily family, CancellationToken cancellationToken) =>
2024
throw new NotSupportedException();
@@ -39,6 +43,9 @@ private static SocketError GetSocketErrorForNativeError(int error)
3943
return SocketError.HostNotFound;
4044
case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_MEMORY:
4145
throw new OutOfMemoryException();
46+
case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_SYSTEM:
47+
Debug.Fail($"Unexpected error: {error} errno: {Interop.Sys.GetErrNo()}");
48+
return SocketError.SocketError;
4249
default:
4350
Debug.Fail($"Unexpected error: {error}");
4451
return SocketError.SocketError;
@@ -146,6 +153,8 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses,
146153

147154
public static unsafe string? TryGetNameInfo(IPAddress addr, out SocketError socketError, out int nativeErrorCode)
148155
{
156+
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
157+
149158
byte* buffer = stackalloc byte[Interop.Sys.NI_MAXHOST + 1 /*for null*/];
150159

151160
byte isIPv6;

src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Windows.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading;
1010
using System.Threading.Tasks;
1111
using Microsoft.Win32.SafeHandles;
12+
using System.Runtime.Versioning;
1213

1314
namespace System.Net
1415
{
@@ -43,6 +44,8 @@ static void Initialize()
4344
}
4445
}
4546

47+
public const bool SupportsGetNameInfo = true;
48+
4649
public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, AddressFamily addressFamily, out string? hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode)
4750
{
4851
Interop.Winsock.EnsureInitialized();

src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ protected override void OnEventCommand(EventCommandEventArgs command)
5959
private void ResolutionFailed() => WriteEvent(ResolutionFailedEventId);
6060

6161
[NonEvent]
62-
public static bool AnyDiagnosticsEnabled() => Log.IsEnabled() || NameResolutionMetrics.IsEnabled() || NameResolutionActivity.IsTracingEnabled();
62+
public static bool AnyDiagnosticsEnabled() => !OperatingSystem.IsWasi() && (Log.IsEnabled() || NameResolutionMetrics.IsEnabled() || NameResolutionActivity.IsTracingEnabled());
6363

6464
[NonEvent]
6565
public NameResolutionActivity BeforeResolution(object hostNameOrAddress, long startingTimestamp = 0)
@@ -91,6 +91,8 @@ public NameResolutionActivity BeforeResolution(object hostNameOrAddress, long st
9191
[NonEvent]
9292
public void AfterResolution(object hostNameOrAddress, in NameResolutionActivity activity, object? answer, Exception? exception = null)
9393
{
94+
if (OperatingSystem.IsWasi()) return;
95+
9496
if (!activity.Stop(answer, exception, out TimeSpan duration))
9597
{
9698
// We stopped the System.Diagnostics.Activity at this point and neither metrics nor EventSource is enabled.

src/libraries/System.Net.NameResolution/tests/FunctionalTests/GetHostAddressesTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ public async Task Dns_GetHostAddressesAsync_NullHost_Fail()
6969
await Assert.ThrowsAsync<ArgumentNullException>(() => Dns.GetHostAddressesAsync(null));
7070
}
7171

72-
[Fact]
72+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
7373
public void DnsBeginGetHostAddresses_BadName_Throws()
7474
{
7575
IAsyncResult asyncObject = Dns.BeginGetHostAddresses("BadName", null, null);
7676
Assert.ThrowsAny<SocketException>(() => Dns.EndGetHostAddresses(asyncObject));
7777
}
7878

79-
[Fact]
79+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
8080
public void DnsBeginGetHostAddresses_BadIpString_ReturnsAddress()
8181
{
8282
IAsyncResult asyncObject = Dns.BeginGetHostAddresses("0.0.1.1", null, null);
@@ -86,7 +86,7 @@ public void DnsBeginGetHostAddresses_BadIpString_ReturnsAddress()
8686
Assert.Equal(IPAddress.Parse("0.0.1.1"), results[0]);
8787
}
8888

89-
[Fact]
89+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
9090
public void DnsBeginGetHostAddresses_MachineName_MatchesGetHostAddresses()
9191
{
9292
IAsyncResult asyncObject = Dns.BeginGetHostAddresses(TestSettings.LocalHost, null, null);

src/libraries/System.Net.NameResolution/tests/FunctionalTests/GetHostByAddressTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace System.Net.NameResolution.Tests
1010
{
11+
[SkipOnPlatform(TestPlatforms.Wasi, "WASI has no getnameinfo")]
1112
public class GetHostByAddressTest
1213
{
1314
[Fact]

0 commit comments

Comments
 (0)