first commit
This commit is contained in:
206
NitroxModel/Helper/NetHelper.cs
Normal file
206
NitroxModel/Helper/NetHelper.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
#if RELEASE
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
#endif
|
||||
|
||||
namespace NitroxModel.Helper
|
||||
{
|
||||
public static class NetHelper
|
||||
{
|
||||
private static readonly string[] privateNetworks =
|
||||
{
|
||||
"10.0.0.0/8",
|
||||
"127.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.0.0.0/24 ",
|
||||
"192.168.0.0/16",
|
||||
"198.18.0.0/15",
|
||||
};
|
||||
|
||||
private static IPAddress wanIpCache;
|
||||
private static IPAddress lanIpCache;
|
||||
private static readonly object wanIpLock = new();
|
||||
private static readonly object lanIpLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network interfaces used for going onto the internet.
|
||||
/// This is done by filtering for "Ethernet" and "Wi-Fi" network interfaces where "Ethernet" is returned earlier.
|
||||
/// </summary>
|
||||
/// <returns>Network interfaces used to go onto the internet.</returns>
|
||||
public static IEnumerable<NetworkInterface> GetInternetInterfaces()
|
||||
{
|
||||
return NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(n => n.OperationalStatus is OperationalStatus.Up
|
||||
&& n.NetworkInterfaceType is not (NetworkInterfaceType.Tunnel or NetworkInterfaceType.Loopback)
|
||||
&& n.NetworkInterfaceType is (NetworkInterfaceType.Wireless80211 or NetworkInterfaceType.Ethernet))
|
||||
.OrderBy(n => n.NetworkInterfaceType is NetworkInterfaceType.Ethernet ? 1 : 0)
|
||||
.ThenBy(n => n.Name);
|
||||
}
|
||||
|
||||
public static IPAddress GetLanIp()
|
||||
{
|
||||
lock (lanIpLock)
|
||||
{
|
||||
if (lanIpCache != null)
|
||||
{
|
||||
return lanIpCache;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NetworkInterface ni in GetInternetInterfaces())
|
||||
{
|
||||
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
lock (lanIpLock)
|
||||
{
|
||||
return lanIpCache = ip.Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<IPAddress> GetWanIpAsync()
|
||||
{
|
||||
lock (wanIpLock)
|
||||
{
|
||||
if (wanIpCache != null)
|
||||
{
|
||||
return wanIpCache;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress ip = await NatHelper.GetExternalIpAsync();
|
||||
#if RELEASE
|
||||
if (ip == null || ip.IsPrivate())
|
||||
{
|
||||
Regex regex = new(@"(?:[0-2]??[0-9]{1,2}\.){3}[0-2]??[0-9]+");
|
||||
string[] sites =
|
||||
{
|
||||
"https://ipv4.icanhazip.com/",
|
||||
"https://checkip.amazonaws.com/",
|
||||
"https://api.ipify.org/",
|
||||
"https://api4.my-ip.io/ip",
|
||||
"https://ifconfig.me/",
|
||||
"https://showmyip.com/",
|
||||
};
|
||||
using HttpClient client = new();
|
||||
foreach (string site in sites)
|
||||
{
|
||||
try
|
||||
{
|
||||
using HttpResponseMessage response = await client.GetAsync(site);
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
ip = IPAddress.Parse(regex.Match(content).Value);
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lock (wanIpLock)
|
||||
{
|
||||
return wanIpCache = ip;
|
||||
}
|
||||
}
|
||||
|
||||
public static IPAddress GetHamachiIp()
|
||||
{
|
||||
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (ni.Name != "Hamachi")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
return ip.Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<bool> HasInternetConnectivityAsync()
|
||||
{
|
||||
if (!NetworkInterface.GetIsNetworkAvailable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using Ping ping = new();
|
||||
PingReply reply = await ping.SendPingAsync(new IPAddress([8, 8, 8, 8]),2000);
|
||||
return reply.Status == IPStatus.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given IP address is reserved for private networks.
|
||||
/// </summary>
|
||||
public static bool IsPrivate(this IPAddress address)
|
||||
{
|
||||
static bool IsInRange(IPAddress ipAddress, string mask)
|
||||
{
|
||||
string[] parts = mask.Split('/');
|
||||
|
||||
int ipNum = BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0);
|
||||
int cidrAddress = BitConverter.ToInt32(IPAddress.Parse(parts[0]).GetAddressBytes(), 0);
|
||||
int cidrMask = IPAddress.HostToNetworkOrder(-1 << (32 - int.Parse(parts[1])));
|
||||
|
||||
return (ipNum & cidrMask) == (cidrAddress & cidrMask);
|
||||
}
|
||||
|
||||
foreach (string privateSubnet in privateNetworks)
|
||||
{
|
||||
if (IsInRange(address, privateSubnet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the IP address points to the executing machine.
|
||||
/// </summary>
|
||||
public static bool IsLocalhost(this IPAddress address)
|
||||
{
|
||||
if (address == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (IPAddress.IsLoopback(address))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (NetworkInterface ni in GetInternetInterfaces())
|
||||
{
|
||||
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (address.Equals(ip.Address))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user