private static unsafe void GetAddressInfoExCallback([In] int error, [In] int bytes, [In] NativeOverlapped *overlapped) { // Can be casted directly to GetAddrInfoExContext* because the overlapped is its first field GetAddrInfoExContext *context = (GetAddrInfoExContext *)overlapped; ProcessResult((SocketError)error, context); }
public static unsafe void GetAddrInfoAsync(DnsResolveAsyncResult asyncResult) { GetAddrInfoExContext *context = GetAddrInfoExContext.AllocateContext(); try { var state = new GetAddrInfoExState(asyncResult); context->QueryStateHandle = state.CreateHandle(); } catch { GetAddrInfoExContext.FreeContext(context); throw; } AddressInfoEx hints = new AddressInfoEx(); hints.ai_flags = AddressInfoHints.AI_CANONNAME; hints.ai_family = AddressFamily.Unspecified; // Gets all address families SocketError errorCode = (SocketError)Interop.Winsock.GetAddrInfoExW(asyncResult.HostName, null, 0 /* NS_ALL*/, IntPtr.Zero, ref hints, out context->Result, IntPtr.Zero, ref context->Overlapped, s_getAddrInfoExCallback, out context->CancelHandle); if (errorCode != SocketError.IOPending) { ProcessResult(errorCode, context); } }
public static void FreeContext(GetAddrInfoExContext *context) { if (context->Result != null) { Interop.Winsock.FreeAddrInfoExW(context->Result); } Marshal.FreeHGlobal((IntPtr)context); }
public CancellationToken UnregisterAndGetCancellationToken() { lock (this) { _cancellationContext = null; _cancellationRegistration.Unregister(); } return(_cancellationRegistration.Token); }
public GetAddrInfoExState(GetAddrInfoExContext *context, string hostName, bool justAddresses) { _cancellationContext = context; HostName = hostName; JustAddresses = justAddresses; if (justAddresses) { IPAddressArrayBuilder = AsyncTaskMethodBuilder <IPAddress[]> .Create(); _ = IPAddressArrayBuilder.Task; // force initialization } else { IPHostEntryBuilder = AsyncTaskMethodBuilder <IPHostEntry> .Create(); _ = IPHostEntryBuilder.Task; // force initialization } }
public void RegisterForCancellation(CancellationToken cancellationToken) { if (!cancellationToken.CanBeCanceled) { return; } lock (this) { if (_cancellationContext == null) { // The operation completed before registration could be done. return; } _cancellationRegistration = cancellationToken.UnsafeRegister(o => { var @this = (GetAddrInfoExState)o !; int cancelResult = 0; lock (@this) { GetAddrInfoExContext *context = @this._cancellationContext; if (context != null) { // An outstanding operation will be completed with WSA_E_CANCELLED, and GetAddrInfoExCancel will return NO_ERROR. // If this thread has lost the race between cancellation and completion, this will be a NOP // with GetAddrInfoExCancel returning WSA_INVALID_HANDLE. cancelResult = Interop.Winsock.GetAddrInfoExCancel(&context->CancelHandle); } } if (cancelResult != 0 && cancelResult != Interop.Winsock.WSA_INVALID_HANDLE && NetEventSource.Log.IsEnabled()) { NetEventSource.Info(@this, $"GetAddrInfoExCancel returned error {cancelResult}"); } }, this); } }
public GetAddrInfoExState(string hostName, bool justAddresses) : base(true) { HostName = hostName; JustAddresses = justAddresses; if (justAddresses) { IPAddressArrayBuilder = AsyncTaskMethodBuilder <IPAddress[]> .Create(); _ = IPAddressArrayBuilder.Task; // force initialization } else { IPHostEntryBuilder = AsyncTaskMethodBuilder <IPHostEntry> .Create(); _ = IPHostEntryBuilder.Task; // force initialization } GetAddrInfoExContext *context = GetAddrInfoExContext.AllocateContext(); context->QueryStateHandle = CreateHandle(); SetHandle((IntPtr)context); }
private static unsafe void ProcessResult(SocketError errorCode, GetAddrInfoExContext *context) { try { GetAddrInfoExState state = GetAddrInfoExState.FromHandleAndFree(context->QueryStateHandle); if (errorCode != SocketError.Success) { state.CompleteAsyncResult(new SocketException((int)errorCode)); return; } AddressInfoEx *result = context->Result; string canonicalName = null; List <IPAddress> addresses = new List <IPAddress>(); while (result != null) { if (canonicalName == null && result->ai_canonname != IntPtr.Zero) { canonicalName = Marshal.PtrToStringUni(result->ai_canonname); } var socketAddress = new ReadOnlySpan <byte>(result->ai_addr, result->ai_addrlen); if (result->ai_family == AddressFamily.InterNetwork) { if (socketAddress.Length == SocketAddressPal.IPv4AddressSize) { addresses.Add(CreateIPv4Address(socketAddress)); } } else if (SocketProtocolSupportPal.OSSupportsIPv6 && result->ai_family == AddressFamily.InterNetworkV6) { if (socketAddress.Length == SocketAddressPal.IPv6AddressSize) { addresses.Add(CreateIPv6Address(socketAddress)); } } result = result->ai_next; } if (canonicalName == null) { canonicalName = state.HostName; } state.CompleteAsyncResult(new IPHostEntry { HostName = canonicalName, Aliases = Array.Empty <string>(), AddressList = addresses.ToArray() }); } finally { GetAddrInfoExContext.FreeContext(context); } }