// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Win32.SafeHandles;
-
using System.Collections.Generic;
using System.Net.Sockets;
using System.Runtime.InteropServices;
-using System.Threading;
using System.Threading.Tasks;
namespace System.Net.NetworkInformation
{
- internal class SystemIPGlobalProperties : IPGlobalProperties
+ internal sealed class SystemIPGlobalProperties : IPGlobalProperties
{
internal SystemIPGlobalProperties()
{
return new SystemIcmpV6Statistics();
}
- public override IAsyncResult BeginGetUnicastAddresses(AsyncCallback? callback, object? state)
- {
- ContextAwareResult asyncResult = new ContextAwareResult(false, false, this, state, callback);
- asyncResult.StartPostingAsyncOp(false);
- if (TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(StableUnicastAddressTableCallback, asyncResult))
- {
- asyncResult.InvokeCallback();
- }
-
- asyncResult.FinishPostingAsyncOp();
-
- return asyncResult;
- }
-
- public override UnicastIPAddressInformationCollection EndGetUnicastAddresses(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- {
- throw new ArgumentNullException(nameof(asyncResult));
- }
-
- ContextAwareResult? result = asyncResult as ContextAwareResult;
- if (result == null || result.AsyncObject == null || result.AsyncObject.GetType() != typeof(SystemIPGlobalProperties))
- {
- throw new ArgumentException(SR.net_io_invalidasyncresult);
- }
-
- if (result.EndCalled)
- {
- throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndGetStableUnicastAddresses"));
- }
-
- result.InternalWaitForCompletion();
-
- result.EndCalled = true;
- return GetUnicastAddressTable();
- }
-
- public override UnicastIPAddressInformationCollection GetUnicastAddresses()
- {
- // Wait for the Address Table to stabilize
- using (ManualResetEvent stable = new ManualResetEvent(false))
- {
- if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(StableUnicastAddressTableCallback, stable))
- {
- stable.WaitOne();
- }
- }
+ public override IAsyncResult BeginGetUnicastAddresses(AsyncCallback? callback, object? state) =>
+ TaskToApm.Begin(GetUnicastAddressesAsync(), callback, state);
- return GetUnicastAddressTable();
- }
+ public override UnicastIPAddressInformationCollection EndGetUnicastAddresses(IAsyncResult asyncResult) =>
+ TaskToApm.End<UnicastIPAddressInformationCollection>(asyncResult);
- public override Task<UnicastIPAddressInformationCollection> GetUnicastAddressesAsync()
- {
- return Task<UnicastIPAddressInformationCollection>.Factory.FromAsync(BeginGetUnicastAddresses, EndGetUnicastAddresses, null);
- }
+ public override UnicastIPAddressInformationCollection GetUnicastAddresses() =>
+ GetUnicastAddressesAsync().GetAwaiter().GetResult();
- private static void StableUnicastAddressTableCallback(object param)
+ public override async Task<UnicastIPAddressInformationCollection> GetUnicastAddressesAsync()
{
- EventWaitHandle? handle = param as EventWaitHandle;
- if (handle != null)
- {
- handle.Set();
- }
- else
+ // Wait for the address table to stabilize.
+ var tcs = new TaskCompletionSource<bool>(TaskContinuationOptions.RunContinuationsAsynchronously);
+ if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
{
- LazyAsyncResult asyncResult = (LazyAsyncResult)param;
- asyncResult.InvokeCallback();
+ await tcs.Task.ConfigureAwait(false);
}
- }
- private static UnicastIPAddressInformationCollection GetUnicastAddressTable()
- {
- UnicastIPAddressInformationCollection rval = new UnicastIPAddressInformationCollection();
+ // Get the address table.
+ var addresses = new UnicastIPAddressInformationCollection();
- NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
- for (int i = 0; i < interfaces.Length; ++i)
+ foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
- UnicastIPAddressInformationCollection addresses = interfaces[i].GetIPProperties().UnicastAddresses;
-
- foreach (UnicastIPAddressInformation address in addresses)
+ foreach (UnicastIPAddressInformation address in ni.GetIPProperties().UnicastAddresses)
{
- if (!rval.Contains(address))
+ if (!addresses.Contains(address))
{
- rval.InternalAdd(address);
+ addresses.InternalAdd(address);
}
}
}
- return rval;
+ return addresses;
}
}
}