You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.7 KiB
129 lines
4.7 KiB
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.Udp;
|
|
|
|
public partial class UdpProtocolSettingsViewModel : ProtocolSettingsViewModel, IUdpProtocolSettings, IRecipient<UdpConnectedMessage>
|
|
{
|
|
public override Types.ProtocolType ProtocolType => Types.ProtocolType.Udp;
|
|
|
|
#region IUdpProtocolSettings Implementation
|
|
[ObservableProperty]
|
|
private string hostname = string.Empty;
|
|
|
|
[ObservableProperty]
|
|
private int port = 10000;
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// A property to display the resolved IP address that the protocol connected to.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private string resolvedAddress = string.Empty;
|
|
|
|
public UdpProtocolSettingsViewModel(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<IUserInterfaceMessage>(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Null or empty"));
|
|
return false;
|
|
}
|
|
if (this.Port < IPEndPoint.MinPort && this.Port > IPEndPoint.MaxPort)
|
|
{
|
|
this.messenger.Send<IUserInterfaceMessage>(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<IUserInterfaceMessage>(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Length is greater than 255 characters"));
|
|
return false;
|
|
}
|
|
catch (SocketException)
|
|
{
|
|
this.messenger.Send<IUserInterfaceMessage>(new ProtocolSettingsInvalidMessage(nameof(this.Hostname), "Error encountered when resolving hostname"));
|
|
return false;
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
this.messenger.Send<IUserInterfaceMessage>(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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the <see cref="ResolvedAddress"/> proprty to the resolved address from the message.
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
void IRecipient<UdpConnectedMessage>.Receive(UdpConnectedMessage message)
|
|
{
|
|
this.ResolvedAddress = message.ResolvedAddress.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to retrieve the first ethernet adapters subnet address.
|
|
/// </summary>
|
|
/// <returns>string of <see cref="IPAddress"/> of the first ethernet adapters subnet address, or <see cref="string.Empty"/> if not found</returns>
|
|
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;
|
|
}
|
|
}
|
|
|