Refactor code.

This commit is contained in:
Christian
2021-10-24 21:19:40 +02:00
parent 5af54963a0
commit 43e4038212
39 changed files with 500 additions and 463 deletions
@@ -84,7 +84,7 @@ namespace MQTTnet.AspNetCore
_output = Connection.Transport.Output;
}
public Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
public Task DisconnectAsync(CancellationToken cancellationToken)
{
_input?.Complete();
_output?.Complete();
@@ -205,25 +205,36 @@ namespace MQTTnet.Extensions.WebSocket4Net
_webSocket.Open();
#pragma warning restore AsyncFixer02 // Long-running or blocking operations inside an async method
var exception = await MqttTaskTimeout.WaitAsync(c =>
using (var timeoutCts = new CancellationTokenSource(_clientOptions.CommunicationTimeout))
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken))
{
c.Register(() => taskCompletionSource.TrySetCanceled());
return taskCompletionSource.Task;
}, _clientOptions.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
if (exception != null)
{
if (exception is AuthenticationException authenticationException)
using (linkedCts.Token.Register(() => taskCompletionSource.TrySetCanceled()))
{
throw new MqttCommunicationException(authenticationException.InnerException);
}
try
{
await taskCompletionSource.Task.ConfigureAwait(false);
}
catch (Exception exception)
{
var timeoutReached = timeoutCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested;
if (timeoutReached)
{
throw new MqttCommunicationTimedOutException(exception);
}
if (exception is AuthenticationException authenticationException)
{
throw new MqttCommunicationException(authenticationException.InnerException);
}
if (exception is OperationCanceledException)
{
throw new MqttCommunicationTimedOutException();
}
if (exception is OperationCanceledException)
{
throw new MqttCommunicationTimedOutException();
}
throw new MqttCommunicationException(exception);
throw new MqttCommunicationException(exception);
}
}
}
}
catch (OperationCanceledException)
@@ -25,7 +25,7 @@ namespace MQTTnet.Adapter
Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken);
Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken);
Task DisconnectAsync(CancellationToken cancellationToken);
Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken);
+16 -32
View File
@@ -76,40 +76,28 @@ namespace MQTTnet.Adapter
}
catch (Exception exception)
{
if (IsWrappedException(exception))
if (!WrapAndThrowException(exception))
{
throw;
}
WrapAndThrowException(exception);
}
}
public async Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
public async Task DisconnectAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
try
{
if (timeout == TimeSpan.Zero)
{
await _channel.DisconnectAsync(cancellationToken).ConfigureAwait(false);
}
else
{
await MqttTaskTimeout.WaitAsync(
t => _channel.DisconnectAsync(t), timeout, cancellationToken).ConfigureAwait(false);
}
await _channel.DisconnectAsync(cancellationToken).ConfigureAwait(false);
}
catch (Exception exception)
{
if (IsWrappedException(exception))
if (!WrapAndThrowException(exception))
{
throw;
}
WrapAndThrowException(exception);
}
}
@@ -136,12 +124,10 @@ namespace MQTTnet.Adapter
}
catch (Exception exception)
{
if (IsWrappedException(exception))
if (!WrapAndThrowException(exception))
{
throw;
}
WrapAndThrowException(exception);
}
finally
{
@@ -192,12 +178,10 @@ namespace MQTTnet.Adapter
}
catch (Exception exception)
{
if (IsWrappedException(exception))
if (!WrapAndThrowException(exception))
{
throw;
}
WrapAndThrowException(exception);
}
return null;
@@ -386,17 +370,17 @@ namespace MQTTnet.Adapter
return value;
}
static bool IsWrappedException(Exception exception)
{
return exception is OperationCanceledException ||
exception is MqttCommunicationTimedOutException ||
exception is MqttCommunicationException ||
exception is MqttProtocolViolationException;
}
static void WrapAndThrowException(Exception exception)
static bool WrapAndThrowException(Exception exception)
{
if (exception is OperationCanceledException ||
exception is MqttCommunicationTimedOutException ||
exception is MqttCommunicationException ||
exception is MqttProtocolViolationException)
{
return false;
}
if (exception is IOException && exception.InnerException is SocketException innerException)
{
exception = innerException;
+24 -28
View File
@@ -23,6 +23,7 @@ namespace MQTTnet.Client
{
public class MqttClient : Disposable, IMqttClient
{
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
readonly MqttPacketIdentifierProvider _packetIdentifierProvider = new MqttPacketIdentifierProvider();
readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
readonly object _disconnectLock = new object();
@@ -156,8 +157,7 @@ namespace MQTTnet.Client
if (clientWasConnected)
{
var disconnectPacketFactory = new MqttDisconnectPacketFactory();
var disconnectPacket = disconnectPacketFactory.Create(options);
var disconnectPacket = _packetFactories.Disconnect.Create(options);
await SendAsync(disconnectPacket, cancellationToken).ConfigureAwait(false);
}
}
@@ -207,8 +207,7 @@ namespace MQTTnet.Client
ThrowIfDisposed();
ThrowIfNotConnected();
var subscribePacketFactory = new MqttSubscribePacketFactory();
var subscribePacket = subscribePacketFactory.Create(options);
var subscribePacket = _packetFactories.Subscribe.Create(options);
subscribePacket.PacketIdentifier = _packetIdentifierProvider.GetNextPacketIdentifier();
var subAckPacket = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket, cancellationToken).ConfigureAwait(false);
@@ -223,9 +222,8 @@ namespace MQTTnet.Client
ThrowIfDisposed();
ThrowIfNotConnected();
var unsubscribeFactory = new MqttUnsubscribePacketFactory();
var unsubscribePacket = unsubscribeFactory.Create(options);
var unsubscribePacket = _packetFactories.Unsubscribe.Create(options);
unsubscribePacket.PacketIdentifier = _packetIdentifierProvider.GetNextPacketIdentifier();
var unsubAckPacket = await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, cancellationToken).ConfigureAwait(false);
@@ -243,10 +241,7 @@ namespace MQTTnet.Client
ThrowIfDisposed();
ThrowIfNotConnected();
var publishPacketFactory = new MqttPublishPacketFactory();
var publishPacket = publishPacketFactory.Create(applicationMessage);
//_adapter.PacketFormatterAdapter.DataConverter.CreatePublishPacket(applicationMessage);
var publishPacket = _packetFactories.Publish.Create(applicationMessage);
switch (applicationMessage.QualityOfServiceLevel)
{
@@ -303,8 +298,7 @@ namespace MQTTnet.Client
try
{
var connectPacketFactory = new MqttConnectPacketFactory();
var connectPacket = connectPacketFactory.Create(options);
var connectPacket = _packetFactories.Connect.Create(options);
var connAckPacket = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket, cancellationToken).ConfigureAwait(false);
@@ -336,7 +330,10 @@ namespace MQTTnet.Client
void ThrowIfConnected(string message)
{
if (IsConnected) throw new MqttProtocolViolationException(message);
if (IsConnected)
{
throw new MqttProtocolViolationException(message);
}
}
Task DisconnectInternalAsync(Task sender, Exception exception, MqttClientConnectResult connectResult)
@@ -360,7 +357,11 @@ namespace MQTTnet.Client
if (_adapter != null)
{
_logger.Verbose("Disconnecting [Timeout={0}]", Options.CommunicationTimeout);
await _adapter.DisconnectAsync(Options.CommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
using (var timeout = new CancellationTokenSource(Options.CommunicationTimeout))
{
await _adapter.DisconnectAsync(timeout.Token).ConfigureAwait(false);
}
}
_logger.Verbose("Disconnected from adapter.");
@@ -434,7 +435,7 @@ namespace MQTTnet.Client
packetIdentifier = packetWithIdentifier.PacketIdentifier;
}
using (var packetAwaiter = _packetDispatcher.AddAwaitable<TResponsePacket>(packetIdentifier))
using (var packetAwaitable = _packetDispatcher.AddAwaitable<TResponsePacket>(packetIdentifier))
{
try
{
@@ -443,12 +444,12 @@ namespace MQTTnet.Client
catch (Exception exception)
{
_logger.Warning(exception, "Error when sending request packet ({0}).", requestPacket.GetType().Name);
packetAwaiter.Fail(exception);
packetAwaitable.Fail(exception);
}
try
{
return await packetAwaiter.WaitOneAsync(Options.CommunicationTimeout).ConfigureAwait(false);
return await packetAwaitable.WaitOneAsync(Options.CommunicationTimeout).ConfigureAwait(false);
}
catch (Exception exception)
{
@@ -686,8 +687,7 @@ namespace MQTTnet.Client
{
if (!eventArgs.ProcessingFailed)
{
var pubAckPacketFactory = new MqttPubAckPacketFactory();
var pubAckPacket = pubAckPacketFactory.Create(eventArgs);
var pubAckPacket = _packetFactories.PubAck.Create(eventArgs);
return SendAsync(pubAckPacket, cancellationToken);
}
}
@@ -695,8 +695,7 @@ namespace MQTTnet.Client
{
if (!eventArgs.ProcessingFailed)
{
var pubRecPacketFactory = new MqttPubRecPacketFactory();
var pubRecPacket = pubRecPacketFactory.Create(eventArgs);
var pubRecPacket = _packetFactories.PubRec.Create(eventArgs);
return SendAsync(pubRecPacket, cancellationToken);
}
}
@@ -714,8 +713,7 @@ namespace MQTTnet.Client
{
// The packet is unknown. Probably due to a restart of the client.
// So wen send this to the server to trigger a full resend of the message.
var pubRelPacketFactory = new MqttPubRelPacketFactory();
var pubRelPacket = pubRelPacketFactory.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.PacketIdentifierNotFound);
var pubRelPacket = _packetFactories.PubRel.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.PacketIdentifierNotFound);
return SendAsync(pubRelPacket, cancellationToken);
}
@@ -724,8 +722,7 @@ namespace MQTTnet.Client
Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
{
var pubCompPacketFactory = new MqttPubCompPacketFactory();
var pubCompPacket =pubCompPacketFactory.Create(pubRelPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubCompPacket = _packetFactories.PubComp.Create(pubRelPacket, MqttApplicationMessageReceivedReasonCode.Success);
return SendAsync(pubCompPacket, cancellationToken);
}
@@ -774,8 +771,7 @@ namespace MQTTnet.Client
var pubRecPacket = await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket, cancellationToken).ConfigureAwait(false);
var pubRelPacketFactory = new MqttPubRelPacketFactory();
var pubRelPacket = pubRelPacketFactory.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubRelPacket = _packetFactories.PubRel.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubCompPacket = await SendAndReceiveAsync<MqttPubCompPacket>(pubRelPacket, cancellationToken).ConfigureAwait(false);
@@ -1,12 +1,14 @@
using System.Collections.Generic;
using System.Collections.Generic;
using MQTTnet.Packets;
namespace MQTTnet.Client.Publishing
{
public sealed class MqttClientPublishResult
{
public ushort? PacketIdentifier { get; set; }
/// <summary>
/// Gets the packet identifier which was used for this publish.
/// </summary>
public ushort PacketIdentifier { get; set; }
/// <summary>
/// Gets or sets the reason code.
@@ -17,7 +17,6 @@ namespace MQTTnet.Formatter
Password = clientOptions.Credentials?.Password,
CleanSession = clientOptions.CleanSession,
KeepAlivePeriod = (ushort) clientOptions.KeepAlivePeriod.TotalSeconds,
WillMessage = clientOptions.WillMessage,
Properties =
{
AuthenticationMethod = clientOptions.AuthenticationMethod,
@@ -32,6 +31,26 @@ namespace MQTTnet.Formatter
}
};
if (clientOptions.WillMessage != null)
{
connectPacket.WillFlag = true;
connectPacket.WillTopic = clientOptions.WillMessage.Topic;
connectPacket.WillQoS = clientOptions.WillMessage.QualityOfServiceLevel;
connectPacket.WillMessage = clientOptions.WillMessage.Payload;
connectPacket.WillRetain = clientOptions.WillMessage.Retain;
connectPacket.WillProperties.ContentType = clientOptions.WillMessage.ContentType;
connectPacket.WillProperties.CorrelationData = clientOptions.WillMessage.CorrelationData;
connectPacket.WillProperties.ResponseTopic = clientOptions.WillMessage.ResponseTopic;
connectPacket.WillProperties.MessageExpiryInterval = clientOptions.WillMessage.MessageExpiryInterval;
connectPacket.WillProperties.PayloadFormatIndicator = clientOptions.WillMessage.PayloadFormatIndicator;
//connectPacket.WillProperties.WillDelayInterval = clientOptions.WillMessage.;
if (clientOptions.WillMessage.UserProperties != null)
{
connectPacket.WillProperties.UserProperties.AddRange(clientOptions.WillMessage.UserProperties);
}
}
if (clientOptions.UserProperties != null)
{
connectPacket.Properties.UserProperties.AddRange(clientOptions.UserProperties);
@@ -0,0 +1,29 @@
namespace MQTTnet.Formatter
{
public sealed class MqttPacketFactories
{
public MqttConnectPacketFactory Connect { get; } = new MqttConnectPacketFactory();
public MqttConnAckPacketFactory ConnAck { get; } = new MqttConnAckPacketFactory();
public MqttDisconnectPacketFactory Disconnect { get; } = new MqttDisconnectPacketFactory();
public MqttSubscribePacketFactory Subscribe { get; } = new MqttSubscribePacketFactory();
public MqttSubAckPacketFactory SubAck { get; } = new MqttSubAckPacketFactory();
public MqttUnsubscribePacketFactory Unsubscribe { get; } = new MqttUnsubscribePacketFactory();
public MqttUnsubAckPacketFactory UnsubAck { get; } = new MqttUnsubAckPacketFactory();
public MqttPublishPacketFactory Publish { get; } = new MqttPublishPacketFactory();
public MqttPubAckPacketFactory PubAck { get; } = new MqttPubAckPacketFactory();
public MqttPubRelPacketFactory PubRel { get; } = new MqttPubRelPacketFactory();
public MqttPubRecPacketFactory PubRec { get; } = new MqttPubRecPacketFactory();
public MqttPubCompPacketFactory PubComp { get; } = new MqttPubCompPacketFactory();
}
}
@@ -1,4 +1,5 @@
using System;
using MQTTnet.Exceptions;
using MQTTnet.Packets;
namespace MQTTnet.Formatter
@@ -41,5 +42,36 @@ namespace MQTTnet.Formatter
return packet;
}
public MqttPublishPacket Create(MqttConnectPacket connectPacket)
{
if (connectPacket == null) throw new ArgumentNullException(nameof(connectPacket));
if (!connectPacket.WillFlag)
{
throw new MqttProtocolViolationException("The CONNECT packet contains no will message (WillFlag).");
}
var packet = new MqttPublishPacket
{
Topic = connectPacket.WillTopic,
Payload = connectPacket.WillMessage,
QualityOfServiceLevel = connectPacket.WillQoS,
Retain = connectPacket.WillRetain,
Dup = false,
Properties =
{
ContentType = connectPacket.WillProperties.ContentType,
CorrelationData = connectPacket.WillProperties.CorrelationData,
MessageExpiryInterval = connectPacket.WillProperties.MessageExpiryInterval,
PayloadFormatIndicator = connectPacket.WillProperties.PayloadFormatIndicator,
ResponseTopic = connectPacket.WillProperties.ResponseTopic
}
};
packet.Properties.UserProperties.AddRange(connectPacket.WillProperties.UserProperties);
return packet;
}
}
}
@@ -11,7 +11,7 @@ namespace MQTTnet.Formatter.V3
public class MqttV310PacketFormatter : IMqttPacketFormatter
{
const int FixedHeaderSize = 1;
static readonly MqttDisconnectPacket DisconnectPacket = new MqttDisconnectPacket();
readonly IMqttPacketWriter _packetWriter;
@@ -30,7 +30,7 @@ namespace MQTTnet.Formatter.V3
_packetWriter.Seek(5);
var fixedHeader = EncodePacket(packet, _packetWriter);
var remainingLength = (uint)(_packetWriter.Length - 5);
var remainingLength = (uint) (_packetWriter.Length - 5);
var remainingLengthSize = MqttPacketWriter.GetLengthOfVariableInteger(remainingLength);
@@ -57,7 +57,7 @@ namespace MQTTnet.Formatter.V3
throw new MqttProtocolViolationException($"The packet type is invalid ({controlPacketType}).");
}
switch ((MqttControlPacketType)controlPacketType)
switch ((MqttControlPacketType) controlPacketType)
{
case MqttControlPacketType.Connect: return DecodeConnectPacket(receivedMqttPacket.BodyReader);
case MqttControlPacketType.ConnAck: return DecodeConnAckPacket(receivedMqttPacket.BodyReader);
@@ -187,7 +187,7 @@ namespace MQTTnet.Formatter.V3
var topicFilter = new MqttTopicFilter
{
Topic = body.ReadStringWithLengthPrefix(),
QualityOfServiceLevel = (MqttQualityOfServiceLevel)body.ReadByte()
QualityOfServiceLevel = (MqttQualityOfServiceLevel) body.ReadByte()
};
packet.TopicFilters.Add(topicFilter);
@@ -201,7 +201,7 @@ namespace MQTTnet.Formatter.V3
ThrowIfBodyIsEmpty(receivedMqttPacket.BodyReader);
var retain = (receivedMqttPacket.FixedHeader & 0x1) > 0;
var qualityOfServiceLevel = (MqttQualityOfServiceLevel)(receivedMqttPacket.FixedHeader >> 1 & 0x3);
var qualityOfServiceLevel = (MqttQualityOfServiceLevel) (receivedMqttPacket.FixedHeader >> 1 & 0x3);
var dup = (receivedMqttPacket.FixedHeader & 0x8) > 0;
var topic = receivedMqttPacket.BodyReader.ReadStringWithLengthPrefix();
@@ -267,13 +267,12 @@ namespace MQTTnet.Formatter.V3
if (willFlag)
{
packet.WillMessage = new MqttApplicationMessage
{
Topic = body.ReadStringWithLengthPrefix(),
Payload = body.ReadWithLengthPrefix(),
QualityOfServiceLevel = (MqttQualityOfServiceLevel)willQoS,
Retain = willRetain
};
packet.WillFlag = true;
packet.WillQoS = (MqttQualityOfServiceLevel) willQoS;
packet.WillRetain = willRetain;
packet.WillTopic = body.ReadStringWithLengthPrefix();
packet.WillMessage = body.ReadWithLengthPrefix();
}
if (usernameFlag)
@@ -301,7 +300,7 @@ namespace MQTTnet.Formatter.V3
while (!body.EndOfStream)
{
packet.ReturnCodes.Add((MqttSubscribeReturnCode)body.ReadByte());
packet.ReturnCodes.Add((MqttSubscribeReturnCode) body.ReadByte());
}
return packet;
@@ -314,7 +313,7 @@ namespace MQTTnet.Formatter.V3
var packet = new MqttConnAckPacket();
body.ReadByte(); // Reserved.
packet.ReturnCode = (MqttConnectReturnCode)body.ReadByte();
packet.ReturnCode = (MqttConnectReturnCode) body.ReadByte();
return packet;
}
@@ -351,12 +350,12 @@ namespace MQTTnet.Formatter.V3
connectFlags |= 0x2;
}
if (packet.WillMessage != null)
if (packet.WillFlag)
{
connectFlags |= 0x4;
connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);
connectFlags |= (byte) ((byte) packet.WillQoS << 3);
if (packet.WillMessage.Retain)
if (packet.WillRetain)
{
connectFlags |= 0x20;
}
@@ -381,10 +380,10 @@ namespace MQTTnet.Formatter.V3
packetWriter.Write(packet.KeepAlivePeriod);
packetWriter.WriteWithLengthPrefix(packet.ClientId);
if (packet.WillMessage != null)
if (packet.WillFlag)
{
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
packetWriter.WriteWithLengthPrefix(packet.WillTopic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage);
}
if (packet.Username != null)
@@ -403,7 +402,7 @@ namespace MQTTnet.Formatter.V3
protected virtual byte EncodeConnAckPacket(MqttConnAckPacket packet, IMqttPacketWriter packetWriter)
{
packetWriter.Write(0); // Reserved.
packetWriter.Write((byte)packet.ReturnCode);
packetWriter.Write((byte) packet.ReturnCode);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
}
@@ -455,7 +454,7 @@ namespace MQTTnet.Formatter.V3
fixedHeader |= 0x01;
}
fixedHeader |= (byte)((byte)packet.QualityOfServiceLevel << 1);
fixedHeader |= (byte) ((byte) packet.QualityOfServiceLevel << 1);
if (packet.Dup)
{
@@ -525,14 +524,14 @@ namespace MQTTnet.Formatter.V3
{
throw new MqttProtocolViolationException("RetainAsPublished is not supported in 3.1.1.");
}
if (topicFilter.RetainHandling != MqttRetainHandling.SendAtSubscribe)
{
throw new MqttProtocolViolationException("RetainHandling is not supported in 3.1.1.");
}
packetWriter.WriteWithLengthPrefix(topicFilter.Topic);
packetWriter.Write((byte)topicFilter.QualityOfServiceLevel);
packetWriter.Write((byte) topicFilter.QualityOfServiceLevel);
}
}
@@ -552,7 +551,7 @@ namespace MQTTnet.Formatter.V3
{
foreach (var packetSubscribeReturnCode in packet.ReturnCodes)
{
packetWriter.Write((byte)packetSubscribeReturnCode);
packetWriter.Write((byte) packetSubscribeReturnCode);
}
}
@@ -606,4 +605,4 @@ namespace MQTTnet.Formatter.V3
}
}
}
}
}
@@ -24,12 +24,12 @@ namespace MQTTnet.Formatter.V3
connectFlags |= 0x2;
}
if (packet.WillMessage != null)
if (packet.WillFlag)
{
connectFlags |= 0x4;
connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);
connectFlags |= (byte)((byte)packet.WillQoS << 3);
if (packet.WillMessage.Retain)
if (packet.WillRetain)
{
connectFlags |= 0x20;
}
@@ -54,10 +54,10 @@ namespace MQTTnet.Formatter.V3
packetWriter.Write(packet.KeepAlivePeriod);
packetWriter.WriteWithLengthPrefix(packet.ClientId);
if (packet.WillMessage != null)
if (packet.WillFlag)
{
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
packetWriter.WriteWithLengthPrefix(packet.WillTopic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage);
}
if (packet.Username != null)
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using MQTTnet.Adapter;
using MQTTnet.Exceptions;
using MQTTnet.Packets;
@@ -72,11 +71,9 @@ namespace MQTTnet.Formatter.V5
if (willMessageFlag)
{
packet.WillMessage = new MqttApplicationMessage
{
QualityOfServiceLevel = (MqttQualityOfServiceLevel)willMessageQoS,
Retain = willMessageRetainFlag
};
packet.WillFlag = true;
packet.WillQoS = (MqttQualityOfServiceLevel) willMessageQoS;
packet.WillRetain = willMessageRetainFlag;
}
packet.KeepAlivePeriod = body.ReadTwoByteInteger();
@@ -128,7 +125,7 @@ namespace MQTTnet.Formatter.V5
packet.ClientId = body.ReadStringWithLengthPrefix();
if (packet.WillMessage != null)
if (packet.WillFlag)
{
var willPropertiesReader = new MqttV500PropertiesReader(body);
@@ -136,50 +133,31 @@ namespace MQTTnet.Formatter.V5
{
if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.PayloadFormatIndicator)
{
packet.WillMessage.PayloadFormatIndicator = propertiesReader.ReadPayloadFormatIndicator();
packet.WillProperties.PayloadFormatIndicator = propertiesReader.ReadPayloadFormatIndicator();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.MessageExpiryInterval)
{
packet.WillMessage.MessageExpiryInterval = propertiesReader.ReadMessageExpiryInterval();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.TopicAlias)
{
packet.WillMessage.TopicAlias = propertiesReader.ReadTopicAlias();
packet.WillProperties.MessageExpiryInterval = propertiesReader.ReadMessageExpiryInterval();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.ResponseTopic)
{
packet.WillMessage.ResponseTopic = propertiesReader.ReadResponseTopic();
packet.WillProperties.ResponseTopic = propertiesReader.ReadResponseTopic();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.CorrelationData)
{
packet.WillMessage.CorrelationData = propertiesReader.ReadCorrelationData();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.SubscriptionIdentifier)
{
if (packet.WillMessage.SubscriptionIdentifiers == null)
{
packet.WillMessage.SubscriptionIdentifiers = new List<uint>();
}
packet.WillMessage.SubscriptionIdentifiers.Add(propertiesReader.ReadSubscriptionIdentifier());
packet.WillProperties.CorrelationData = propertiesReader.ReadCorrelationData();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.ContentType)
{
packet.WillMessage.ContentType = propertiesReader.ReadContentType();
packet.WillProperties.ContentType = propertiesReader.ReadContentType();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.WillDelayInterval)
{
// This is a special case!
packet.Properties.WillDelayInterval = propertiesReader.ReadWillDelayInterval();
packet.WillProperties.WillDelayInterval = propertiesReader.ReadWillDelayInterval();
}
else if (willPropertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
{
if (packet.WillMessage.UserProperties == null)
{
packet.WillMessage.UserProperties = new List<MqttUserProperty>();
}
propertiesReader.AddUserPropertyTo(packet.Properties.UserProperties);
propertiesReader.AddUserPropertyTo(packet.WillProperties.UserProperties);
}
else
{
@@ -187,8 +165,8 @@ namespace MQTTnet.Formatter.V5
}
}
packet.WillMessage.Topic = body.ReadStringWithLengthPrefix();
packet.WillMessage.Payload = body.ReadWithLengthPrefix();
packet.WillTopic = body.ReadStringWithLengthPrefix();
packet.WillMessage = body.ReadWithLengthPrefix();
}
if (usernameFlag)
@@ -88,12 +88,12 @@ namespace MQTTnet.Formatter.V5
connectFlags |= 0x2;
}
if (packet.WillMessage != null)
if (packet.WillFlag)
{
connectFlags |= 0x4;
connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);
connectFlags |= (byte)((byte)packet.WillQoS << 3);
if (packet.WillMessage.Retain)
if (packet.WillRetain)
{
connectFlags |= 0x20;
}
@@ -135,25 +135,23 @@ namespace MQTTnet.Formatter.V5
packetWriter.WriteWithLengthPrefix(packet.ClientId);
if (packet.WillMessage != null)
if (packet.WillFlag)
{
var willPropertiesWriter = new MqttV500PropertiesWriter();
willPropertiesWriter.WritePayloadFormatIndicator(packet.WillMessage.PayloadFormatIndicator);
willPropertiesWriter.WriteMessageExpiryInterval(packet.WillMessage.MessageExpiryInterval);
willPropertiesWriter.WriteTopicAlias(packet.WillMessage.TopicAlias);
willPropertiesWriter.WriteResponseTopic(packet.WillMessage.ResponseTopic);
willPropertiesWriter.WriteCorrelationData(packet.WillMessage.CorrelationData);
willPropertiesWriter.WriteSubscriptionIdentifiers(packet.WillMessage.SubscriptionIdentifiers);
willPropertiesWriter.WriteContentType(packet.WillMessage.ContentType);
willPropertiesWriter.WriteUserProperties(packet.WillMessage.UserProperties);
willPropertiesWriter.WritePayloadFormatIndicator(packet.WillProperties.PayloadFormatIndicator);
willPropertiesWriter.WriteMessageExpiryInterval(packet.WillProperties.MessageExpiryInterval);
willPropertiesWriter.WriteResponseTopic(packet.WillProperties.ResponseTopic);
willPropertiesWriter.WriteCorrelationData(packet.WillProperties.CorrelationData);
willPropertiesWriter.WriteContentType(packet.WillProperties.ContentType);
willPropertiesWriter.WriteUserProperties(packet.WillProperties.UserProperties);
// This is a special case!
willPropertiesWriter.WriteWillDelayInterval(packet.Properties?.WillDelayInterval);
willPropertiesWriter.WriteTo(packetWriter);
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
packetWriter.WriteWithLengthPrefix(packet.WillTopic);
packetWriter.WriteWithLengthPrefix(packet.WillMessage);
}
if (packet.Username != null)
@@ -143,7 +143,7 @@ namespace MQTTnet.Formatter.V5
return _body.ReadVariableLengthInteger();
}
public MqttPayloadFormatIndicator? ReadPayloadFormatIndicator()
public MqttPayloadFormatIndicator ReadPayloadFormatIndicator()
{
return (MqttPayloadFormatIndicator)_body.ReadByte();
}
+25 -9
View File
@@ -11,11 +11,11 @@ namespace MQTTnet.Internal
{
readonly object _syncRoot = new object();
readonly Queue<MqttPacketBusItem>[] _partitions = new Queue<MqttPacketBusItem>[]
readonly LinkedList<MqttPacketBusItem>[] _partitions = new LinkedList<MqttPacketBusItem>[]
{
new Queue<MqttPacketBusItem>(4096),
new Queue<MqttPacketBusItem>(1028),
new Queue<MqttPacketBusItem>(128)
new LinkedList<MqttPacketBusItem>(),
new LinkedList<MqttPacketBusItem>(),
new LinkedList<MqttPacketBusItem>()
};
readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0);
@@ -33,11 +33,14 @@ namespace MQTTnet.Internal
}
}
public int DataPacketsCount()
public int DataPacketsCount
{
lock (_syncRoot)
get
{
return _partitions[(int)MqttPacketBusPartition.Data].Count;
lock (_syncRoot)
{
return _partitions[(int) MqttPacketBusPartition.Data].Count;
}
}
}
@@ -55,7 +58,7 @@ namespace MQTTnet.Internal
lock (_syncRoot)
{
_partitions[(int) partition].Enqueue(item);
_partitions[(int) partition].AddLast(item);
}
_semaphore.Release();
@@ -85,7 +88,9 @@ namespace MQTTnet.Internal
if (_partitions[_activePartition].Count > 0)
{
return _partitions[_activePartition].Dequeue();
var item = _partitions[_activePartition].First;
_partitions[_activePartition].RemoveFirst();
return item.Value;
}
}
}
@@ -102,5 +107,16 @@ namespace MQTTnet.Internal
{
_semaphore?.Dispose();
}
public void Clear()
{
lock (_syncRoot)
{
foreach (var partition in _partitions)
{
partition.Clear();
}
}
}
}
}
@@ -30,29 +30,5 @@ namespace MQTTnet.Internal
}
}
}
public static async Task<TResult> WaitAsync<TResult>(Func<CancellationToken, Task<TResult>> action, TimeSpan timeout, CancellationToken cancellationToken)
{
if (action == null) throw new ArgumentNullException(nameof(action));
using (var timeoutCts = new CancellationTokenSource(timeout))
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken))
{
try
{
return await action(linkedCts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException exception)
{
var timeoutReached = timeoutCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested;
if (timeoutReached)
{
throw new MqttCommunicationTimedOutException(exception);
}
throw;
}
}
}
}
}
@@ -113,7 +113,7 @@ namespace MQTTnet.LowLevelClient
{
try
{
await _adapter.DisconnectAsync(_options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
await _adapter.DisconnectAsync(cancellationToken).ConfigureAwait(false);
}
catch (Exception exception)
{
+3 -3
View File
@@ -51,7 +51,7 @@ namespace MQTTnet
/// The feature is very similar to the HTTP header concept.
/// Hint: MQTT 5 feature only.
/// </summary>
public List<MqttUserProperty> UserProperties { get; set; }
public List<MqttUserProperty> UserProperties { get; set; } = new List<MqttUserProperty>();
/// <summary>
/// Gets or sets the content type.
@@ -74,7 +74,7 @@ namespace MQTTnet
/// If no payload format indicator is provided, the default value is 0.
/// Hint: MQTT 5 feature only.
/// </summary>
public MqttPayloadFormatIndicator? PayloadFormatIndicator { get; set; }
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified;
/// <summary>
/// Gets or sets the message expiry interval.
@@ -84,7 +84,7 @@ namespace MQTTnet
/// When the retained=true option is set on the PUBLISH message, this interval also defines how long a message is retained on a topic.
/// Hint: MQTT 5 feature only.
/// </summary>
public uint? MessageExpiryInterval { get; set; }
public uint MessageExpiryInterval { get; set; }
/// <summary>
/// Gets or sets the topic alias.
@@ -87,7 +87,7 @@ namespace MQTTnet
/// When the retained=true option is set on the PUBLISH message, this interval also defines how long a message is retained on a topic.
/// Hint: MQTT 5 feature only.
/// </summary>
uint? _messageExpiryInterval;
uint _messageExpiryInterval;
/// <summary>
/// The payload format indicator.
@@ -97,7 +97,7 @@ namespace MQTTnet
/// If no payload format indicator is provided, the default value is 0.
/// Hint: MQTT 5 feature only.
/// </summary>
MqttPayloadFormatIndicator? _payloadFormatIndicator;
MqttPayloadFormatIndicator _payloadFormatIndicator;
/// <summary>
/// The user properties.
+15 -3
View File
@@ -1,4 +1,6 @@
namespace MQTTnet.Packets
using MQTTnet.Protocol;
namespace MQTTnet.Packets
{
public sealed class MqttConnectPacket : MqttBasePacket
{
@@ -14,13 +16,23 @@
/// Also called "Clean Start" in MQTTv5.
/// </summary>
public bool CleanSession { get; set; }
public MqttApplicationMessage WillMessage { get; set; }
/// <summary>
/// Added in MQTTv5.
/// </summary>
public MqttConnectPacketProperties Properties { get; } = new MqttConnectPacketProperties();
public bool WillFlag { get; set; }
public string WillTopic { get; set; }
public byte[] WillMessage { get; set; }
public MqttQualityOfServiceLevel WillQoS { get; set; } = MqttQualityOfServiceLevel.AtMostOnce;
public bool WillRetain { get; set; }
public MqttConnectPacketWillProperties WillProperties { get; } = new MqttConnectPacketWillProperties();
public override string ToString()
{
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using MQTTnet.Protocol;
namespace MQTTnet.Packets
{
public sealed class MqttConnectPacketWillProperties
{
public uint WillDelayInterval { get; set; }
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified;
public uint MessageExpiryInterval { get; set; }
public string ContentType { get; set; }
public string ResponseTopic { get; set; }
public byte[] CorrelationData { get; set; }
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
}
}
@@ -5,9 +5,9 @@ namespace MQTTnet.Packets
{
public sealed class MqttPublishPacketProperties
{
public MqttPayloadFormatIndicator? PayloadFormatIndicator { get; set; }
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified;
public uint? MessageExpiryInterval { get; set; }
public uint MessageExpiryInterval { get; set; }
public ushort? TopicAlias { get; set; }
@@ -19,12 +19,13 @@ namespace MQTTnet.Server.Internal
{
readonly Dictionary<ushort, string> _topicAlias = new Dictionary<ushort, string>();
readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
readonly MqttClientSessionsManager _sessionsManager;
readonly MqttNetSourceLogger _logger;
readonly IMqttServerOptions _serverOptions;
readonly MqttConnectPacket _connectPacket;
CancellationTokenSource _cancellationToken;
@@ -39,10 +40,10 @@ namespace MQTTnet.Server.Internal
{
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
_sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
ChannelAdapter = channelAdapter ?? throw new ArgumentNullException(nameof(channelAdapter));
Endpoint = channelAdapter.Endpoint;
Session = session ?? throw new ArgumentNullException(nameof(session));
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
@@ -50,10 +51,10 @@ namespace MQTTnet.Server.Internal
_logger = logger.WithSource(nameof(MqttClientConnection));
}
public string ClientId => _connectPacket.ClientId;
public string Id => _connectPacket.ClientId;
public string Endpoint { get; }
public string Endpoint {get;}
public IMqttChannelAdapter ChannelAdapter { get; }
public MqttClientConnectionStatistics Statistics { get; } = new MqttClientConnectionStatistics();
@@ -61,13 +62,13 @@ namespace MQTTnet.Server.Internal
public bool IsRunning { get; private set; }
public ushort KeepAlivePeriod => _connectPacket.KeepAlivePeriod;
public MqttClientSession Session { get; }
public bool IsTakenOver { get; set; }
public bool IsCleanDisconnect { get; private set; }
public async Task StopAsync(MqttClientDisconnectReason reason)
{
IsRunning = false;
@@ -88,7 +89,7 @@ namespace MQTTnet.Server.Internal
{
ChannelAdapter.ResetStatistics();
}
public void Dispose()
{
_cancellationToken.Dispose();
@@ -96,10 +97,11 @@ namespace MQTTnet.Server.Internal
public async Task RunAsync()
{
_logger.Info("Client '{0}': Session started.", ClientId);
_logger.Info("Client '{0}': Session started.", Id);
Session.LatestConnectPacket = _connectPacket;
Session.WillMessageSent = false;
Session.WillMessage = _connectPacket.WillMessage;
using (var cancellationToken = new CancellationTokenSource())
{
_cancellationToken = cancellationToken;
@@ -108,7 +110,8 @@ namespace MQTTnet.Server.Internal
{
Task.Run(() => SendPacketsLoop(cancellationToken.Token), cancellationToken.Token).RunInBackground(_logger);
Session.IsCleanSession = false;
// TODO: Check!.
//Session.IsCleanSession = false;
IsRunning = true;
@@ -117,21 +120,22 @@ namespace MQTTnet.Server.Internal
finally
{
IsRunning = false;
cancellationToken.Cancel();
_cancellationToken = null;
}
}
_packetDispatcher.CancelAll();
if (!IsTakenOver && !IsCleanDisconnect && Session.WillMessage != null)
if (!IsTakenOver && !IsCleanDisconnect && Session.LatestConnectPacket.WillFlag && !Session.WillMessageSent)
{
_sessionsManager.DispatchApplicationMessage(Session.WillMessage, this);
Session.WillMessage = null;
var publishPacket = _packetFactories.Publish.Create(Session.LatestConnectPacket);
_sessionsManager.DispatchPublishPacket(publishPacket, this);
Session.WillMessageSent = true;
}
_logger.Info("Client '{0}': Connection stopped.", ClientId);
_logger.Info("Client '{0}': Connection stopped.", Id);
}
Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
@@ -163,23 +167,19 @@ namespace MQTTnet.Server.Internal
}
else if (packet is MqttPubAckPacket pubAckPacket)
{
// TODO: Do anything!
Session.AcknowledgePublishPacket(pubAckPacket.PacketIdentifier);
}
else if (packet is MqttPubCompPacket pubCompPacket)
{
// TODO: Do anything!
Session.AcknowledgePublishPacket(pubCompPacket.PacketIdentifier);
}
else if (packet is MqttPubRecPacket pubRecPacket)
{
// TODO: Do anything!
// TODO: Send pub rel!
var pubRelPacketFactory = new MqttPubRelPacketFactory();
var pubRelPacket = pubRelPacketFactory.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.Success);
Session.EnqueuePacket(new MqttPacketBusItem(pubRelPacket));
HandleIncomingPubRecPacket(pubRecPacket);
}
else if (packet is MqttPubRelPacket pubRelPacket)
{
await HandleIncomingPubRelPacket(pubRelPacket, cancellationToken).ConfigureAwait(false);
HandleIncomingPubRelPacket(pubRelPacket);
}
else if (packet is MqttSubscribePacket subscribePacket)
{
@@ -220,30 +220,25 @@ namespace MQTTnet.Server.Internal
{
if (exception is MqttCommunicationException)
{
_logger.Warning(exception, "Client '{0}': Communication exception while receiving client packets.", ClientId);
_logger.Warning(exception, "Client '{0}': Communication exception while receiving client packets.", Id);
}
else
{
_logger.Error(exception, "Client '{0}': Error while receiving client packets.", ClientId);
_logger.Error(exception, "Client '{0}': Error while receiving client packets.", Id);
}
}
}
async Task SendPacketsLoop(CancellationToken cancellationToken)
{
//MqttQueuedApplicationMessage queuedApplicationMessage = null;
MqttPacketBusItem packetBusItem = null;
//MqttPublishPacket publishPacket = null;
try
{
while (!cancellationToken.IsCancellationRequested)
{
//queuedApplicationMessage = await Session.DequeuePacketAsync(cancellationToken).ConfigureAwait(false);
packetBusItem = await Session.DequeuePacketAsync(cancellationToken).ConfigureAwait(false);
// Also check the cancellation token here because the dequeue is blocking and may take some time.
if (cancellationToken.IsCancellationRequested)
{
@@ -254,7 +249,7 @@ namespace MQTTnet.Server.Internal
{
await SendPacketAsync(packetBusItem.Packet, cancellationToken).ConfigureAwait(false);
packetBusItem.MarkAsDelivered();
_logger.Verbose("Sent packet '{0}'.", packetBusItem.Packet);
}
catch (OperationCanceledException)
@@ -265,7 +260,7 @@ namespace MQTTnet.Server.Internal
{
packetBusItem.MarkAsFailed(exception);
}
// TODO: Move QoS 1 + 2 to other layer!
// if (queuedApplicationMessage == null)
// {
@@ -305,7 +300,7 @@ namespace MQTTnet.Server.Internal
// }
// }
_logger.Verbose("Client '{0}': Queued application message sent.", ClientId);
_logger.Verbose("Client '{0}': Queued application message sent.", Id);
}
}
catch (OperationCanceledException)
@@ -315,15 +310,15 @@ namespace MQTTnet.Server.Internal
{
if (exception is MqttCommunicationTimedOutException)
{
_logger.Warning(exception, "Client '{0}': Sending publish packet failed: Timeout.", ClientId);
_logger.Warning(exception, "Client '{0}': Sending publish packet failed: Timeout.", Id);
}
else if (exception is MqttCommunicationException)
{
_logger.Warning(exception, "Client '{0}': Sending publish packet failed: Communication exception.", ClientId);
_logger.Warning(exception, "Client '{0}': Sending publish packet failed: Communication exception.", Id);
}
else
{
_logger.Error(exception, "Client '{0}': Sending publish packet failed.", ClientId);
_logger.Error(exception, "Client '{0}': Sending publish packet failed.", Id);
}
if (packetBusItem?.Packet is MqttPublishPacket publishPacket)
@@ -333,23 +328,8 @@ namespace MQTTnet.Server.Internal
publishPacket.Dup = true;
Session.EnqueuePacket(new MqttPacketBusItem(publishPacket));
}
// if (queuedApplicationMessage != null)
// {
// queuedApplicationMessage.IsDuplicate = true;
// Session.ApplicationMessagesQueue.Enqueue(queuedApplicationMessage);
// }
}
// if (publishPacket?.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
// {
// if (queuedApplicationMessage != null)
// {
// queuedApplicationMessage.IsDuplicate = true;
// Session.ApplicationMessagesQueue.Enqueue(queuedApplicationMessage);
// }
// }
StopInternal();
}
}
@@ -387,35 +367,35 @@ namespace MQTTnet.Server.Internal
_cancellationToken?.Cancel();
}
Task HandleIncomingPubRelPacket(MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
void HandleIncomingPubRecPacket(MqttPubRecPacket pubRecPacket)
{
var pubCompPacketFactory = new MqttPubCompPacketFactory();
var pubCompPacket =pubCompPacketFactory.Create(pubRelPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubRelPacket = _packetFactories.PubRel.Create(pubRecPacket, MqttApplicationMessageReceivedReasonCode.Success);
Session.EnqueuePacket(new MqttPacketBusItem(pubRelPacket));
}
void HandleIncomingPubRelPacket(MqttPubRelPacket pubRelPacket)
{
var pubCompPacket = _packetFactories.PubComp.Create(pubRelPacket, MqttApplicationMessageReceivedReasonCode.Success);
Session.EnqueuePacket(new MqttPacketBusItem(pubCompPacket));
//return SendPacketAsync(pubCompPacket, cancellationToken);
return PlatformAbstractionLayer.CompletedTask;
}
async Task HandleIncomingSubscribePacket(MqttSubscribePacket subscribePacket, CancellationToken cancellationToken)
{
var subscribeResult = await Session.SubscriptionsManager.Subscribe(subscribePacket, cancellationToken).ConfigureAwait(false);
var subAckPacketFactory = new MqttSubAckPacketFactory();
var subAckPacket = subAckPacketFactory.Create(subscribePacket, subscribeResult);
var subAckPacket = _packetFactories.SubAck.Create(subscribePacket, subscribeResult);
Session.EnqueuePacket(new MqttPacketBusItem(subAckPacket));
if (subscribeResult.CloseConnection)
{
StopInternal();
return;
}
var publishPacketFactory = new MqttPublishPacketFactory();
foreach (var retainedApplicationMessage in subscribeResult.RetainedApplicationMessages)
{
var publishPacket = publishPacketFactory.Create(retainedApplicationMessage.ApplicationMessage);
var publishPacket = _packetFactories.Publish.Create(retainedApplicationMessage.ApplicationMessage);
Session.EnqueuePacket(new MqttPacketBusItem(publishPacket));
}
}
@@ -424,9 +404,8 @@ namespace MQTTnet.Server.Internal
{
var unsubscribeResult = await Session.SubscriptionsManager.Unsubscribe(unsubscribePacket, cancellationToken).ConfigureAwait(false);
var unsubAckPacketFactory = new MqttUnsubAckPacketFactory();
var unsubAckPacket = unsubAckPacketFactory.Create(unsubscribePacket, unsubscribeResult);
var unsubAckPacket = _packetFactories.UnsubAck.Create(unsubscribePacket, unsubscribeResult);
Session.EnqueuePacket(new MqttPacketBusItem(unsubAckPacket));
if (unsubscribeResult.CloseConnection)
@@ -439,12 +418,8 @@ namespace MQTTnet.Server.Internal
{
HandleTopicAlias(publishPacket);
var applicationMessageFactory = new MqttApplicationMessageFactory();
var applicationMessage = applicationMessageFactory.Create(publishPacket);
_sessionsManager.DispatchPublishPacket(publishPacket, this);
_sessionsManager.DispatchApplicationMessage(applicationMessage, this);
// TODO: Check!
switch (publishPacket.QualityOfServiceLevel)
{
case MqttQualityOfServiceLevel.AtMostOnce:
@@ -454,15 +429,13 @@ namespace MQTTnet.Server.Internal
}
case MqttQualityOfServiceLevel.AtLeastOnce:
{
var pubAckPacketFactory = new MqttPubAckPacketFactory();
var pubAckPacket = pubAckPacketFactory.Create(publishPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubAckPacket = _packetFactories.PubAck.Create(publishPacket, MqttApplicationMessageReceivedReasonCode.Success);
Session.EnqueuePacket(new MqttPacketBusItem(pubAckPacket));
break;
}
case MqttQualityOfServiceLevel.ExactlyOnce:
{
var pubRecPacketFactory = new MqttPubRecPacketFactory();
var pubRecPacket = pubRecPacketFactory.Create(publishPacket, MqttApplicationMessageReceivedReasonCode.Success);
var pubRecPacket = _packetFactories.PubRec.Create(publishPacket, MqttApplicationMessageReceivedReasonCode.Success);
Session.EnqueuePacket(new MqttPacketBusItem(pubRecPacket));
break;
}
@@ -500,7 +473,7 @@ namespace MQTTnet.Server.Internal
}
}
}
async Task TrySendDisconnectPacket(MqttClientDisconnectReason reason)
{
try
@@ -511,8 +484,7 @@ namespace MQTTnet.Server.Internal
ReasonString = reason.ToString()
};
var disconnectPacketFactory = new MqttDisconnectPacketFactory();
var disconnectPacket = disconnectPacketFactory.Create(disconnectOptions);
var disconnectPacket = _packetFactories.Disconnect.Create(disconnectOptions);
using (var timeout = new CancellationTokenSource(_serverOptions.DefaultCommunicationTimeout))
{
@@ -521,10 +493,11 @@ namespace MQTTnet.Server.Internal
}
catch (Exception exception)
{
_logger.Warning(exception, "Client '{{0}}': Error while sending DISCONNECT packet (Reason = {1}).", ClientId, reason);
_logger.Warning(exception, "Client '{{0}}': Error while sending DISCONNECT packet (Reason = {1}).", Id, reason);
}
}
// TODO: Fix!
async Task<MqttPublishPacket> InvokeClientMessageQueueInterceptor(MqttPublishPacket publishPacket, MqttQueuedApplicationMessage queuedApplicationMessage)
{
if (_serverOptions.ClientMessageQueueInterceptor == null)
@@ -535,7 +508,7 @@ namespace MQTTnet.Server.Internal
var context = new MqttClientMessageQueueInterceptorContext
{
SenderClientId = queuedApplicationMessage.SenderClientId,
ReceiverClientId = ClientId,
ReceiverClientId = Id,
ApplicationMessage = queuedApplicationMessage.ApplicationMessage,
SubscriptionQualityOfServiceLevel = queuedApplicationMessage.SubscriptionQualityOfServiceLevel
};
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
namespace MQTTnet.Server.Internal
{
@@ -12,6 +14,8 @@ namespace MQTTnet.Server.Internal
{
readonly MqttPacketBus _packetBus = new MqttPacketBus();
readonly Dictionary<ushort, MqttPublishPacket> _publishPacketsWithoutAcknowledge = new Dictionary<ushort, MqttPublishPacket>();
readonly IMqttServerOptions _serverOptions;
readonly MqttClientSessionsManager _clientSessionsManager;
@@ -24,52 +28,70 @@ namespace MQTTnet.Server.Internal
{
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
_clientSessionsManager = clientSessionsManager ?? throw new ArgumentNullException(nameof(clientSessionsManager));
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
Id = clientId ?? throw new ArgumentNullException(nameof(clientId));
Items = items ?? throw new ArgumentNullException(nameof(items));
SubscriptionsManager = new MqttClientSubscriptionsManager(this, serverOptions, eventDispatcher, retainedMessagesManager);
//ApplicationMessagesQueue = new MqttClientSessionApplicationMessagesQueue(serverOptions);
}
public event EventHandler Deleted;
public string ClientId { get; }
public string Id { get; }
public MqttPacketIdentifierProvider PacketIdentifierProvider { get; } = new MqttPacketIdentifierProvider();
public DateTime CreatedTimestamp { get; } = DateTime.UtcNow;
public bool IsCleanSession { get; set; } = true;
//public bool IsCleanSession { get; set; } = true;
public MqttApplicationMessage WillMessage { get; set; }
public MqttConnectPacket LatestConnectPacket { get; set; }
public MqttClientSubscriptionsManager SubscriptionsManager { get; }
//public MqttClientSessionApplicationMessagesQueue ApplicationMessagesQueue { get; }
public IDictionary<object, object> Items { get; }
public void EnqueuePacket(MqttPacketBusItem packet)
public bool WillMessageSent { get; set; }
public long PendingDataPacketsCount => _packetBus.DataPacketsCount;
public void AcknowledgePublishPacket(ushort packetIdentifier)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
_publishPacketsWithoutAcknowledge.Remove(packetIdentifier);
}
public void EnqueuePacket(MqttPacketBusItem packetBusItem)
{
if (packetBusItem == null) throw new ArgumentNullException(nameof(packetBusItem));
if (_packetBus.PacketsCount >= _serverOptions.MaxPendingMessagesPerClient)
{
// TODO: Log!
return;
if (_serverOptions.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
{
// TODO: Log!
return;
}
else
{
// TODO: Implement.
}
}
if (packet.Packet is MqttPublishPacket)
if (packetBusItem.Packet is MqttPublishPacket publishPacket)
{
_packetBus.Enqueue(packet, MqttPacketBusPartition.Data);
if (publishPacket.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
{
_publishPacketsWithoutAcknowledge[publishPacket.PacketIdentifier] = publishPacket;
}
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Data);
}
else if (packet.Packet is MqttPingReqPacket || packet.Packet is MqttPingRespPacket)
else if (packetBusItem.Packet is MqttPingReqPacket || packetBusItem.Packet is MqttPingRespPacket)
{
_packetBus.Enqueue(packet, MqttPacketBusPartition.Health);
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Health);
}
else
{
_packetBus.Enqueue(packet, MqttPacketBusPartition.Control);
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Control);
}
}
@@ -80,13 +102,25 @@ namespace MQTTnet.Server.Internal
public Task DeleteAsync()
{
return _clientSessionsManager.DeleteSessionAsync(ClientId);
return _clientSessionsManager.DeleteSessionAsync(Id);
}
public void OnDeleted()
{
Deleted?.Invoke(this, EventArgs.Empty);
}
public void Recover()
{
// TODO: Keep the bus and only insert pending items again.
// TODO: Check if packet identifier must be restarted or not.
_packetBus.Clear();
foreach (var publishPacket in _publishPacketsWithoutAcknowledge.Values.ToList())
{
EnqueuePacket(new MqttPacketBusItem(publishPacket));
}
}
public void Dispose()
{
@@ -19,7 +19,8 @@ namespace MQTTnet.Server.Internal
public sealed class MqttClientSessionsManager : IDisposable
{
readonly BlockingCollection<MqttPendingApplicationMessage> _messageQueue = new BlockingCollection<MqttPendingApplicationMessage>();
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
readonly AsyncLock _createConnectionSyncRoot = new AsyncLock();
readonly Dictionary<string, MqttClientConnection> _clientConnections = new Dictionary<string, MqttClientConnection>(4096);
readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>(4096);
@@ -129,36 +130,39 @@ namespace MQTTnet.Server.Internal
{
if (clientConnection != null)
{
if (clientConnection.ClientId != null)
if (clientConnection.Id != null)
{
// in case it is a takeover _clientConnections already contains the new connection
if (!clientConnection.IsTakenOver)
{
lock (_clientConnections)
{
_clientConnections.Remove(clientConnection.ClientId);
_clientConnections.Remove(clientConnection.Id);
}
if (!_options.EnablePersistentSessions)
{
await DeleteSessionAsync(clientConnection.ClientId).ConfigureAwait(false);
await DeleteSessionAsync(clientConnection.Id).ConfigureAwait(false);
}
}
}
var endpoint = clientConnection.Endpoint;
if (clientConnection.ClientId != null && !clientConnection.IsTakenOver)
if (clientConnection.Id != null && !clientConnection.IsTakenOver)
{
// The event is fired at a separate place in case of a handover!
await _eventDispatcher.SafeNotifyClientDisconnectedAsync(
clientConnection.ClientId,
clientConnection.Id,
clientConnection.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean,
endpoint).ConfigureAwait(false);
}
}
await channelAdapter.DisconnectAsync(_options.DefaultCommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
using (var timeout = new CancellationTokenSource(_options.DefaultCommunicationTimeout))
{
await channelAdapter.DisconnectAsync(timeout.Token).ConfigureAwait(false);
}
}
}
@@ -221,11 +225,11 @@ namespace MQTTnet.Server.Internal
return Task.FromResult((IList<IMqttSessionStatus>)result);
}
public void DispatchApplicationMessage(MqttApplicationMessage applicationMessage, MqttClientConnection sender)
public void DispatchPublishPacket(MqttPublishPacket publishPacket, MqttClientConnection sender)
{
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
_messageQueue.Add(new MqttPendingApplicationMessage(applicationMessage, sender));
_messageQueue.Add(new MqttPendingApplicationMessage(publishPacket, sender));
}
public async Task SubscribeAsync(string clientId, ICollection<MqttTopicFilter> topicFilters)
@@ -242,11 +246,7 @@ namespace MQTTnet.Server.Internal
foreach (var retainedApplicationMessage in subscribeResult.RetainedApplicationMessages)
{
//clientSession.ApplicationMessagesQueue.Enqueue(retainedApplicationMessage);
// TODO: Review!
var publishPacketFactory = new MqttPublishPacketFactory();
var publishPacket = publishPacketFactory.Create(retainedApplicationMessage.ApplicationMessage);
var publishPacket = _packetFactories.Publish.Create(retainedApplicationMessage.ApplicationMessage);
clientSession.EnqueuePacket(new MqttPacketBusItem(publishPacket));
}
}
@@ -351,8 +351,10 @@ namespace MQTTnet.Server.Internal
}
var clientConnection = pendingApplicationMessage.Sender;
var senderClientId = clientConnection?.ClientId ?? _options.ClientId;
var applicationMessage = pendingApplicationMessage.ApplicationMessage;
var senderClientId = clientConnection?.Id ?? _options.ClientId;
// TODO: Only use PUBLISH packets internally!
var applicationMessage = new MqttApplicationMessageFactory().Create(pendingApplicationMessage.PublishPacket);
var interceptor = _options.ApplicationMessageInterceptor;
if (interceptor != null)
@@ -403,7 +405,7 @@ namespace MQTTnet.Server.Internal
continue;
}
_logger.Verbose("Client '{0}': Queued application message with topic '{1}'.", clientSession.ClientId, applicationMessage.Topic);
_logger.Verbose("Client '{0}': Queued application message with topic '{1}'.", clientSession.Id, applicationMessage.Topic);
// var queuedApplicationMessage = new MqttQueuedApplicationMessage
// {
@@ -411,16 +413,12 @@ namespace MQTTnet.Server.Internal
// SubscriptionQualityOfServiceLevel = checkSubscriptionsResult.QualityOfServiceLevel,
// SubscriptionIdentifiers = checkSubscriptionsResult.SubscriptionIdentifiers
// };
var publishPacketFactory = new MqttPublishPacketFactory();
var publishPacket = publishPacketFactory.Create(applicationMessage);
var publishPacket = _packetFactories.Publish.Create(applicationMessage);
publishPacket.QualityOfServiceLevel = checkSubscriptionsResult.QualityOfServiceLevel;
publishPacket.Properties.SubscriptionIdentifiers.AddRange(checkSubscriptionsResult.SubscriptionIdentifiers);
//clientSession.ApplicationMessagesQueue.Enqueue(queuedApplicationMessage);
if (publishPacket.QualityOfServiceLevel > 0)
{
publishPacket.PacketIdentifier = clientSession.PacketIdentifierProvider.GetNextPacketIdentifier();
@@ -458,34 +456,6 @@ namespace MQTTnet.Server.Internal
_logger.Error(exception, "Unhandled exception while processing next queued application message.");
}
}
// public async Task<MqttPublishPacket> CreatePublishPacket(MqttQueuedApplicationMessage queuedApplicationMessage)
// {
// var publishPacket = ChannelAdapter.PacketFormatterAdapter.DataConverter.CreatePublishPacket(queuedApplicationMessage.ApplicationMessage);
// publishPacket.QualityOfServiceLevel = queuedApplicationMessage.SubscriptionQualityOfServiceLevel;
//
// if (ChannelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500)
// {
// publishPacket.Properties.SubscriptionIdentifiers.AddRange(queuedApplicationMessage.SubscriptionIdentifiers ?? new List<uint>());
// }
//
// // Set the retain flag to true according to [MQTT-3.3.1-8] and [MQTT-3.3.1-9].
// publishPacket.Retain = queuedApplicationMessage.IsRetainedMessage;
//
// publishPacket = await InvokeClientMessageQueueInterceptor(publishPacket, queuedApplicationMessage).ConfigureAwait(false);
// if (publishPacket == null)
// {
// // The interceptor has decided that the message is not relevant and will be fully ignored.
// return null;
// }
//
// if (publishPacket.QualityOfServiceLevel > 0)
// {
// publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNextPacketIdentifier();
// }
//
// return publishPacket;
// }
async Task<MqttConnectionValidatorContext> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
{
@@ -547,6 +517,7 @@ namespace MQTTnet.Server.Internal
{
_logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId);
connAckPacket.IsSessionPresent = true;
session.Recover();
}
}
@@ -565,7 +536,7 @@ namespace MQTTnet.Server.Internal
if (existingConnection != null)
{
await _eventDispatcher.SafeNotifyClientDisconnectedAsync(existingConnection.ClientId, MqttClientDisconnectType.Takeover, existingConnection.Endpoint);
await _eventDispatcher.SafeNotifyClientDisconnectedAsync(existingConnection.Id, MqttClientDisconnectType.Takeover, existingConnection.Endpoint);
existingConnection.IsTakenOver = true;
await existingConnection.StopAsync(MqttClientDisconnectReason.SessionTakenOver).ConfigureAwait(false);
@@ -591,7 +562,7 @@ namespace MQTTnet.Server.Internal
}
else
{
senderClientId = clientConnection.ClientId;
senderClientId = clientConnection.Id;
sessionItems = clientConnection.Session.Items;
}
@@ -599,7 +570,7 @@ namespace MQTTnet.Server.Internal
{
ClientId = senderClientId,
SessionItems = sessionItems,
AcceptPublish = true,
ProcessPublish = true,
ApplicationMessage = applicationMessage,
CloseConnection = false
};
@@ -16,7 +16,7 @@ namespace MQTTnet.Server.Internal
// completely by swapping references etc.
readonly ReaderWriterLockSlim _subscriptionsLock = new ReaderWriterLockSlim();
readonly Dictionary<string, Subscription> _subscriptions = new Dictionary<string, Subscription>(4096);
readonly MqttClientSession _clientSession;
readonly IMqttServerOptions _options;
readonly MqttServerEventDispatcher _eventDispatcher;
@@ -67,7 +67,7 @@ namespace MQTTnet.Server.Internal
// must be closed. So do not revert to false!
result.CloseConnection = true;
}
if (!acceptSubscription || string.IsNullOrEmpty(finalTopicFilter.Topic))
{
continue;
@@ -81,7 +81,7 @@ namespace MQTTnet.Server.Internal
interceptorContext.ReasonCode);
await _eventDispatcher
.SafeNotifyClientSubscribedTopicAsync(_clientSession.ClientId, finalTopicFilter)
.SafeNotifyClientSubscribedTopicAsync(_clientSession.Id, finalTopicFilter)
.ConfigureAwait(false);
FilterRetainedApplicationMessages(retainedApplicationMessages, subscription, result);
@@ -103,7 +103,7 @@ namespace MQTTnet.Server.Internal
foreach (var topicFilter in unsubscribePacket.TopicFilters)
{
_subscriptions.TryGetValue(topicFilter, out var existingSubscription);
var interceptorContext = await InterceptUnsubscribe(topicFilter, existingSubscription, cancellationToken).ConfigureAwait(false);
var acceptUnsubscription = interceptorContext.ReasonCode == MqttUnsubscribeReasonCode.Success;
@@ -115,7 +115,7 @@ namespace MQTTnet.Server.Internal
// must be closed. So do not revert to false!
result.CloseConnection = true;
}
if (!acceptUnsubscription)
{
continue;
@@ -134,7 +134,7 @@ namespace MQTTnet.Server.Internal
foreach (var topicFilter in unsubscribePacket.TopicFilters)
{
await _eventDispatcher.SafeNotifyClientUnsubscribedTopicAsync(_clientSession.ClientId, topicFilter).ConfigureAwait(false);
await _eventDispatcher.SafeNotifyClientUnsubscribedTopicAsync(_clientSession.Id, topicFilter).ConfigureAwait(false);
}
return result;
@@ -154,7 +154,7 @@ namespace MQTTnet.Server.Internal
_subscriptionsLock.ExitReadLock();
}
var senderIsReceiver = string.Equals(senderClientId, _clientSession.ClientId);
var senderIsReceiver = string.Equals(senderClientId, _clientSession.Id);
var qosLevels = new HashSet<MqttQualityOfServiceLevel>();
var subscriptionIdentifiers = new HashSet<uint>();
@@ -296,7 +296,7 @@ namespace MQTTnet.Server.Internal
{
var context = new MqttSubscriptionInterceptorContext
{
ClientId = _clientSession.ClientId,
ClientId = _clientSession.Id,
TopicFilter = topicFilter,
SessionItems = _clientSession.Items,
Session = new MqttSessionStatus(_clientSession),
@@ -343,7 +343,7 @@ namespace MQTTnet.Server.Internal
{
var context = new MqttUnsubscriptionInterceptorContext
{
ClientId = _clientSession.ClientId,
ClientId = _clientSession.Id,
Topic = topicFilter,
SessionItems = _clientSession.Items,
CancellationToken = cancellationToken
@@ -369,8 +369,7 @@ namespace MQTTnet.Server.Internal
return context;
}
static MqttQualityOfServiceLevel GetEffectiveQoS(MqttQualityOfServiceLevel qosLevel,
HashSet<MqttQualityOfServiceLevel> subscribedQoSLevels)
static MqttQualityOfServiceLevel GetEffectiveQoS(MqttQualityOfServiceLevel qosLevel, ICollection<MqttQualityOfServiceLevel> subscribedQoSLevels)
{
MqttQualityOfServiceLevel effectiveQoS;
if (subscribedQoSLevels.Contains(qosLevel))
@@ -101,7 +101,7 @@ namespace MQTTnet.Server.Internal
return;
}
_logger.Warning("Client '{0}': Did not receive any packet or keep alive signal.", connection.ClientId);
_logger.Warning("Client '{0}': Did not receive any packet or keep alive signal.", connection.Id);
// Execute the disconnection in background so that the keep alive monitor can continue
// with checking other connections.
@@ -112,7 +112,7 @@ namespace MQTTnet.Server.Internal
}
catch (Exception exception)
{
_logger.Error(exception, "Client {0}: Unhandled exception while checking keep alive timeouts.", connection.ClientId);
_logger.Error(exception, "Client {0}: Unhandled exception while checking keep alive timeouts.", connection.Id);
}
}
}
@@ -41,12 +41,6 @@ namespace MQTTnet.Server
public string Password => Encoding.UTF8.GetString(RawPassword ?? PlatformAbstractionLayer.EmptyByteArray);
/// <summary>
/// Gets or sets the will delay interval.
/// This is the time between the client disconnect and the time the will message will be sent.
/// </summary>
public MqttApplicationMessage WillMessage => _connectPacket.WillMessage;
/// <summary>
/// Gets or sets a value indicating whether clean sessions are used or not.
/// When a client connects to a broker it can connect using either a non persistent connection (clean session) or a persistent connection.
@@ -123,7 +117,7 @@ namespace MQTTnet.Server
/// Gets or sets the will delay interval.
/// This is the time between the client disconnect and the time the will message will be sent.
/// </summary>
public uint? WillDelayInterval => _connectPacket.Properties?.WillDelayInterval;
public uint? WillDelayInterval => _connectPacket.WillProperties?.WillDelayInterval;
/// <summary>
/// Gets or sets a key/value collection that can be used to share data within the scope of this session.
@@ -1,17 +1,18 @@
using MQTTnet.Server.Internal;
using MQTTnet.Packets;
using MQTTnet.Server.Internal;
namespace MQTTnet.Server
{
public sealed class MqttPendingApplicationMessage
{
public MqttPendingApplicationMessage(MqttApplicationMessage applicationMessage, MqttClientConnection sender)
public MqttPendingApplicationMessage(MqttPublishPacket publishPacket, MqttClientConnection sender)
{
Sender = sender;
ApplicationMessage = applicationMessage;
PublishPacket = publishPacket;
}
public MqttClientConnection Sender { get; }
public MqttApplicationMessage ApplicationMessage { get; }
public MqttPublishPacket PublishPacket { get; }
}
}
+4 -2
View File
@@ -1,7 +1,6 @@
using MQTTnet.Adapter;
using MQTTnet.Client.Publishing;
using MQTTnet.Client.Receiving;
using MQTTnet.Diagnostics;
using MQTTnet.Exceptions;
using MQTTnet.Protocol;
using MQTTnet.Server.Status;
@@ -11,6 +10,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Internal;
using MQTTnet.Server.Internal;
@@ -19,6 +19,7 @@ namespace MQTTnet.Server
{
public class MqttServer : Disposable, IMqttServer
{
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
readonly MqttServerEventDispatcher _eventDispatcher;
readonly ICollection<IMqttServerAdapter> _adapters;
readonly IMqttNetLogger _rootLogger;
@@ -148,7 +149,8 @@ namespace MQTTnet.Server
ThrowIfNotStarted();
_clientSessionsManager.DispatchApplicationMessage(applicationMessage, null);
var publishPacket = _packetFactories.Publish.Create(applicationMessage);
_clientSessionsManager.DispatchPublishPacket(publishPacket, null);
return Task.FromResult(new MqttClientPublishResult());
}
@@ -19,7 +19,7 @@ namespace MQTTnet.Server.Status
/// Gets or sets the client identifier.
/// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues.
/// </summary>
public string ClientId => _connection.ClientId;
public string ClientId => _connection.Id;
public string Endpoint => _connection.Endpoint;
@@ -24,10 +24,9 @@ namespace MQTTnet.Server.Status
remove => _session.Deleted += value;
}
public string ClientId => _session.ClientId;
public string ClientId => _session.Id;
// TODO: Fix!
public long PendingApplicationMessagesCount => 0; // _session.ApplicationMessagesQueue.Count;
public long PendingApplicationMessagesCount => _session.PendingDataPacketsCount;
public DateTime CreatedTimestamp => _session.CreatedTimestamp;