using Common.Messaging;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MultiTerm.Protocols.Types;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace MultiTerm.Protocols.Network;
public abstract partial class NetworkProtocolSettingsViewModel : ProtocolSettingsViewModel, INetworkProtocolSettings
{
public override abstract Types.ProtocolType ProtocolType { get; }
#region IUdpProtocolSettings Implementation
[ObservableProperty]
private string hostname = string.Empty;
[ObservableProperty]
private int port = 10000;
#endregion
///
/// A property to display the resolved IP address that the protocol connected to.
///
[ObservableProperty]
private string resolvedAddress = string.Empty;
public NetworkProtocolSettingsViewModel(IMessenger messenger) : base(messenger)
{
// register for messages
// messenger.Register(this);
// initialize IP address with first ethernet adapter local IP
this.Hostname = GetFirstEthernetAdaptersSubnet();
}
public bool AreValid()
{
if (String.IsNullOrEmpty(this.Hostname))
{
this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Null or empty"));
return false;
}
if (this.Port < IPEndPoint.MinPort && this.Port > IPEndPoint.MaxPort)
{
this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.Port), "Out of range"));
return false;
}
// try parse to IP address
if (IPAddress.TryParse(this.Hostname, out _))
{
return true;
}
// else try to resolve hostname
else
{
IPHostEntry host;
try
{
host = Dns.GetHostEntry(this.Hostname);
}
catch (ArgumentOutOfRangeException)
{
this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Length is greater than 255 characters"));
return false;
}
catch (SocketException)
{
this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Error encountered when resolving hostname"));
return false;
}
catch (ArgumentException)
{
this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Invalid IP address"));
return false;
}
// host not null and found at least one address => success
return host != null && host.AddressList.Length > 0;
}
}
///
/// Sets the proprty to the resolved address from the message.
///
///
//void IRecipient.Receive(UdpConnectedMessage message)
//{
// this.ResolvedAddress = message.ResolvedAddress.ToString();
//}
///
/// Tries to retrieve the first ethernet adapters subnet address.
///
/// string of of the first ethernet adapters subnet address, or if not found
private static string GetFirstEthernetAdaptersSubnet()
{
// iterate through all network interfaces
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in interfaces)
{
// return first found ipv4 adapter subnet address
if (adapter.OperationalStatus == OperationalStatus.Up)
{
try
{
var unicastAddresses = adapter.GetIPProperties().UnicastAddresses;
foreach (var unicastAddress in unicastAddresses)
{
// only interested in IPv4
if (unicastAddress.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
// Ignore loopback addresses (e.g., 127.0.0.1)
if (IPAddress.IsLoopback(unicastAddress.Address))
continue;
// split and only return first three parts of the IPv4 address
var splitIpv4 = unicastAddress.Address.ToString().Split('.');
return $"{splitIpv4[0]}.{splitIpv4[1]}.{splitIpv4[2]}.";
}
}
catch { }
}
}
return string.Empty;
}
}