Skip to content

Commit b0be1ab

Browse files
authored
Add cancellable and AddressFamily-specific name resolution. (#33420)
Add AddressFamily-specific name resolution and cancellation support for Windows. Resolves #939
1 parent 2b2955e commit b0be1ab

File tree

14 files changed

+478
-153
lines changed

14 files changed

+478
-153
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal unsafe struct HostEntry
3333
}
3434

3535
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")]
36-
internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entry);
36+
internal static extern unsafe int GetHostEntryForName(string address, System.Net.Sockets.AddressFamily family, HostEntry* entry);
3737

3838
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")]
3939
internal static extern unsafe void FreeHostEntry(HostEntry* entry);

src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoExW.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ internal static partial class Interop
1111
{
1212
internal static partial class Winsock
1313
{
14+
internal const int WSA_INVALID_HANDLE = 6;
15+
internal const int WSA_E_CANCELLED = 10111;
16+
1417
internal const string GetAddrInfoExCancelFunctionName = "GetAddrInfoExCancel";
1518

1619
internal const int NS_ALL = 0;
@@ -28,6 +31,9 @@ internal static extern unsafe int GetAddrInfoExW(
2831
[In] delegate* unmanaged<int, int, NativeOverlapped*, void> lpCompletionRoutine,
2932
[Out] IntPtr* lpNameHandle);
3033

34+
[DllImport(Libraries.Ws2_32, ExactSpelling = true)]
35+
internal static extern unsafe int GetAddrInfoExCancel([In] IntPtr* lpHandle);
36+
3137
[DllImport(Libraries.Ws2_32, ExactSpelling = true)]
3238
internal static extern unsafe void FreeAddrInfoExW(AddressInfoEx* pAddrInfo);
3339

src/libraries/Native/Unix/System.Native/pal_networking.c

Lines changed: 82 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,80 @@ c_static_assert(offsetof(IOVector, Count) == offsetof(iovec, iov_len));
170170

171171
#define Min(left,right) (((left) < (right)) ? (left) : (right))
172172

173+
static bool TryConvertAddressFamilyPlatformToPal(sa_family_t platformAddressFamily, int32_t* palAddressFamily)
174+
{
175+
assert(palAddressFamily != NULL);
176+
177+
switch (platformAddressFamily)
178+
{
179+
case AF_UNSPEC:
180+
*palAddressFamily = AddressFamily_AF_UNSPEC;
181+
return true;
182+
183+
case AF_UNIX:
184+
*palAddressFamily = AddressFamily_AF_UNIX;
185+
return true;
186+
187+
case AF_INET:
188+
*palAddressFamily = AddressFamily_AF_INET;
189+
return true;
190+
191+
case AF_INET6:
192+
*palAddressFamily = AddressFamily_AF_INET6;
193+
return true;
194+
#ifdef AF_PACKET
195+
case AF_PACKET:
196+
*palAddressFamily = AddressFamily_AF_PACKET;
197+
return true;
198+
#endif
199+
#ifdef AF_CAN
200+
case AF_CAN:
201+
*palAddressFamily = AddressFamily_AF_CAN;
202+
return true;
203+
#endif
204+
default:
205+
*palAddressFamily = platformAddressFamily;
206+
return false;
207+
}
208+
}
209+
210+
static bool TryConvertAddressFamilyPalToPlatform(int32_t palAddressFamily, sa_family_t* platformAddressFamily)
211+
{
212+
assert(platformAddressFamily != NULL);
213+
214+
switch (palAddressFamily)
215+
{
216+
case AddressFamily_AF_UNSPEC:
217+
*platformAddressFamily = AF_UNSPEC;
218+
return true;
219+
220+
case AddressFamily_AF_UNIX:
221+
*platformAddressFamily = AF_UNIX;
222+
return true;
223+
224+
case AddressFamily_AF_INET:
225+
*platformAddressFamily = AF_INET;
226+
return true;
227+
228+
case AddressFamily_AF_INET6:
229+
*platformAddressFamily = AF_INET6;
230+
return true;
231+
#ifdef AF_PACKET
232+
case AddressFamily_AF_PACKET:
233+
*platformAddressFamily = AF_PACKET;
234+
return true;
235+
#endif
236+
#ifdef AF_CAN
237+
case AddressFamily_AF_CAN:
238+
*platformAddressFamily = AF_CAN;
239+
return true;
240+
#endif
241+
default:
242+
*platformAddressFamily = (sa_family_t)palAddressFamily;
243+
return false;
244+
}
245+
}
246+
173247
static void ConvertByteArrayToIn6Addr(struct in6_addr* addr, const uint8_t* buffer, int32_t bufferLength)
174248
{
175249
assert(bufferLength == NUM_BYTES_IN_IPV6_ADDRESS);
@@ -261,7 +335,7 @@ static int32_t CopySockAddrToIPAddress(sockaddr* addr, sa_family_t family, IPAdd
261335
return -1;
262336
}
263337

264-
int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry)
338+
int32_t SystemNative_GetHostEntryForName(const uint8_t* address, int32_t addressFamily, HostEntry* entry)
265339
{
266340
if (address == NULL || entry == NULL)
267341
{
@@ -275,11 +349,16 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr
275349
struct ifaddrs* addrs = NULL;
276350
#endif
277351

278-
// Get all address families and the canonical name
352+
sa_family_t platformFamily;
353+
if (!TryConvertAddressFamilyPalToPlatform(addressFamily, &platformFamily))
354+
{
355+
return GetAddrInfoErrorFlags_EAI_FAMILY;
356+
}
357+
279358
struct addrinfo hint;
280359
memset(&hint, 0, sizeof(struct addrinfo));
281-
hint.ai_family = AF_UNSPEC;
282360
hint.ai_flags = AI_CANONNAME;
361+
hint.ai_family = platformFamily;
283362

284363
int result = getaddrinfo((const char*)address, NULL, &hint, &info);
285364
if (result != 0)
@@ -593,80 +672,6 @@ int32_t SystemNative_GetIPSocketAddressSizes(int32_t* ipv4SocketAddressSize, int
593672
return Error_SUCCESS;
594673
}
595674

596-
static bool TryConvertAddressFamilyPlatformToPal(sa_family_t platformAddressFamily, int32_t* palAddressFamily)
597-
{
598-
assert(palAddressFamily != NULL);
599-
600-
switch (platformAddressFamily)
601-
{
602-
case AF_UNSPEC:
603-
*palAddressFamily = AddressFamily_AF_UNSPEC;
604-
return true;
605-
606-
case AF_UNIX:
607-
*palAddressFamily = AddressFamily_AF_UNIX;
608-
return true;
609-
610-
case AF_INET:
611-
*palAddressFamily = AddressFamily_AF_INET;
612-
return true;
613-
614-
case AF_INET6:
615-
*palAddressFamily = AddressFamily_AF_INET6;
616-
return true;
617-
#ifdef AF_PACKET
618-
case AF_PACKET:
619-
*palAddressFamily = AddressFamily_AF_PACKET;
620-
return true;
621-
#endif
622-
#ifdef AF_CAN
623-
case AF_CAN:
624-
*palAddressFamily = AddressFamily_AF_CAN;
625-
return true;
626-
#endif
627-
default:
628-
*palAddressFamily = platformAddressFamily;
629-
return false;
630-
}
631-
}
632-
633-
static bool TryConvertAddressFamilyPalToPlatform(int32_t palAddressFamily, sa_family_t* platformAddressFamily)
634-
{
635-
assert(platformAddressFamily != NULL);
636-
637-
switch (palAddressFamily)
638-
{
639-
case AddressFamily_AF_UNSPEC:
640-
*platformAddressFamily = AF_UNSPEC;
641-
return true;
642-
643-
case AddressFamily_AF_UNIX:
644-
*platformAddressFamily = AF_UNIX;
645-
return true;
646-
647-
case AddressFamily_AF_INET:
648-
*platformAddressFamily = AF_INET;
649-
return true;
650-
651-
case AddressFamily_AF_INET6:
652-
*platformAddressFamily = AF_INET6;
653-
return true;
654-
#ifdef AF_PACKET
655-
case AddressFamily_AF_PACKET:
656-
*platformAddressFamily = AF_PACKET;
657-
return true;
658-
#endif
659-
#ifdef AF_CAN
660-
case AddressFamily_AF_CAN:
661-
*platformAddressFamily = AF_CAN;
662-
return true;
663-
#endif
664-
default:
665-
*platformAddressFamily = (sa_family_t)palAddressFamily;
666-
return false;
667-
}
668-
}
669-
670675
int32_t SystemNative_GetAddressFamily(const uint8_t* socketAddress, int32_t socketAddressLen, int32_t* addressFamily)
671676
{
672677
if (socketAddress == NULL || addressFamily == NULL || socketAddressLen < 0)

src/libraries/Native/Unix/System.Native/pal_networking.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ typedef struct
301301
uint32_t Padding; // Pad out to 8-byte alignment
302302
} SocketEvent;
303303

304-
PALEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry);
304+
PALEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, int32_t addressFamily, HostEntry* entry);
305305

306306
PALEXPORT void SystemNative_FreeHostEntry(HostEntry* entry);
307307

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private static async Task<HttpResponseMessage> SendWithNtAuthAsync(HttpRequestMe
110110
}
111111
else
112112
{
113-
IPHostEntry result = await Dns.GetHostEntryAsync(authUri.IdnHost).ConfigureAwait(false);
113+
IPHostEntry result = await Dns.GetHostEntryAsync(authUri.IdnHost, cancellationToken).ConfigureAwait(false);
114114
hostName = result.HostName;
115115
}
116116

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public static partial class Dns
2222
[System.ObsoleteAttribute("EndResolve is obsoleted for this type, please use EndGetHostEntry instead. https://go.microsoft.com/fwlink/?linkid=14202")]
2323
public static System.Net.IPHostEntry EndResolve(System.IAsyncResult asyncResult) { throw null; }
2424
public static System.Net.IPAddress[] GetHostAddresses(string hostNameOrAddress) { throw null; }
25+
public static System.Net.IPAddress[] GetHostAddresses(string hostNameOrAddress, System.Net.Sockets.AddressFamily family) { throw null; }
2526
public static System.Threading.Tasks.Task<System.Net.IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress) { throw null; }
27+
public static System.Threading.Tasks.Task<System.Net.IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress, System.Net.Sockets.AddressFamily family, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
28+
public static System.Threading.Tasks.Task<System.Net.IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress, System.Threading.CancellationToken cancellationToken) { throw null; }
2629
[System.ObsoleteAttribute("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. https://go.microsoft.com/fwlink/?linkid=14202")]
2730
public static System.Net.IPHostEntry GetHostByAddress(System.Net.IPAddress address) { throw null; }
2831
[System.ObsoleteAttribute("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. https://go.microsoft.com/fwlink/?linkid=14202")]
@@ -31,8 +34,11 @@ public static partial class Dns
3134
public static System.Net.IPHostEntry GetHostByName(string hostName) { throw null; }
3235
public static System.Net.IPHostEntry GetHostEntry(System.Net.IPAddress address) { throw null; }
3336
public static System.Net.IPHostEntry GetHostEntry(string hostNameOrAddress) { throw null; }
37+
public static System.Net.IPHostEntry GetHostEntry(string hostNameOrAddress, System.Net.Sockets.AddressFamily family) { throw null; }
3438
public static System.Threading.Tasks.Task<System.Net.IPHostEntry> GetHostEntryAsync(System.Net.IPAddress address) { throw null; }
3539
public static System.Threading.Tasks.Task<System.Net.IPHostEntry> GetHostEntryAsync(string hostNameOrAddress) { throw null; }
40+
public static System.Threading.Tasks.Task<System.Net.IPHostEntry> GetHostEntryAsync(string hostNameOrAddress, System.Net.Sockets.AddressFamily family, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
41+
public static System.Threading.Tasks.Task<System.Net.IPHostEntry> GetHostEntryAsync(string hostNameOrAddress, System.Threading.CancellationToken cancellationToken) { throw null; }
3642
public static string GetHostName() { throw null; }
3743
[System.ObsoleteAttribute("Resolve is obsoleted for this type, please use GetHostEntry instead. https://go.microsoft.com/fwlink/?linkid=14202")]
3844
public static System.Net.IPHostEntry Resolve(string hostName) { throw null; }

0 commit comments

Comments
 (0)