using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
namespace LiteNetLib
{
///
/// Address type that you want to receive from NetUtils.GetLocalIp method
///
[Flags]
public enum LocalAddrType
{
IPv4 = 1,
IPv6 = 2,
All = IPv4 | IPv6
}
///
/// Some specific network utilities
///
public static class NetUtils
{
public static IPEndPoint MakeEndPoint(string hostStr, int port)
{
return new IPEndPoint(ResolveAddress(hostStr), port);
}
public static IPAddress ResolveAddress(string hostStr)
{
if(hostStr == "localhost")
return IPAddress.Loopback;
IPAddress ipAddress;
if (!IPAddress.TryParse(hostStr, out ipAddress))
{
if (NetSocket.IPv6Support)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetworkV6);
if (ipAddress == null)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetwork);
}
if (ipAddress == null)
throw new ArgumentException("Invalid address: " + hostStr);
return ipAddress;
}
private static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily)
{
IPAddress[] addresses = ResolveAddresses(hostStr);
foreach (IPAddress ip in addresses)
{
if (ip.AddressFamily == addressFamily)
{
return ip;
}
}
return null;
}
private static IPAddress[] ResolveAddresses(string hostStr)
{
#if NETSTANDARD || NETCOREAPP
var hostTask = Dns.GetHostEntryAsync(hostStr);
hostTask.GetAwaiter().GetResult();
var host = hostTask.Result;
#else
var host = Dns.GetHostEntry(hostStr);
#endif
return host.AddressList;
}
///
/// Get all local ip addresses
///
/// type of address (IPv4, IPv6 or both)
/// List with all local ip addresses
public static List GetLocalIpList(LocalAddrType addrType)
{
List targetList = new List();
GetLocalIpList(targetList, addrType);
return targetList;
}
///
/// Get all local ip addresses (non alloc version)
///
/// result list
/// type of address (IPv4, IPv6 or both)
public static void GetLocalIpList(IList targetList, LocalAddrType addrType)
{
bool ipv4 = (addrType & LocalAddrType.IPv4) == LocalAddrType.IPv4;
bool ipv6 = (addrType & LocalAddrType.IPv6) == LocalAddrType.IPv6;
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
//Skip loopback and disabled network interfaces
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
ni.OperationalStatus != OperationalStatus.Up)
continue;
var ipProps = ni.GetIPProperties();
//Skip address without gateway
if (ipProps.GatewayAddresses.Count == 0)
continue;
foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
{
var address = ip.Address;
if ((ipv4 && address.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && address.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(address.ToString());
}
}
}
catch
{
//ignored
}
//Fallback mode (unity android)
if (targetList.Count == 0)
{
IPAddress[] addresses = ResolveAddresses(Dns.GetHostName());
foreach (IPAddress ip in addresses)
{
if((ipv4 && ip.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && ip.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(ip.ToString());
}
}
if (targetList.Count == 0)
{
if(ipv4)
targetList.Add("127.0.0.1");
if(ipv6)
targetList.Add("::1");
}
}
private static readonly List IpList = new List();
///
/// Get first detected local ip address
///
/// type of address (IPv4, IPv6 or both)
/// IP address if available. Else - string.Empty
public static string GetLocalIp(LocalAddrType addrType)
{
lock (IpList)
{
IpList.Clear();
GetLocalIpList(IpList, addrType);
return IpList.Count == 0 ? string.Empty : IpList[0];
}
}
// ===========================================
// Internal and debug log related stuff
// ===========================================
internal static void PrintInterfaceInfos()
{
NetDebug.WriteForce(NetLogLevel.Info, "IPv6Support: {0}", NetSocket.IPv6Support);
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork ||
ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
{
NetDebug.WriteForce(
NetLogLevel.Info,
"Interface: {0}, Type: {1}, Ip: {2}, OpStatus: {3}",
ni.Name,
ni.NetworkInterfaceType.ToString(),
ip.Address.ToString(),
ni.OperationalStatus.ToString());
}
}
}
}
catch (Exception e)
{
NetDebug.WriteForce(NetLogLevel.Info, "Error while getting interface infos: {0}", e.ToString());
}
}
internal static int RelativeSequenceNumber(int number, int expected)
{
return (number - expected + NetConstants.MaxSequence + NetConstants.HalfMaxSequence) % NetConstants.MaxSequence - NetConstants.HalfMaxSequence;
}
}
}