blob: 1893cd417bddc34458615b2cc1b264e196d11b14 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 Robert Bosch GmbH
* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace BaSyx.Utils.Network
{
public static class NetworkUtils
{
private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// This method returns the closest source IP address relative to the the target IP address.
/// The probality of being able to call the target IP hence increases.
/// </summary>
/// <param name="target">Target IP address to call</param>
/// <param name="sources">Source IP address from where to cal the target</param>
/// <returns>The closest source IP address to the the target IP address or the Loopback Address</returns>
public static IPAddress GetClosestIPAddress(IPAddress target, List<IPAddress> sources)
{
Dictionary<int, IPAddress> scoredSourceIPAddresses = new Dictionary<int, IPAddress>();
byte[] targetBytes = target.GetAddressBytes();
foreach (var source in sources)
{
byte[] sourceBytes = source.GetAddressBytes();
int score = CompareIPByteArray(targetBytes, sourceBytes);
if(!scoredSourceIPAddresses.ContainsKey(score) && score != 0)
scoredSourceIPAddresses.Add(score, source);
}
if(scoredSourceIPAddresses.Count > 0)
return scoredSourceIPAddresses[scoredSourceIPAddresses.Keys.Max()];
return IPAddress.Loopback;
}
private static int CompareIPByteArray(byte[] target, byte[] source)
{
if (target.Length != source.Length)
return 0;
int score = 0;
for (int i = 0; i < source.Length; i++)
{
if (target[i] == source[i])
score++;
else
return score;
}
return score;
}
/// <summary>
/// Returns a sequence of network interfaces which are up and running.
/// If there is no other than the loopback interface available, the loopback interface is returned
/// </summary>
/// <returns>Sequence of network interfaces</returns>
public static IEnumerable<NetworkInterface> GetOperationalNetworkInterfaces()
{
NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
IEnumerable<NetworkInterface> selectedInterfaces = networkInterfaces?.Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback);
if(selectedInterfaces?.Count() > 0)
return selectedInterfaces;
else
return networkInterfaces?.Where(n => n.OperationalStatus == OperationalStatus.Up);
}
/// <summary>
/// Returns all IP addresses of all network interfaces without loopback
/// </summary>
/// <returns>Sequence of IP addresses</returns>
public static IEnumerable<IPAddress> GetIPAddresses()
{
IEnumerable<NetworkInterface> networkInterfaces = GetOperationalNetworkInterfaces();
return networkInterfaces?.SelectMany(n => n.GetIPProperties().UnicastAddresses)?.Select(s => s.Address);
}
/// <summary>
/// Returns all link local IP addresses
/// </summary>
/// <returns>Sequence of link local IP addresses</returns>
public static List<IPAddress> GetLinkLocalIPAddresses()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
List<IPAddress> ipAddresses = new List<IPAddress>();
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6 && ip.IsIPv6LinkLocal)
ipAddresses.Add(ip);
}
return ipAddresses;
}
/// <summary>
/// Pings a host and returns true if ping was successfull otherwise false
/// </summary>
/// <param name="hostNameOrAddress">IP-address or host name</param>
/// <returns>true if pingable, false otherwise</returns>
public static async Task<bool> PingHostAsync(string hostNameOrAddress)
{
if (string.IsNullOrEmpty(hostNameOrAddress))
throw new ArgumentNullException(nameof(hostNameOrAddress));
try
{
using (Ping pinger = new Ping())
{
PingReply reply = await pinger.SendPingAsync(hostNameOrAddress);
if (reply.Status == IPStatus.Success)
{
return true;
}
else
{
logger.Warn($"Pinging {hostNameOrAddress} PingReply-Status: " + Enum.GetName(typeof(IPStatus), reply.Status));
return false;
}
}
}
catch (PingException e)
{
logger.Error(e, "Ping-Exception");
return false;
}
}
}
}