Add support for topic alias.

This commit is contained in:
Christian Kratky
2020-11-09 21:10:05 +01:00
parent 6c15693456
commit e1bf9de347
9 changed files with 144 additions and 35 deletions
+1 -1
View File
@@ -219,7 +219,7 @@ namespace MQTTnet.Client
{
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
MqttTopicValidator.ThrowIfInvalid(applicationMessage.Topic);
MqttTopicValidator.ThrowIfInvalid(applicationMessage);
ThrowIfDisposed();
ThrowIfNotConnected();
@@ -18,6 +18,8 @@ namespace MQTTnet.Formatter
MqttPubAckPacket CreatePubAckPacket(MqttPublishPacket publishPacket);
MqttBasePacket CreatePubRecPacket(MqttPublishPacket publishPacket);
MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket);
MqttClientAuthenticateResult CreateClientConnectResult(MqttConnAckPacket connAckPacket);
@@ -40,6 +40,15 @@ namespace MQTTnet.Formatter.V3
};
}
public MqttBasePacket CreatePubRecPacket(MqttPublishPacket publishPacket)
{
return new MqttPubRecPacket
{
PacketIdentifier = publishPacket.PacketIdentifier,
ReasonCode = MqttPubRecReasonCode.Success
};
}
public MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket)
{
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
@@ -58,6 +58,15 @@ namespace MQTTnet.Formatter.V5
};
}
public MqttBasePacket CreatePubRecPacket(MqttPublishPacket publishPacket)
{
return new MqttPubRecPacket
{
PacketIdentifier = publishPacket.PacketIdentifier,
ReasonCode = MqttPubRecReasonCode.Success
};
}
public MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket)
{
return new MqttApplicationMessage
+14 -1
View File
@@ -1,9 +1,22 @@
using MQTTnet.Exceptions;
using System;
using MQTTnet.Exceptions;
namespace MQTTnet.Protocol
{
public static class MqttTopicValidator
{
public static void ThrowIfInvalid(MqttApplicationMessage applicationMessage)
{
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
if (applicationMessage.TopicAlias > 0)
{
return;
}
ThrowIfInvalid(applicationMessage.Topic);
}
public static void ThrowIfInvalid(string topic)
{
if (string.IsNullOrEmpty(topic))
+35 -30
View File
@@ -18,6 +18,7 @@ namespace MQTTnet.Server
{
public sealed class MqttClientConnection : IDisposable
{
readonly Dictionary<ushort, string> _topicAlias = new Dictionary<ushort, string>();
readonly MqttPacketIdentifierProvider _packetIdentifierProvider = new MqttPacketIdentifierProvider();
readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
readonly CancellationTokenSource _cancellationToken = new CancellationTokenSource();
@@ -316,19 +317,26 @@ namespace MQTTnet.Server
{
Interlocked.Increment(ref _sentApplicationMessagesCount);
HandleTopicAlias(publishPacket);
var applicationMessage = _dataConverter.CreateApplicationMessage(publishPacket);
_sessionsManager.DispatchApplicationMessage(applicationMessage, this);
switch (publishPacket.QualityOfServiceLevel)
{
case MqttQualityOfServiceLevel.AtMostOnce:
{
return HandleIncomingPublishPacketWithQoS0Async(publishPacket);
return PlatformAbstractionLayer.CompletedTask;
}
case MqttQualityOfServiceLevel.AtLeastOnce:
{
return HandleIncomingPublishPacketWithQoS1Async(publishPacket, cancellationToken);
var pubAckPacket = _dataConverter.CreatePubAckPacket(publishPacket);
return SendAsync(pubAckPacket, cancellationToken);
}
case MqttQualityOfServiceLevel.ExactlyOnce:
{
return HandleIncomingPublishPacketWithQoS2Async(publishPacket, cancellationToken);
var pubRecPacket = _dataConverter.CreatePubRecPacket(publishPacket);
return SendAsync(pubRecPacket, cancellationToken);
}
default:
{
@@ -337,36 +345,33 @@ namespace MQTTnet.Server
}
}
Task HandleIncomingPublishPacketWithQoS0Async(MqttPublishPacket publishPacket)
void HandleTopicAlias(MqttPublishPacket publishPacket)
{
var applicationMessage = _dataConverter.CreateApplicationMessage(publishPacket);
_sessionsManager.DispatchApplicationMessage(applicationMessage, this);
return PlatformAbstractionLayer.CompletedTask;
}
Task HandleIncomingPublishPacketWithQoS1Async(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
{
var applicationMessage = _dataConverter.CreateApplicationMessage(publishPacket);
_sessionsManager.DispatchApplicationMessage(applicationMessage, this);
var pubAckPacket = _dataConverter.CreatePubAckPacket(publishPacket);
return SendAsync(pubAckPacket, cancellationToken);
}
Task HandleIncomingPublishPacketWithQoS2Async(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
{
var applicationMessage = _dataConverter.CreateApplicationMessage(publishPacket);
_sessionsManager.DispatchApplicationMessage(applicationMessage, this);
var pubRecPacket = new MqttPubRecPacket
if (publishPacket.Properties?.TopicAlias == null)
{
PacketIdentifier = publishPacket.PacketIdentifier,
ReasonCode = MqttPubRecReasonCode.Success
};
return;
}
return SendAsync(pubRecPacket, cancellationToken);
var topicAlias = publishPacket.Properties.TopicAlias.Value;
lock (_topicAlias)
{
if (!string.IsNullOrEmpty(publishPacket.Topic))
{
_topicAlias[topicAlias] = publishPacket.Topic;
}
else
{
if (_topicAlias.TryGetValue(topicAlias, out var topic))
{
publishPacket.Topic = topic;
}
else
{
}
}
}
}
async Task SendPendingPacketsAsync(CancellationToken cancellationToken)