From e1098f89476eb4b9db77ca6fa5d92858378a5ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Tue, 23 Feb 2021 21:31:58 +0100 Subject: [PATCH 1/4] Revert "NameResolutionPal.Unix: fixed loss of address family information in async lookup (#47171)" This reverts commit 2f2593177dafbe702407fe0b7ac156a7829b7ee6. --- .../Unix/System.Native/pal_networking.c | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_networking.c b/src/libraries/Native/Unix/System.Native/pal_networking.c index 67d41f9a48d76..5e0f37635d326 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networking.c +++ b/src/libraries/Native/Unix/System.Native/pal_networking.c @@ -601,6 +601,12 @@ int32_t SystemNative_GetHostEntryForNameAsync(const uint8_t* address, int32_t ad return GetAddrInfoErrorFlags_EAI_BADARG; } + sa_family_t platformFamily; + if (!TryConvertAddressFamilyPalToPlatform(addressFamily, &platformFamily)) + { + return GetAddrInfoErrorFlags_EAI_FAMILY; + } + struct GetAddrInfoAsyncState* state = malloc(sizeof(*state) + addrlen + 1); if (state == NULL) @@ -616,22 +622,24 @@ int32_t SystemNative_GetHostEntryForNameAsync(const uint8_t* address, int32_t ad memcpy(state->address, address, addrlen + 1); - state->gai_request = (struct gaicb) { - .ar_name = state->address, - .ar_service = NULL, - .ar_request = &state->hint, - .ar_result = NULL - }; - state->gai_requests = &state->gai_request; - state->sigevent = (struct sigevent) { - .sigev_notify = SIGEV_THREAD, - .sigev_value = { - .sival_ptr = state + *state = (struct GetAddrInfoAsyncState) { + .gai_request = { + .ar_name = state->address, + .ar_service = NULL, + .ar_request = &state->hint, + .ar_result = NULL + }, + .gai_requests = &state->gai_request, + .sigevent = { + .sigev_notify = SIGEV_THREAD, + .sigev_value = { + .sival_ptr = state + }, + .sigev_notify_function = GetHostEntryForNameAsyncComplete }, - .sigev_notify_function = GetHostEntryForNameAsyncComplete + .entry = entry, + .callback = callback }; - state->entry = entry; - state->callback = callback; atomic_thread_fence(memory_order_release); From 57770653c985aaccb255d65fa2fc8a5d023c86d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Tue, 23 Feb 2021 21:43:45 +0100 Subject: [PATCH 2/4] Revert "NameResolutionPal.Unix enabled async name resolution (#34633)" This reverts commit f4ae9059426a942c5172c68ec7e7460178d87cf3. --- .../Unix/System.Native/Interop.HostEntry.cs | 10 - .../Native/Unix/Common/pal_config.h.in | 1 - .../Native/Unix/System.Native/entrypoints.c | 2 - .../Unix/System.Native/extra_libs.cmake | 4 - .../Unix/System.Native/pal_networking.c | 194 ++----------- .../Unix/System.Native/pal_networking.h | 8 - src/libraries/Native/Unix/configure.cmake | 14 - .../src/System/Net/Dns.cs | 2 + .../src/System/Net/NameResolutionPal.Unix.cs | 269 ++++-------------- .../corehost/apphost/static/configure.cmake | 14 - 10 files changed, 79 insertions(+), 439 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 12c2c3941d224..d197637043e8a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -32,19 +32,9 @@ internal unsafe struct HostEntry internal int IPAddressCount; // Number of IP addresses in the list } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PlatformSupportsGetAddrInfoAsync")] - internal static extern bool PlatformSupportsGetAddrInfoAsync(); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] internal static extern unsafe int GetHostEntryForName(string address, AddressFamily family, HostEntry* entry); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForNameAsync")] - internal static extern unsafe int GetHostEntryForNameAsync( - string address, - AddressFamily family, - HostEntry* entry, - delegate* unmanaged callback); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] internal static extern unsafe void FreeHostEntry(HostEntry* entry); } diff --git a/src/libraries/Native/Unix/Common/pal_config.h.in b/src/libraries/Native/Unix/Common/pal_config.h.in index 84196a23d5434..d346596800281 100644 --- a/src/libraries/Native/Unix/Common/pal_config.h.in +++ b/src/libraries/Native/Unix/Common/pal_config.h.in @@ -10,7 +10,6 @@ #cmakedefine01 HAVE_F_FULLFSYNC #cmakedefine01 HAVE_O_CLOEXEC #cmakedefine01 HAVE_GETIFADDRS -#cmakedefine01 HAVE_GETADDRINFO_A #cmakedefine01 HAVE_UTSNAME_DOMAINNAME #cmakedefine01 HAVE_STAT64 #cmakedefine01 HAVE_FORK diff --git a/src/libraries/Native/Unix/System.Native/entrypoints.c b/src/libraries/Native/Unix/System.Native/entrypoints.c index a9f229a0203d1..e425cb3d89c3e 100644 --- a/src/libraries/Native/Unix/System.Native/entrypoints.c +++ b/src/libraries/Native/Unix/System.Native/entrypoints.c @@ -115,9 +115,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_ReadEvents) DllImportEntry(SystemNative_CreateNetworkChangeListenerSocket) DllImportEntry(SystemNative_CloseNetworkChangeListenerSocket) - DllImportEntry(SystemNative_PlatformSupportsGetAddrInfoAsync) DllImportEntry(SystemNative_GetHostEntryForName) - DllImportEntry(SystemNative_GetHostEntryForNameAsync) DllImportEntry(SystemNative_FreeHostEntry) DllImportEntry(SystemNative_GetNameInfo) DllImportEntry(SystemNative_GetDomainName) diff --git a/src/libraries/Native/Unix/System.Native/extra_libs.cmake b/src/libraries/Native/Unix/System.Native/extra_libs.cmake index a8cc4a3bea612..b59bf61488ab8 100644 --- a/src/libraries/Native/Unix/System.Native/extra_libs.cmake +++ b/src/libraries/Native/Unix/System.Native/extra_libs.cmake @@ -13,8 +13,4 @@ macro(append_extra_system_libs NativeLibsExtra) if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) list(APPEND ${NativeLibsExtra} "-framework Foundation") endif () - - if (CLR_CMAKE_TARGET_LINUX AND HAVE_GETADDRINFO_A) - list(APPEND ${NativeLibsExtra} anl) - endif () endmacro() diff --git a/src/libraries/Native/Unix/System.Native/pal_networking.c b/src/libraries/Native/Unix/System.Native/pal_networking.c index 5e0f37635d326..2e819aaa5c455 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networking.c +++ b/src/libraries/Native/Unix/System.Native/pal_networking.c @@ -60,10 +60,6 @@ #if HAVE_LINUX_CAN_H #include #endif -#if HAVE_GETADDRINFO_A -#include -#include -#endif #if HAVE_SYS_FILIO_H #include #endif @@ -339,14 +335,37 @@ static int32_t CopySockAddrToIPAddress(sockaddr* addr, sa_family_t family, IPAdd return -1; } -static int32_t GetHostEntries(const uint8_t* address, struct addrinfo* info, HostEntry* entry) +int32_t SystemNative_GetHostEntryForName(const uint8_t* address, int32_t addressFamily, HostEntry* entry) { + if (address == NULL || entry == NULL) + { + return GetAddrInfoErrorFlags_EAI_BADARG; + } + int32_t ret = GetAddrInfoErrorFlags_EAI_SUCCESS; + struct addrinfo* info = NULL; #if HAVE_GETIFADDRS struct ifaddrs* addrs = NULL; #endif + sa_family_t platformFamily; + if (!TryConvertAddressFamilyPalToPlatform(addressFamily, &platformFamily)) + { + return GetAddrInfoErrorFlags_EAI_FAMILY; + } + + struct addrinfo hint; + memset(&hint, 0, sizeof(struct addrinfo)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = platformFamily; + + int result = getaddrinfo((const char*)address, NULL, &hint, &info); + if (result != 0) + { + return ConvertGetAddrInfoAndGetNameInfoErrorsToPal(result); + } + entry->CanonicalName = NULL; entry->Aliases = NULL; entry->IPAddressList = NULL; @@ -374,8 +393,7 @@ static int32_t GetHostEntries(const uint8_t* address, struct addrinfo* info, Hos #if HAVE_GETIFADDRS char name[_POSIX_HOST_NAME_MAX]; - - int result = gethostname((char*)name, _POSIX_HOST_NAME_MAX); + result = gethostname((char*)name, _POSIX_HOST_NAME_MAX); bool includeIPv4Loopback = true; bool includeIPv6Loopback = true; @@ -425,8 +443,6 @@ static int32_t GetHostEntries(const uint8_t* address, struct addrinfo* info, Hos } } } -#else - (void)address; #endif if (entry->IPAddressCount > 0) @@ -503,166 +519,6 @@ static int32_t GetHostEntries(const uint8_t* address, struct addrinfo* info, Hos return ret; } -#if HAVE_GETADDRINFO_A -struct GetAddrInfoAsyncState -{ - struct gaicb gai_request; - struct gaicb* gai_requests; - struct sigevent sigevent; - - struct addrinfo hint; - HostEntry* entry; - GetHostEntryForNameCallback callback; - char address[]; -}; - -static void GetHostEntryForNameAsyncComplete(sigval_t context) -{ - struct GetAddrInfoAsyncState* state = (struct GetAddrInfoAsyncState*)context.sival_ptr; - - atomic_thread_fence(memory_order_acquire); - - GetHostEntryForNameCallback callback = state->callback; - - int ret = ConvertGetAddrInfoAndGetNameInfoErrorsToPal(gai_error(&state->gai_request)); - - if (ret == 0) - { - const uint8_t* address = (const uint8_t*)state->address; - struct addrinfo* info = state->gai_request.ar_result; - - ret = GetHostEntries(address, info, state->entry); - } - - assert(callback != NULL); - callback(state->entry, ret); - - free(state); -} -#endif - -static bool TrySetAddressFamily(int32_t addressFamily, struct addrinfo* hint) -{ - sa_family_t platformFamily; - if (!TryConvertAddressFamilyPalToPlatform(addressFamily, &platformFamily)) - { - return false; - } - - memset(hint, 0, sizeof(struct addrinfo)); - - hint->ai_flags = AI_CANONNAME; - hint->ai_family = platformFamily; - - return true; -} - -int32_t SystemNative_PlatformSupportsGetAddrInfoAsync() -{ - return HAVE_GETADDRINFO_A; -} - -int32_t SystemNative_GetHostEntryForName(const uint8_t* address, int32_t addressFamily, HostEntry* entry) -{ - if (address == NULL || entry == NULL) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - struct addrinfo hint; - if (!TrySetAddressFamily(addressFamily, &hint)) - { - return GetAddrInfoErrorFlags_EAI_FAMILY; - } - - struct addrinfo* info = NULL; - - int result = getaddrinfo((const char*)address, NULL, &hint, &info); - if (result != 0) - { - return ConvertGetAddrInfoAndGetNameInfoErrorsToPal(result); - } - - return GetHostEntries(address, info, entry); -} - -int32_t SystemNative_GetHostEntryForNameAsync(const uint8_t* address, int32_t addressFamily, HostEntry* entry, GetHostEntryForNameCallback callback) -{ -#if HAVE_GETADDRINFO_A - if (address == NULL || entry == NULL) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - size_t addrlen = strlen((const char*)address); - - if (addrlen > _POSIX_HOST_NAME_MAX) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - sa_family_t platformFamily; - if (!TryConvertAddressFamilyPalToPlatform(addressFamily, &platformFamily)) - { - return GetAddrInfoErrorFlags_EAI_FAMILY; - } - - struct GetAddrInfoAsyncState* state = malloc(sizeof(*state) + addrlen + 1); - - if (state == NULL) - { - return GetAddrInfoErrorFlags_EAI_MEMORY; - } - - if (!TrySetAddressFamily(addressFamily, &state->hint)) - { - free(state); - return GetAddrInfoErrorFlags_EAI_FAMILY; - } - - memcpy(state->address, address, addrlen + 1); - - *state = (struct GetAddrInfoAsyncState) { - .gai_request = { - .ar_name = state->address, - .ar_service = NULL, - .ar_request = &state->hint, - .ar_result = NULL - }, - .gai_requests = &state->gai_request, - .sigevent = { - .sigev_notify = SIGEV_THREAD, - .sigev_value = { - .sival_ptr = state - }, - .sigev_notify_function = GetHostEntryForNameAsyncComplete - }, - .entry = entry, - .callback = callback - }; - - atomic_thread_fence(memory_order_release); - - int32_t result = getaddrinfo_a(GAI_NOWAIT, &state->gai_requests, 1, &state->sigevent); - - if (result != 0) - { - free(state); - return ConvertGetAddrInfoAndGetNameInfoErrorsToPal(result); - } - - return result; -#else - (void)address; - (void)addressFamily; - (void)entry; - (void)callback; - - // GetHostEntryForNameAsync is not supported on this platform. - return -1; -#endif -} - void SystemNative_FreeHostEntry(HostEntry* entry) { if (entry != NULL) diff --git a/src/libraries/Native/Unix/System.Native/pal_networking.h b/src/libraries/Native/Unix/System.Native/pal_networking.h index 69d0d1759bb5d..bbb0bc0785cce 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networking.h +++ b/src/libraries/Native/Unix/System.Native/pal_networking.h @@ -301,16 +301,8 @@ typedef struct uint32_t Padding; // Pad out to 8-byte alignment } SocketEvent; -PALEXPORT int32_t SystemNative_PlatformSupportsGetAddrInfoAsync(void); - PALEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, int32_t addressFamily, HostEntry* entry); -typedef void (*GetHostEntryForNameCallback)(HostEntry* entry, int status); -PALEXPORT int32_t SystemNative_GetHostEntryForNameAsync(const uint8_t* address, - int32_t addressFamily, - HostEntry* entry, - GetHostEntryForNameCallback callback); - PALEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index d06059d5dd527..22e7e515b3479 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -6,7 +6,6 @@ include(CheckPrototypeDefinition) include(CheckStructHasMember) include(CheckSymbolExists) include(CheckTypeSize) -include(CMakePushCheckState) include(CheckLibraryExists) # CMP0075 Include file check macros honor CMAKE_REQUIRED_LIBRARIES. @@ -918,19 +917,6 @@ check_symbol_exists( HAVE_INOTIFY_RM_WATCH) set (CMAKE_REQUIRED_LIBRARIES ${PREVIOUS_CMAKE_REQUIRED_LIBRARIES}) -if (CLR_CMAKE_TARGET_LINUX) - cmake_push_check_state(RESET) - set (CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE") - set (CMAKE_REQUIRED_LIBRARIES "-lanl") - - check_symbol_exists( - getaddrinfo_a - netdb.h - HAVE_GETADDRINFO_A) - - cmake_pop_check_state() -endif () - set (HAVE_INOTIFY 0) if (HAVE_INOTIFY_INIT AND HAVE_INOTIFY_ADD_WATCH AND HAVE_INOTIFY_RM_WATCH) set (HAVE_INOTIFY 1) diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs index 5334e3506f5b5..6e3b2fba6f673 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs @@ -547,6 +547,8 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR { if (NameResolutionPal.SupportsGetAddrInfoAsync) { +#pragma warning disable CS0162 // Unreachable code detected -- SupportsGetAddrInfoAsync is a constant on *nix. + // If the OS supports it and 'hostName' is not an IP Address, resolve the name asynchronously // instead of calling the synchronous version in the ThreadPool. // If it fails, we will fall back to ThreadPool as well. diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index e64924fe04cbb..46858edea5dfa 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -1,11 +1,12 @@ // 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.Net.Internals; using System.Net.Sockets; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -13,145 +14,10 @@ namespace System.Net { internal static partial class NameResolutionPal { - public static bool SupportsGetAddrInfoAsync { get; } = Interop.Sys.PlatformSupportsGetAddrInfoAsync(); + public const bool SupportsGetAddrInfoAsync = false; - public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, AddressFamily addressFamily, out string? hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode) - { - Debug.Assert(name is not null); - - if (name.Length == 0) - { - // To match documented behavior on Windows, if an empty string is passed in, use the local host's name. - name = Dns.GetHostName(); - } - - Interop.Sys.HostEntry entry; - int result = Interop.Sys.GetHostEntryForName(name, addressFamily, &entry); - if (result != 0) - { - nativeErrorCode = result; - hostName = name; - aliases = Array.Empty(); - addresses = Array.Empty(); - return GetSocketErrorForNativeError(result); - } - - ParseHostEntry(entry, justAddresses, out hostName, out aliases, out addresses); - nativeErrorCode = 0; - return SocketError.Success; - } - - public static unsafe string? TryGetNameInfo(IPAddress addr, out SocketError socketError, out int nativeErrorCode) - { - byte* buffer = stackalloc byte[Interop.Sys.NI_MAXHOST + 1 /*for null*/]; - - byte isIPv6; - int rawAddressLength; - if (addr.AddressFamily == AddressFamily.InterNetwork) - { - isIPv6 = 0; - rawAddressLength = IPAddressParserStatics.IPv4AddressBytes; - } - else - { - isIPv6 = 1; - rawAddressLength = IPAddressParserStatics.IPv6AddressBytes; - } - - byte* rawAddress = stackalloc byte[rawAddressLength]; - addr.TryWriteBytes(new Span(rawAddress, rawAddressLength), out int bytesWritten); - Debug.Assert(bytesWritten == rawAddressLength); - - int error = Interop.Sys.GetNameInfo( - rawAddress, - (uint)rawAddressLength, - isIPv6, - buffer, - Interop.Sys.NI_MAXHOST, - null, - 0, - Interop.Sys.GetNameInfoFlags.NI_NAMEREQD); - - socketError = GetSocketErrorForNativeError(error); - nativeErrorCode = error; - return socketError == SocketError.Success ? Marshal.PtrToStringAnsi((IntPtr)buffer) : null; - } - - public static string GetHostName() => Interop.Sys.GetHostName(); - - public static unsafe Task? GetAddrInfoAsync(string hostName, bool justAddresses, AddressFamily addressFamily, CancellationToken _) - { - Debug.Assert(hostName is not null); - - if (hostName.Length == 0) - { - // To match documented behavior on Windows, if an empty string is passed in, use the local host's name. - hostName = Dns.GetHostName(); - } - - GetHostEntryForNameContext* context = GetHostEntryForNameContext.AllocateContext(); - - GetHostEntryForNameState state; - try - { - state = new GetHostEntryForNameState(hostName, justAddresses); - context->State = state.CreateHandle(); - } - catch - { - GetHostEntryForNameContext.FreeContext(context); - throw; - } - - int errorCode = Interop.Sys.GetHostEntryForNameAsync(hostName, addressFamily, &context->Result, &GetHostEntryForNameCallback); - - if (errorCode != 0) - { - ProcessResult(GetSocketErrorForNativeError(errorCode), context); - } - - return state.Task; - } - - [UnmanagedCallersOnly] - private static unsafe void GetHostEntryForNameCallback(Interop.Sys.HostEntry* entry, int error) - { - // Can be casted directly to GetHostEntryForNameContext* because the HostEntry is its first field - GetHostEntryForNameContext* context = (GetHostEntryForNameContext*)entry; - - ProcessResult(GetSocketErrorForNativeError(error), context); - } - - private static unsafe void ProcessResult(SocketError errorCode, GetHostEntryForNameContext* context) - { - try - { - GetHostEntryForNameState state = GetHostEntryForNameState.FromHandleAndFree(context->State); - - if (errorCode == SocketError.Success) - { - ParseHostEntry(context->Result, state.JustAddresses, out string? hostName, out string[] aliases, out IPAddress[] addresses); - - state.SetResult(state.JustAddresses - ? (object)addresses - : new IPHostEntry - { - HostName = hostName ?? state.HostName, - Aliases = aliases, - AddressList = addresses - }); - } - else - { - Exception ex = new SocketException((int)errorCode); - state.SetResult(ExceptionDispatchInfo.SetCurrentStackTrace(ex)); - } - } - finally - { - GetHostEntryForNameContext.FreeContext(context); - } - } + internal static Task? GetAddrInfoAsync(string hostName, bool justAddresses, AddressFamily family, CancellationToken cancellationToken) => + throw new NotSupportedException(); private static SocketError GetSocketErrorForNativeError(int error) { @@ -251,97 +117,66 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool } } - private sealed class GetHostEntryForNameState : IThreadPoolWorkItem + public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, AddressFamily addressFamily, out string? hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode) { - private AsyncTaskMethodBuilder _ipAddressArrayBuilder; - private AsyncTaskMethodBuilder _ipHostEntryBuilder; - private object? _result; - - public string HostName { get; } - public bool JustAddresses { get; } - - public GetHostEntryForNameState(string hostName, bool justAddresses) - { - HostName = hostName; - JustAddresses = justAddresses; - - if (justAddresses) - { - _ipAddressArrayBuilder = AsyncTaskMethodBuilder.Create(); - _ = _ipAddressArrayBuilder.Task; // force initialization - } - else - { - _ipHostEntryBuilder = AsyncTaskMethodBuilder.Create(); - _ = _ipHostEntryBuilder.Task; // force initialization - } - } - - public Task Task => JustAddresses ? _ipAddressArrayBuilder.Task : _ipHostEntryBuilder.Task; - - public void SetResult(object result) + if (name == "") { - // Store the result and then queue this object to the thread pool to actually complete the Tasks, as we - // want to avoid invoking continuations on the OS callback thread. Effectively we're manually - // implementing TaskCreationOptions.RunContinuationsAsynchronously, which we can't use because we're - // using AsyncTaskMethodBuilder, which we're using in order to create either a strongly-typed Task - // or Task without allocating additional objects. - Debug.Assert(result is Exception or IPAddress[] or IPHostEntry); - _result = result; - ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: false); + // To match documented behavior on Windows, if an empty string is passed in, use the local host's name. + name = Dns.GetHostName(); } - void IThreadPoolWorkItem.Execute() + Interop.Sys.HostEntry entry; + int result = Interop.Sys.GetHostEntryForName(name, addressFamily, &entry); + if (result != 0) { - if (JustAddresses) - { - if (_result is Exception e) - { - _ipAddressArrayBuilder.SetException(e); - } - else - { - _ipAddressArrayBuilder.SetResult((IPAddress[])_result!); - } - } - else - { - if (_result is Exception e) - { - _ipHostEntryBuilder.SetException(e); - } - else - { - _ipHostEntryBuilder.SetResult((IPHostEntry)_result!); - } - } + nativeErrorCode = result; + hostName = name; + aliases = Array.Empty(); + addresses = Array.Empty(); + return GetSocketErrorForNativeError(result); } - public IntPtr CreateHandle() => GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Normal)); - - public static GetHostEntryForNameState FromHandleAndFree(IntPtr handle) - { - GCHandle gCHandle = GCHandle.FromIntPtr(handle); - var state = (GetHostEntryForNameState)gCHandle.Target!; - gCHandle.Free(); - return state; - } + ParseHostEntry(entry, justAddresses, out hostName, out aliases, out addresses); + nativeErrorCode = 0; + return SocketError.Success; } - [StructLayout(LayoutKind.Sequential)] - private unsafe struct GetHostEntryForNameContext + public static unsafe string? TryGetNameInfo(IPAddress addr, out SocketError socketError, out int nativeErrorCode) { - public Interop.Sys.HostEntry Result; - public IntPtr State; + byte* buffer = stackalloc byte[Interop.Sys.NI_MAXHOST + 1 /*for null*/]; - public static GetHostEntryForNameContext* AllocateContext() + byte isIPv6; + int rawAddressLength; + if (addr.AddressFamily == AddressFamily.InterNetwork) { - GetHostEntryForNameContext* context = (GetHostEntryForNameContext*)Marshal.AllocHGlobal(sizeof(GetHostEntryForNameContext)); - *context = default; - return context; + isIPv6 = 0; + rawAddressLength = IPAddressParserStatics.IPv4AddressBytes; } + else + { + isIPv6 = 1; + rawAddressLength = IPAddressParserStatics.IPv6AddressBytes; + } + + byte* rawAddress = stackalloc byte[rawAddressLength]; + addr.TryWriteBytes(new Span(rawAddress, rawAddressLength), out int bytesWritten); + Debug.Assert(bytesWritten == rawAddressLength); - public static void FreeContext(GetHostEntryForNameContext* context) => Marshal.FreeHGlobal((IntPtr)context); + int error = Interop.Sys.GetNameInfo( + rawAddress, + (uint)rawAddressLength, + isIPv6, + buffer, + Interop.Sys.NI_MAXHOST, + null, + 0, + Interop.Sys.GetNameInfoFlags.NI_NAMEREQD); + + socketError = GetSocketErrorForNativeError(error); + nativeErrorCode = error; + return socketError == SocketError.Success ? Marshal.PtrToStringAnsi((IntPtr)buffer) : null; } + + public static string GetHostName() => Interop.Sys.GetHostName(); } } diff --git a/src/native/corehost/apphost/static/configure.cmake b/src/native/corehost/apphost/static/configure.cmake index fe9e8a06a885f..e3741d7e056a5 100644 --- a/src/native/corehost/apphost/static/configure.cmake +++ b/src/native/corehost/apphost/static/configure.cmake @@ -1,5 +1,4 @@ include(CheckIncludeFiles) -include(CMakePushCheckState) check_include_files( GSS/GSS.h @@ -11,16 +10,3 @@ if (HeimdalGssApi) gssapi/gssapi.h HAVE_HEIMDAL_HEADERS) endif() - -if (CLR_CMAKE_TARGET_LINUX) - cmake_push_check_state(RESET) - set (CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE") - set (CMAKE_REQUIRED_LIBRARIES "-lanl") - - check_symbol_exists( - getaddrinfo_a - netdb.h - HAVE_GETADDRINFO_A) - - cmake_pop_check_state() -endif () From 098e3c99983215f69c409ad785c585954558eb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Tue, 23 Feb 2021 22:52:12 +0100 Subject: [PATCH 3/4] Fixed unreachable code bug SupportsGetAddrInfoAsync is a constant on *nix. Tests check if it's supported and return if not, so unreachable code was created on *nix. --- .../tests/PalTests/NameResolutionPalTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs index d64b7665fa229..dc283db96c231 100644 --- a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs +++ b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs @@ -243,6 +243,8 @@ public void HostName_NotNull() Assert.NotNull(NameResolutionPal.GetHostName()); } +#pragma warning disable CS0162 // Unreachable code detected -- SupportsGetAddrInfoAsync is a constant on *nix. + [Theory] [InlineData(false)] [InlineData(true)] From 8de5e3245a4a0fc02dd52b36615ac89802e002c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sat, 27 Feb 2021 00:31:08 +0100 Subject: [PATCH 4/4] Restored warning CS0162 --- src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs | 1 + .../tests/PalTests/NameResolutionPalTests.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs index 6e3b2fba6f673..869d6091d11c9 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs @@ -573,6 +573,7 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR { return t; } +#pragma warning restore CS0162 } asyncState = family == AddressFamily.Unspecified ? (object)hostName : new KeyValuePair(hostName, family); diff --git a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs index dc283db96c231..65542d3555574 100644 --- a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs +++ b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs @@ -420,6 +420,8 @@ public async Task GetAddrInfoAsync_UnknownHost(bool justAddresses) Assert.Equal(SocketError.HostNotFound, socketError); } +#pragma warning restore CS0162 + [Fact] [PlatformSpecific(TestPlatforms.AnyUnix)] public void Exception_HostNotFound_Success()