Multiprocotol Terminalprogram (BAT)
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.
MultiTerm/MultiTerm.Protocols/Udp/UdpProtocol.cs

186 lines
6.3 KiB

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;
public class UdpProtocol : CommunicationProtocol
{
public override Types.ProtocolType ProtocolType => Types.ProtocolType.Udp;
public override string InstanceIdentifier { get; protected set; } = string.Empty;
private INetworkProtocolSettings? settings;
private UdpClient? receivingUdpClient;
private UdpClient? sendingUdpClient;
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 INetworkProtocolSettings networkSettings)
{
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.settings = networkSettings;
// update identifier
this.InstanceIdentifier = NetworkProtocolHelpers.GetLimitedLengthHostname(this.settings);
// check if clients are null
if(this.receivingUdpClient != null || this.sendingUdpClient != null)
{
throw new Exception($"A UDP client was not null when {nameof(InternalConnect)} was called: " +
$"{nameof(receivingUdpClient)} isnull={this.receivingUdpClient == null}," +
$"{nameof(sendingUdpClient)} isnull={this.sendingUdpClient == null}");
}
/* create udp clients */
// try opening receiving udp socket
try
{
this.receivingUdpClient = new UdpClient(this.settings.Port);
}
catch (Exception ex)
{
this.logger.LogException(ex, $"'{nameof(InternalConnect)}()'Opening Receiving UDP socket failed:", nameof(UdpProtocol));
// rollback
this.InternalDisconnect();
return false;
}
// try opening sending udp socket
try
{
this.sendingUdpClient = new UdpClient();
this.sendingUdpClient.Connect(this.settings.Hostname!, this.settings.Port);
}
catch (Exception ex)
{
this.logger.LogException(ex, $"'{nameof(InternalConnect)}()'Opening Sending UDP Socket failed:", nameof(UdpProtocol));
// rollback
this.InternalDisconnect();
return false;
}
return true;
}
protected override void InternalDisconnect()
{
// close receiving udp client
if(this.receivingUdpClient != null)
{
this.receivingUdpClient?.Close();
this.receivingUdpClient?.Dispose();
this.receivingUdpClient = null;
}
// close sending udp client
if (this.sendingUdpClient != null)
{
this.sendingUdpClient?.Close();
this.sendingUdpClient?.Dispose();
this.sendingUdpClient = null;
}
}
protected override void InternalRead(CancellationToken ct)
{
while(ct.IsCancellationRequested == false)
{
// if receiving Udp Client is null => break
if (this.receivingUdpClient == null)
{
this.OnUnintentionallyDisconnected();
break; // break loop
}
// try receive message
UdpReceiveResult receivedResult;
try
{
receivedResult = this.receivingUdpClient.ReceiveAsync(ct).GetAwaiter().GetResult();
}
catch (OperationCanceledException) // intentionally cancelled => just break
{
break;
}
catch (ObjectDisposedException objex)
{
this.logger.LogException(objex, $"ObjectDisposedException while sending data in {nameof(InternalRead)}", nameof(UdpProtocol));
this.OnUnintentionallyDisconnected();
break; // break loop
}
catch (Exception ex)
{
this.logger.LogException(ex, $"Exception while reading data in {nameof(InternalRead)}", nameof(UdpProtocol));
this.messenger.Send<IUserInterfaceMessage>(new GenericUserInterfaceMessage($"UDP client ended reading on port " +
$"{this.settings!.Port} because of exception.", MessageImportance.Medium));
break; // break loop
}
// any data received?
byte[] receivedBytes = receivedResult.Buffer;
if (receivedBytes.Length > 0)
{
foreach (byte b in receivedBytes)
{
// report received data
this.OnReceivedData(new ExtendedByte(b));
}
}
}
}
protected override bool InternalSendBytes(byte[] bytes)
{
// if sending Udp Client is null => return error
if (this.sendingUdpClient == null)
{
this.OnUnintentionallyDisconnected();
return false;
}
// check for empty bytes array
if (bytes == null || bytes.Length == 0)
{
this.logger.LogWarn($"'{nameof(InternalSendBytes)}()' got null or empty bytes array.", nameof(UdpProtocol));
return false;
}
// try sending the data
try
{
this.sendingUdpClient.Send(bytes, bytes.Length);
}
catch (ObjectDisposedException objex)
{
this.logger.LogException(objex, $"ObjectDisposedException while sending data in {nameof(InternalSendBytes)}", nameof(UdpProtocol));
this.OnUnintentionallyDisconnected();
return false;
}
catch (Exception ex)
{
this.logger.LogException(ex, $"Exception while sending data in {nameof(InternalSendBytes)}", nameof(UdpProtocol));
return false;
}
foreach (byte b in bytes)
{
// report sent data
this.OnSentData(new ExtendedByte(b));
}
return true;
}
}