Created
October 31, 2022 22:08
-
-
Save patridge/133b9dbe0780cd12570ed7f1f1f255b5 to your computer and use it in GitHub Desktop.
Meadow: Network helper methods (NTP, WiFi discovery, requests, etc.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class NetworkHelpers | |
{ | |
public static async Task GetWebPageViaHttpClient(string uri) | |
{ | |
Console.WriteLine($"Requesting {uri} - {DateTime.Now}"); | |
using (var client = new HttpClient()) | |
{ | |
try | |
{ | |
HttpResponseMessage response = await client.GetAsync(uri); | |
response.EnsureSuccessStatusCode(); | |
string responseBody = await response.Content.ReadAsStringAsync(); | |
Console.WriteLine($"Success [length: {responseBody.Length}]"); | |
} | |
catch (TaskCanceledException cancelledEx) | |
{ | |
Console.WriteLine($"Request timed out: {cancelledEx.Message}"); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine($"Request exception: {ex.ToString()}\n\t{ex.InnerException?.ToString() ?? ""}"); | |
} | |
} | |
} | |
public static async Task ScanForAccessPoints(IWiFiNetworkAdapter wifi) | |
{ | |
Console.WriteLine("Getting list of access points."); | |
var networks = await wifi.Scan(TimeSpan.FromSeconds(60)); | |
if (networks.Count > 0) | |
{ | |
Console.WriteLine("|-------------------------------------------------------------|---------|"); | |
Console.WriteLine("| Network Name | RSSI | BSSID | Channel |"); | |
Console.WriteLine("|-------------------------------------------------------------|---------|"); | |
foreach (WifiNetwork accessPoint in networks) | |
{ | |
Console.WriteLine($"| {accessPoint.Ssid,-32} | {accessPoint.SignalDbStrength,4} | {accessPoint.Bssid,17} | {accessPoint.ChannelCenterFrequency,3} |"); | |
} | |
} | |
else | |
{ | |
Console.WriteLine($"No access points detected."); | |
} | |
} | |
public static void DisplayNetworkInformation() | |
{ | |
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); | |
if (adapters.Length == 0) | |
{ | |
Console.WriteLine("No adapters available."); | |
} | |
foreach (NetworkInterface adapter in adapters) | |
{ | |
IPInterfaceProperties properties = adapter.GetIPProperties(); | |
Console.WriteLine(); | |
Console.WriteLine(adapter.Description); | |
Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length, '=')); | |
Console.WriteLine($" Adapter name: {adapter.Name}"); | |
Console.WriteLine($" Interface type .......................... : {adapter.NetworkInterfaceType}"); | |
Console.WriteLine($" Physical Address ........................ : {adapter.GetPhysicalAddress().ToString()}"); | |
Console.WriteLine($" Operational status ...................... : {adapter.OperationalStatus}"); | |
string versions = String.Empty; | |
if (adapter.Supports(NetworkInterfaceComponent.IPv4)) | |
{ | |
versions = "IPv4"; | |
} | |
if (adapter.Supports(NetworkInterfaceComponent.IPv6)) | |
{ | |
if (versions.Length > 0) | |
{ | |
versions += " "; | |
} | |
versions += "IPv6"; | |
} | |
Console.WriteLine($" IP version .............................. : {versions}"); | |
if (adapter.Supports(NetworkInterfaceComponent.IPv4)) | |
{ | |
IPv4InterfaceProperties ipv4 = properties.GetIPv4Properties(); | |
Console.WriteLine(" MTU ..................................... : {0}", ipv4.Mtu); | |
} | |
if ((adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) || (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet)) | |
{ | |
foreach (UnicastIPAddressInformation ip in adapter.GetIPProperties().UnicastAddresses) | |
{ | |
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) | |
{ | |
Console.WriteLine($" IP address .............................. : {ip.Address.ToString()}"); | |
Console.WriteLine($" Subnet mask ............................. : {ip.IPv4Mask.ToString()}"); | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// https://stackoverflow.com/a/12150289/48700 | |
/// </summary> | |
/// <param name="ntpServer"> | |
/// Defaults to the default Windows time server. Another option: any of [0-3].pool.ntp.org. | |
/// </param> | |
public static DateTime GetNetworkTime(string ntpServer = "time.windows.com") | |
{ | |
// NTP message size - 16 bytes of the digest (RFC 2030) | |
var 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) | |
var addresses = Dns.GetHostEntry(ntpServer).AddressList; | |
//The UDP port number assigned to NTP is 123 | |
var ipEndPoint = new IPEndPoint(addresses[0], 123); | |
//NTP uses UDP | |
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) | |
{ | |
socket.Connect(ipEndPoint); | |
//Stops code hang if NTP is blocked | |
socket.ReceiveTimeout = 3000; | |
socket.Send(ntpData); | |
socket.Receive(ntpData); | |
socket.Close(); | |
} | |
//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 | |
ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime); | |
//Get the seconds fraction | |
ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4); | |
// stackoverflow.com/a/3294698/162671 | |
Func<ulong, uint> SwapEndianness = (ulong x) => | |
{ | |
return (uint)(((x & 0x000000ff) << 24) + | |
((x & 0x0000ff00) << 8) + | |
((x & 0x00ff0000) >> 8) + | |
((x & 0xff000000) >> 24)); | |
}; | |
//Convert From big-endian to little-endian | |
intPart = SwapEndianness(intPart); | |
fractPart = SwapEndianness(fractPart); | |
var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L); | |
//**UTC** time | |
var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds); | |
return networkDateTime.ToLocalTime(); | |
} | |
static readonly HttpClient staticHttpClient = new HttpClient() | |
{ | |
Timeout = TimeSpan.FromSeconds(10), | |
}; | |
// TODO: Use IHttpClientFactory from NuGet Microsoft.Extensions.Http | |
public static async Task GetWebPageViaStaticHttpClient(string uri) | |
{ | |
Console.WriteLine($"Requesting {uri} - {DateTime.Now}"); | |
try | |
{ | |
HttpResponseMessage response = await staticHttpClient.GetAsync(uri); | |
response.EnsureSuccessStatusCode(); | |
string responseBody = await response.Content.ReadAsStringAsync(); | |
Console.WriteLine($"Success [length: {responseBody.Length}]"); | |
} | |
catch (TaskCanceledException cancelledEx) | |
{ | |
Console.WriteLine($"Request timed out: {cancelledEx.Message}"); | |
Console.WriteLine($"Failure"); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine($"Request exception: {e.Message}"); | |
Console.WriteLine($"Failure"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment