2019-12-03 18:44:25 +01:00
|
|
|
|
using Unosquare.Swan.Networking;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Net.NetworkInformation;
|
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Unosquare.Swan {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Provides miscellaneous network utilities such as a Public IP finder,
|
|
|
|
|
/// a DNS client to query DNS records of any kind, and an NTP client.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class Network {
|
2019-02-17 14:08:57 +01:00
|
|
|
|
/// <summary>
|
2019-12-03 18:44:25 +01:00
|
|
|
|
/// The DNS default port.
|
2019-02-17 14:08:57 +01:00
|
|
|
|
/// </summary>
|
2019-12-03 18:44:25 +01:00
|
|
|
|
public const Int32 DnsDefaultPort = 53;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The NTP default port.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const Int32 NtpDefaultPort = 123;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the name of the host.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>
|
|
|
|
|
/// The name of the host.
|
|
|
|
|
/// </value>
|
|
|
|
|
public static String HostName => IPGlobalProperties.GetIPGlobalProperties().HostName;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the name of the network domain.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>
|
|
|
|
|
/// The name of the network domain.
|
|
|
|
|
/// </value>
|
|
|
|
|
public static String DomainName => IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
|
|
|
|
|
|
|
|
|
#region IP Addresses and Adapters Information Methods
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the active IPv4 interfaces.
|
|
|
|
|
/// Only those interfaces with a valid unicast address and a valid gateway will be returned in the collection.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// A collection of NetworkInterface/IPInterfaceProperties pairs
|
|
|
|
|
/// that represents the active IPv4 interfaces.
|
|
|
|
|
/// </returns>
|
|
|
|
|
public static Dictionary<NetworkInterface, IPInterfaceProperties> GetIPv4Interfaces() {
|
|
|
|
|
// zero conf ip address
|
|
|
|
|
IPAddress zeroConf = new IPAddress(0);
|
|
|
|
|
|
|
|
|
|
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces()
|
|
|
|
|
.Where(network =>
|
|
|
|
|
network.OperationalStatus == OperationalStatus.Up
|
|
|
|
|
&& network.NetworkInterfaceType != NetworkInterfaceType.Unknown
|
|
|
|
|
&& network.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
Dictionary<NetworkInterface, IPInterfaceProperties> result = new Dictionary<NetworkInterface, IPInterfaceProperties>();
|
|
|
|
|
|
|
|
|
|
foreach(NetworkInterface adapter in adapters) {
|
|
|
|
|
IPInterfaceProperties properties = adapter.GetIPProperties();
|
|
|
|
|
if(properties == null
|
|
|
|
|
|| properties.GatewayAddresses.Count == 0
|
|
|
|
|
|| properties.GatewayAddresses.All(gateway => Equals(gateway.Address, zeroConf))
|
|
|
|
|
|| properties.UnicastAddresses.Count == 0
|
|
|
|
|
|| properties.GatewayAddresses.All(address => Equals(address.Address, zeroConf))
|
|
|
|
|
|| properties.UnicastAddresses.Any(a => a.Address.AddressFamily == AddressFamily.InterNetwork) ==
|
|
|
|
|
false) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result[adapter] = properties;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieves the local ip addresses.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="includeLoopback">if set to <c>true</c> [include loopback].</param>
|
|
|
|
|
/// <returns>An array of local ip addresses.</returns>
|
|
|
|
|
public static IPAddress[] GetIPv4Addresses(Boolean includeLoopback = true) =>
|
|
|
|
|
GetIPv4Addresses(NetworkInterfaceType.Unknown, true, includeLoopback);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieves the local ip addresses.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="interfaceType">Type of the interface.</param>
|
|
|
|
|
/// <param name="skipTypeFilter">if set to <c>true</c> [skip type filter].</param>
|
|
|
|
|
/// <param name="includeLoopback">if set to <c>true</c> [include loopback].</param>
|
|
|
|
|
/// <returns>An array of local ip addresses.</returns>
|
|
|
|
|
public static IPAddress[] GetIPv4Addresses(
|
|
|
|
|
NetworkInterfaceType interfaceType,
|
|
|
|
|
Boolean skipTypeFilter = false,
|
|
|
|
|
Boolean includeLoopback = false) {
|
|
|
|
|
List<IPAddress> addressList = new List<IPAddress>();
|
|
|
|
|
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
|
|
|
|
.Where(ni =>
|
2019-02-17 14:08:57 +01:00
|
|
|
|
#if NET452
|
2019-12-03 18:44:25 +01:00
|
|
|
|
ni.IsReceiveOnly == false &&
|
2019-02-17 14:08:57 +01:00
|
|
|
|
#endif
|
2019-12-03 18:44:25 +01:00
|
|
|
|
(skipTypeFilter || ni.NetworkInterfaceType == interfaceType) &&
|
|
|
|
|
ni.OperationalStatus == OperationalStatus.Up)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
foreach(NetworkInterface networkInterface in interfaces) {
|
|
|
|
|
IPInterfaceProperties properties = networkInterface.GetIPProperties();
|
|
|
|
|
|
|
|
|
|
if(properties.GatewayAddresses.All(g => g.Address.AddressFamily != AddressFamily.InterNetwork)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addressList.AddRange(properties.UnicastAddresses
|
|
|
|
|
.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
|
|
|
|
|
.Select(i => i.Address));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(includeLoopback || interfaceType == NetworkInterfaceType.Loopback) {
|
|
|
|
|
addressList.Add(IPAddress.Loopback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return addressList.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the public IP address using ipify.org.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>A public IP address of the result produced by this Task.</returns>
|
|
|
|
|
public static async Task<IPAddress> GetPublicIPAddressAsync(CancellationToken ct = default) {
|
|
|
|
|
using(HttpClient client = new HttpClient()) {
|
|
|
|
|
HttpResponseMessage response = await client.GetAsync("https://api.ipify.org", ct).ConfigureAwait(false);
|
|
|
|
|
return IPAddress.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the public IP address using ipify.org.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>A public ip address.</returns>
|
|
|
|
|
public static IPAddress GetPublicIPAddress() => GetPublicIPAddressAsync().GetAwaiter().GetResult();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the configured IPv4 DNS servers for the active network interfaces.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// A collection of NetworkInterface/IPInterfaceProperties pairs
|
|
|
|
|
/// that represents the active IPv4 interfaces.
|
|
|
|
|
/// </returns>
|
|
|
|
|
public static IPAddress[] GetIPv4DnsServers()
|
|
|
|
|
=> GetIPv4Interfaces()
|
|
|
|
|
.Select(a => a.Value.DnsAddresses.Where(d => d.AddressFamily == AddressFamily.InterNetwork))
|
|
|
|
|
.SelectMany(d => d)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region DNS and NTP Clients
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fqdn">The FQDN.</param>
|
|
|
|
|
/// <returns>An array of local ip addresses.</returns>
|
|
|
|
|
public static IPAddress[] GetDnsHostEntry(String fqdn) {
|
|
|
|
|
IPAddress dnsServer = GetIPv4DnsServers().FirstOrDefault() ?? IPAddress.Parse("8.8.8.8");
|
|
|
|
|
return GetDnsHostEntry(fqdn, dnsServer, DnsDefaultPort);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fqdn">The FQDN.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>An array of local ip addresses of the result produced by this task.</returns>
|
|
|
|
|
public static Task<IPAddress[]> GetDnsHostEntryAsync(String fqdn,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => GetDnsHostEntry(fqdn), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fqdn">The FQDN.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// An array of local ip addresses.
|
|
|
|
|
/// </returns>
|
|
|
|
|
/// <exception cref="ArgumentNullException">fqdn.</exception>
|
|
|
|
|
public static IPAddress[] GetDnsHostEntry(String fqdn, IPAddress dnsServer, Int32 port) {
|
|
|
|
|
if(fqdn == null) {
|
|
|
|
|
throw new ArgumentNullException(nameof(fqdn));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(fqdn.IndexOf(".", StringComparison.Ordinal) == -1) {
|
|
|
|
|
fqdn += "." + IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(true) {
|
|
|
|
|
if(fqdn.EndsWith(".") == false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fqdn = fqdn.Substring(0, fqdn.Length - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DnsClient client = new DnsClient(dnsServer, port);
|
|
|
|
|
IList<IPAddress> result = client.Lookup(fqdn);
|
|
|
|
|
return result.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fqdn">The FQDN.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>An array of local ip addresses of the result produced by this task.</returns>
|
|
|
|
|
public static Task<IPAddress[]> GetDnsHostEntryAsync(String fqdn, IPAddress dnsServer, Int32 port, CancellationToken ct = default) => Task.Run(() => GetDnsHostEntry(fqdn, dnsServer, port), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the reverse lookup FQDN of the given IP Address.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
|
|
|
|
public static String GetDnsPointerEntry(IPAddress query, IPAddress dnsServer, Int32 port) => new DnsClient(dnsServer, port).Reverse(query);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the reverse lookup FQDN of the given IP Address.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
|
|
|
|
public static Task<String> GetDnsPointerEntryAsync(
|
|
|
|
|
IPAddress query,
|
|
|
|
|
IPAddress dnsServer,
|
|
|
|
|
Int32 port,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => GetDnsPointerEntry(query, dnsServer, port), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the reverse lookup FQDN of the given IP Address.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
|
|
|
|
public static String GetDnsPointerEntry(IPAddress query) => new DnsClient(GetIPv4DnsServers().FirstOrDefault()).Reverse(query);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the reverse lookup FQDN of the given IP Address.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
|
|
|
|
public static Task<String> GetDnsPointerEntryAsync(
|
|
|
|
|
IPAddress query,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => GetDnsPointerEntry(query), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Queries the DNS server for the specified record type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="recordType">Type of the record.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// Appropriate DNS server for the specified record type.
|
|
|
|
|
/// </returns>
|
|
|
|
|
public static DnsQueryResult QueryDns(String query, DnsRecordType recordType, IPAddress dnsServer, Int32 port) {
|
|
|
|
|
if(query == null) {
|
|
|
|
|
throw new ArgumentNullException(nameof(query));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DnsClient.DnsClientResponse response = new DnsClient(dnsServer, port).Resolve(query, recordType);
|
|
|
|
|
return new DnsQueryResult(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Queries the DNS server for the specified record type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="recordType">Type of the record.</param>
|
|
|
|
|
/// <param name="dnsServer">The DNS server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>Queries the DNS server for the specified record type of the result produced by this Task.</returns>
|
|
|
|
|
public static Task<DnsQueryResult> QueryDnsAsync(
|
|
|
|
|
String query,
|
|
|
|
|
DnsRecordType recordType,
|
|
|
|
|
IPAddress dnsServer,
|
|
|
|
|
Int32 port,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => QueryDns(query, recordType, dnsServer, port), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Queries the DNS server for the specified record type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="recordType">Type of the record.</param>
|
|
|
|
|
/// <returns>Appropriate DNS server for the specified record type.</returns>
|
|
|
|
|
public static DnsQueryResult QueryDns(String query, DnsRecordType recordType) => QueryDns(query, recordType, GetIPv4DnsServers().FirstOrDefault(), DnsDefaultPort);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Queries the DNS server for the specified record type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query.</param>
|
|
|
|
|
/// <param name="recordType">Type of the record.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>Queries the DNS server for the specified record type of the result produced by this Task.</returns>
|
|
|
|
|
public static Task<DnsQueryResult> QueryDnsAsync(
|
|
|
|
|
String query,
|
|
|
|
|
DnsRecordType recordType,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => QueryDns(query, recordType), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the UTC time by querying from an NTP server.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ntpServerAddress">The NTP server address.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// A new instance of the DateTime structure to
|
|
|
|
|
/// the specified year, month, day, hour, minute and second.
|
|
|
|
|
/// </returns>
|
|
|
|
|
public static DateTime GetNetworkTimeUtc(IPAddress ntpServerAddress, Int32 port = NtpDefaultPort) {
|
|
|
|
|
if(ntpServerAddress == null) {
|
|
|
|
|
throw new ArgumentNullException(nameof(ntpServerAddress));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NTP message size - 16 bytes of the digest (RFC 2030)
|
|
|
|
|
Byte[] ntpData = new Byte[48];
|
|
|
|
|
|
|
|
|
|
// Setting the Leap Indicator, Version Number and Mode values
|
|
|
|
|
ntpData[0] = 0x1B; // LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
|
|
|
|
|
|
|
|
|
|
// The UDP port number assigned to NTP is 123
|
|
|
|
|
IPEndPoint endPoint = new IPEndPoint(ntpServerAddress, port);
|
|
|
|
|
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
|
|
|
|
|
|
|
|
socket.Connect(endPoint);
|
|
|
|
|
socket.ReceiveTimeout = 3000; // Stops code hang if NTP is blocked
|
|
|
|
|
_ = socket.Send(ntpData);
|
|
|
|
|
_ = socket.Receive(ntpData);
|
|
|
|
|
socket.Dispose();
|
|
|
|
|
|
|
|
|
|
// Offset to get to the "Transmit Timestamp" field (time at which the reply
|
|
|
|
|
// departed the server for the client, in 64-bit timestamp format."
|
|
|
|
|
const Byte serverReplyTime = 40;
|
|
|
|
|
|
|
|
|
|
// Get the seconds part
|
|
|
|
|
UInt64 intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
|
|
|
|
|
|
|
|
|
|
// Get the seconds fraction
|
|
|
|
|
UInt64 fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
|
|
|
|
|
|
|
|
|
|
// Convert From big-endian to little-endian to match the platform
|
|
|
|
|
if(BitConverter.IsLittleEndian) {
|
|
|
|
|
intPart = intPart.SwapEndianness();
|
|
|
|
|
fractPart = intPart.SwapEndianness();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UInt64 milliseconds = intPart * 1000 + fractPart * 1000 / 0x100000000L;
|
|
|
|
|
|
|
|
|
|
// The time is given in UTC
|
|
|
|
|
return new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((Int64)milliseconds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the UTC time by querying from an NTP server.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ntpServerName">The NTP server, by default pool.ntp.org.</param>
|
|
|
|
|
/// <param name="port">The port, by default NTP 123.</param>
|
|
|
|
|
/// <returns>The UTC time by querying from an NTP server.</returns>
|
|
|
|
|
public static DateTime GetNetworkTimeUtc(String ntpServerName = "pool.ntp.org",
|
|
|
|
|
Int32 port = NtpDefaultPort) {
|
|
|
|
|
IPAddress[] addresses = GetDnsHostEntry(ntpServerName);
|
|
|
|
|
return GetNetworkTimeUtc(addresses.First(), port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the UTC time by querying from an NTP server.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ntpServerAddress">The NTP server address.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>The UTC time by querying from an NTP server of the result produced by this Task.</returns>
|
|
|
|
|
public static Task<DateTime> GetNetworkTimeUtcAsync(
|
|
|
|
|
IPAddress ntpServerAddress,
|
|
|
|
|
Int32 port = NtpDefaultPort,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => GetNetworkTimeUtc(ntpServerAddress, port), ct);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the UTC time by querying from an NTP server.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ntpServerName">Name of the NTP server.</param>
|
|
|
|
|
/// <param name="port">The port.</param>
|
|
|
|
|
/// <param name="ct">The cancellation token.</param>
|
|
|
|
|
/// <returns>The UTC time by querying from an NTP server of the result produced by this Task.</returns>
|
|
|
|
|
public static Task<DateTime> GetNetworkTimeUtcAsync(
|
|
|
|
|
String ntpServerName = "pool.ntp.org",
|
|
|
|
|
Int32 port = NtpDefaultPort,
|
|
|
|
|
CancellationToken ct = default) => Task.Run(() => GetNetworkTimeUtc(ntpServerName, port), ct);
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
2019-02-17 14:08:57 +01:00
|
|
|
|
}
|