diff --git a/MultiTerm.Protocols/Helpers/NetworkProtocolHelpers.cs b/MultiTerm.Protocols/Helpers/NetworkProtocolHelpers.cs
new file mode 100644
index 0000000..8adecad
--- /dev/null
+++ b/MultiTerm.Protocols/Helpers/NetworkProtocolHelpers.cs
@@ -0,0 +1,31 @@
+using MultiTerm.Protocols.Network;
+
+namespace MultiTerm.Protocols.Helpers;
+
+internal static class NetworkProtocolHelpers
+{
+ ///
+ /// Returns the hostname of the but limited to amount of characters.
+ /// If the hostname is longer than , '...' will be prefixed. The resulting string may also be +3 characters long.
+ /// If the hostname cannot be read, the result will be "invalid".
+ ///
+ /// settings object containing hostname
+ /// max amount of characters of the resulting string
+ /// string with limited length (maximum amount of characters = + 3
+ public static string GetLimitedLengthHostname(INetworkProtocolSettings settingsObject, int maxLength = 20)
+ {
+ string limitedHostname = "invalid";
+ string prefix = "...";
+
+ if (settingsObject.Hostname != null && settingsObject.Hostname.Length >= maxLength)
+ {
+ limitedHostname = $"{prefix}{settingsObject.Hostname.Substring(settingsObject.Hostname.Length - maxLength, maxLength)}";
+ }
+ else if (settingsObject.Hostname != null)
+ {
+ limitedHostname = $"{settingsObject.Hostname}";
+ }
+
+ return limitedHostname;
+ }
+}
diff --git a/MultiTerm.Protocols/Udp/IUdpProtocolSettings.cs b/MultiTerm.Protocols/Network/INetworkProtocolSettings.cs
similarity index 66%
rename from MultiTerm.Protocols/Udp/IUdpProtocolSettings.cs
rename to MultiTerm.Protocols/Network/INetworkProtocolSettings.cs
index a9ba156..fea5524 100644
--- a/MultiTerm.Protocols/Udp/IUdpProtocolSettings.cs
+++ b/MultiTerm.Protocols/Network/INetworkProtocolSettings.cs
@@ -1,12 +1,12 @@
-namespace MultiTerm.Protocols.Udp;
+namespace MultiTerm.Protocols.Network;
-internal interface IUdpProtocolSettings : IProtocolSettings
+internal interface INetworkProtocolSettings : IProtocolSettings
{
///
/// Hostname to connect to.
/// Can be a hostname with or without domain or an IPv4/IVv6 address.
///
- string Hostname {get; internal set; }
+ string Hostname { get; internal set; }
///
/// Port of the end device. Will also be the port that is listened on.
diff --git a/MultiTerm.Protocols/Network/NetworkProtocolSettingsViewModel.cs b/MultiTerm.Protocols/Network/NetworkProtocolSettingsViewModel.cs
new file mode 100644
index 0000000..7d3eea7
--- /dev/null
+++ b/MultiTerm.Protocols/Network/NetworkProtocolSettingsViewModel.cs
@@ -0,0 +1,129 @@
+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;
+ }
+}
diff --git a/MultiTerm.Protocols/Udp/UdpProtocol.cs b/MultiTerm.Protocols/Udp/UdpProtocol.cs
index f8b2696..636db17 100644
--- a/MultiTerm.Protocols/Udp/UdpProtocol.cs
+++ b/MultiTerm.Protocols/Udp/UdpProtocol.cs
@@ -1,7 +1,9 @@
using Common.Logging;
using Common.Messaging;
using CommunityToolkit.Mvvm.Messaging;
+using MultiTerm.Protocols.Helpers;
using MultiTerm.Protocols.Model;
+using MultiTerm.Protocols.Network;
using System.Net.Sockets;
namespace MultiTerm.Protocols.Udp;
@@ -12,40 +14,27 @@ public class UdpProtocol : CommunicationProtocol
public override string InstanceIdentifier { get; protected set; } = string.Empty;
- private IUdpProtocolSettings? udpSettings;
+ private INetworkProtocolSettings? settings;
private UdpClient? receivingUdpClient;
private UdpClient? sendingUdpClient;
- private const int MaxInstanceIdentifierLength = 20; // maximum number of characters for the InstanceIdentifier
-
public UdpProtocol(ILogger logger, IMessenger messenger) : base(logger, messenger) { }
protected override bool InternalConnect(IProtocolSettings settings)
{
// check if settings are of correct type
- if (settings is not IUdpProtocolSettings udpProtocolSettings)
+ if (settings is not INetworkProtocolSettings networkSettings)
{
- this.udpSettings = null;
+ this.settings = null;
throw new ArgumentException($"Cannot connect due to wrong type of Protocol Settings. " +
$"Check parameter {nameof(settings)}' of '{nameof(InternalConnect)}()' in {nameof(UdpProtocol)}.");
}
// store locally
- this.udpSettings = udpProtocolSettings;
+ this.settings = networkSettings;
// update identifier
- if(this.udpSettings.Hostname != null && this.udpSettings.Hostname.Length >= MaxInstanceIdentifierLength)
- {
- this.InstanceIdentifier = $"...{this.udpSettings.Hostname.Substring(this.udpSettings.Hostname.Length - MaxInstanceIdentifierLength, MaxInstanceIdentifierLength)}";
- }
- else if(this.udpSettings.Hostname != null)
- {
- this.InstanceIdentifier = $"{this.udpSettings.Hostname}";
- }
- else
- {
- this.InstanceIdentifier = "invalid";
- }
+ this.InstanceIdentifier = NetworkProtocolHelpers.GetLimitedLengthHostname(this.settings);
// check if clients are null
if(this.receivingUdpClient != null || this.sendingUdpClient != null)
@@ -59,7 +48,7 @@ public class UdpProtocol : CommunicationProtocol
// try opening receiving udp socket
try
{
- this.receivingUdpClient = new UdpClient(this.udpSettings.Port);
+ this.receivingUdpClient = new UdpClient(this.settings.Port);
}
catch (Exception ex)
{
@@ -74,7 +63,7 @@ public class UdpProtocol : CommunicationProtocol
try
{
this.sendingUdpClient = new UdpClient();
- this.sendingUdpClient.Connect(this.udpSettings.Hostname!, this.udpSettings.Port);
+ this.sendingUdpClient.Connect(this.settings.Hostname!, this.settings.Port);
}
catch (Exception ex)
{
@@ -136,7 +125,7 @@ public class UdpProtocol : CommunicationProtocol
{
this.logger.LogException(ex, $"Exception while reading data in {nameof(InternalRead)}", nameof(UdpProtocol));
this.messenger.Send(new GenericUserInterfaceMessage($"UDP client ended reading on port " +
- $"{this.udpSettings!.Port} because of exception.", MessageImportance.Medium));
+ $"{this.settings!.Port} because of exception.", MessageImportance.Medium));
break; // break loop
}
diff --git a/MultiTerm.Protocols/Udp/UdpProtocolSettingsViewModel.cs b/MultiTerm.Protocols/Udp/UdpProtocolSettingsViewModel.cs
index 43d0e95..f5580aa 100644
--- a/MultiTerm.Protocols/Udp/UdpProtocolSettingsViewModel.cs
+++ b/MultiTerm.Protocols/Udp/UdpProtocolSettingsViewModel.cs
@@ -1,84 +1,16 @@
-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;
+using CommunityToolkit.Mvvm.Messaging;
+using MultiTerm.Protocols.Network;
namespace MultiTerm.Protocols.Udp;
-public partial class UdpProtocolSettingsViewModel : ProtocolSettingsViewModel, IUdpProtocolSettings, IRecipient
+public partial class UdpProtocolSettingsViewModel : NetworkProtocolSettingsViewModel, IRecipient
{
public override Types.ProtocolType ProtocolType => Types.ProtocolType.Udp;
- #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 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(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;
- }
}
///
@@ -89,41 +21,4 @@ public partial class UdpProtocolSettingsViewModel : ProtocolSettingsViewModel, I
{
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;
- }
}
diff --git a/MultiTerm.Wpf/View/ShellView.xaml b/MultiTerm.Wpf/View/ShellView.xaml
index ca10d39..6a6a6a9 100644
--- a/MultiTerm.Wpf/View/ShellView.xaml
+++ b/MultiTerm.Wpf/View/ShellView.xaml
@@ -145,12 +145,12 @@
-
-