mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-22 04:43:04 +08:00
Feature/mqttv5 subscriptions server (#1246)
* Add support for RetainHandling. * Add support for No Local. * Add support for _SubscriptionIdentifier_. * Add more Unit Tests. * Update docs.
This commit is contained in:
@@ -8,6 +8,7 @@ using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Formatter
|
||||
{
|
||||
@@ -15,13 +16,13 @@ namespace MQTTnet.Formatter
|
||||
{
|
||||
MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket);
|
||||
|
||||
MqttClientAuthenticateResult CreateClientConnectResult(MqttConnAckPacket connAckPacket);
|
||||
MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket);
|
||||
|
||||
MqttClientPublishResult CreateClientPublishResult(MqttPubAckPacket pubAckPacket);
|
||||
|
||||
MqttClientPublishResult CreateClientPublishResult(MqttPubRecPacket pubRecPacket, MqttPubCompPacket pubCompPacket);
|
||||
|
||||
Client.Subscribing.MqttClientSubscribeResult CreateClientSubscribeResult(MqttSubscribePacket subscribePacket, MqttSubAckPacket subAckPacket);
|
||||
MqttClientSubscribeResult CreateClientSubscribeResult(MqttSubscribePacket subscribePacket, MqttSubAckPacket subAckPacket);
|
||||
|
||||
MqttClientUnsubscribeResult CreateClientUnsubscribeResult(MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket);
|
||||
|
||||
@@ -41,7 +42,7 @@ namespace MQTTnet.Formatter
|
||||
|
||||
MqttSubscribePacket CreateSubscribePacket(MqttClientSubscribeOptions options);
|
||||
|
||||
MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, Server.MqttClientSubscribeResult subscribeResult);
|
||||
MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, SubscribeResult subscribeResult);
|
||||
|
||||
MqttUnsubscribePacket CreateUnsubscribePacket(MqttClientUnsubscribeOptions options);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ using MQTTnet.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MqttClientSubscribeResult = MQTTnet.Client.Subscribing.MqttClientSubscribeResult;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Formatter.V3
|
||||
{
|
||||
@@ -85,12 +85,12 @@ namespace MQTTnet.Formatter.V3
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientAuthenticateResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
public MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
{
|
||||
if (connAckPacket == null) throw new ArgumentNullException(nameof(connAckPacket));
|
||||
|
||||
MqttClientConnectResultCode resultCode;
|
||||
switch (connAckPacket.ReturnCode.Value)
|
||||
switch (connAckPacket.ReturnCode)
|
||||
{
|
||||
case MqttConnectReturnCode.ConnectionAccepted:
|
||||
{
|
||||
@@ -132,8 +132,10 @@ namespace MQTTnet.Formatter.V3
|
||||
throw new MqttProtocolViolationException("Received unexpected return code.");
|
||||
}
|
||||
|
||||
return new MqttClientAuthenticateResult
|
||||
return new MqttClientConnectResult
|
||||
{
|
||||
RetainAvailable = true, // Always true because v3.1.1 does not have a way to "disable" that feature.
|
||||
WildcardSubscriptionAvailable = true, // Always true because v3.1.1 does not have a way to "disable" that feature.
|
||||
IsSessionPresent = connAckPacket.IsSessionPresent,
|
||||
ResultCode = resultCode
|
||||
};
|
||||
@@ -205,7 +207,7 @@ namespace MQTTnet.Formatter.V3
|
||||
return subscribePacket;
|
||||
}
|
||||
|
||||
public MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, Server.MqttClientSubscribeResult subscribeResult)
|
||||
public MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, SubscribeResult subscribeResult)
|
||||
{
|
||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||
if (subscribeResult == null) throw new ArgumentNullException(nameof(subscribeResult));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Exceptions;
|
||||
@@ -407,7 +408,7 @@ namespace MQTTnet.Formatter.V3
|
||||
protected virtual byte EncodeConnAckPacket(MqttConnAckPacket packet, IMqttPacketWriter packetWriter)
|
||||
{
|
||||
packetWriter.Write(0); // Reserved.
|
||||
packetWriter.Write((byte)packet.ReturnCode.Value);
|
||||
packetWriter.Write((byte)packet.ReturnCode);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||
}
|
||||
@@ -520,6 +521,21 @@ namespace MQTTnet.Formatter.V3
|
||||
{
|
||||
foreach (var topicFilter in packet.TopicFilters)
|
||||
{
|
||||
if (topicFilter.NoLocal)
|
||||
{
|
||||
throw new MqttProtocolViolationException("NoLocal is not supported in 3.1.1.");
|
||||
}
|
||||
|
||||
if (topicFilter.RetainAsPublished)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using MQTTnet.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MqttClientSubscribeResult = MQTTnet.Client.Subscribing.MqttClientSubscribeResult;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
@@ -115,16 +115,16 @@ namespace MQTTnet.Formatter.V5
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientAuthenticateResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
public MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
{
|
||||
if (connAckPacket == null) throw new ArgumentNullException(nameof(connAckPacket));
|
||||
|
||||
return new MqttClientAuthenticateResult
|
||||
return new MqttClientConnectResult
|
||||
{
|
||||
IsSessionPresent = connAckPacket.IsSessionPresent,
|
||||
ResultCode = (MqttClientConnectResultCode)(int)(connAckPacket.ReasonCode ?? 0),
|
||||
WildcardSubscriptionAvailable = connAckPacket.Properties?.WildcardSubscriptionAvailable,
|
||||
RetainAvailable = connAckPacket.Properties?.RetainAvailable,
|
||||
ResultCode = (MqttClientConnectResultCode)(int)connAckPacket.ReasonCode,
|
||||
WildcardSubscriptionAvailable = connAckPacket.Properties?.WildcardSubscriptionAvailable ?? true,
|
||||
RetainAvailable = connAckPacket.Properties?.RetainAvailable ?? true,
|
||||
AssignedClientIdentifier = connAckPacket.Properties?.AssignedClientIdentifier,
|
||||
AuthenticationMethod = connAckPacket.Properties?.AuthenticationMethod,
|
||||
AuthenticationData = connAckPacket.Properties?.AuthenticationData,
|
||||
@@ -133,13 +133,13 @@ namespace MQTTnet.Formatter.V5
|
||||
ReceiveMaximum = connAckPacket.Properties?.ReceiveMaximum,
|
||||
MaximumQoS = connAckPacket.Properties?.MaximumQoS ?? MqttQualityOfServiceLevel.ExactlyOnce,
|
||||
ResponseInformation = connAckPacket.Properties?.ResponseInformation,
|
||||
TopicAliasMaximum = connAckPacket.Properties?.TopicAliasMaximum,
|
||||
TopicAliasMaximum = connAckPacket.Properties?.TopicAliasMaximum ?? 0,
|
||||
ServerReference = connAckPacket.Properties?.ServerReference,
|
||||
ServerKeepAlive = connAckPacket.Properties?.ServerKeepAlive,
|
||||
SessionExpiryInterval = connAckPacket.Properties?.SessionExpiryInterval,
|
||||
SubscriptionIdentifiersAvailable = connAckPacket.Properties?.SubscriptionIdentifiersAvailable,
|
||||
SharedSubscriptionAvailable = connAckPacket.Properties?.SharedSubscriptionAvailable,
|
||||
UserProperties = connAckPacket.Properties?.UserProperties
|
||||
SubscriptionIdentifiersAvailable = connAckPacket.Properties?.SubscriptionIdentifiersAvailable ?? true,
|
||||
SharedSubscriptionAvailable = connAckPacket.Properties?.SharedSubscriptionAvailable ?? true,
|
||||
UserProperties = connAckPacket.Properties?.UserProperties ?? new List<MqttUserProperty>()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -180,12 +180,18 @@ namespace MQTTnet.Formatter.V5
|
||||
ReasonCode = connectionValidatorContext.ReasonCode,
|
||||
Properties = new MqttConnAckPacketProperties
|
||||
{
|
||||
RetainAvailable = true,
|
||||
SubscriptionIdentifiersAvailable = true,
|
||||
SharedSubscriptionAvailable = false,
|
||||
TopicAliasMaximum = ushort.MaxValue,
|
||||
WildcardSubscriptionAvailable = true,
|
||||
|
||||
UserProperties = connectionValidatorContext.ResponseUserProperties,
|
||||
AuthenticationMethod = connectionValidatorContext.AuthenticationMethod,
|
||||
AuthenticationData = connectionValidatorContext.ResponseAuthenticationData,
|
||||
AssignedClientIdentifier = connectionValidatorContext.AssignedClientIdentifier,
|
||||
ReasonString = connectionValidatorContext.ReasonString,
|
||||
TopicAliasMaximum = ushort.MaxValue
|
||||
ServerReference = connectionValidatorContext.ServerReference
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -242,7 +248,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
public MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, Server.MqttClientSubscribeResult subscribeResult)
|
||||
public MqttSubAckPacket CreateSubAckPacket(MqttSubscribePacket subscribePacket, SubscribeResult subscribeResult)
|
||||
{
|
||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||
if (subscribeResult == null) throw new ArgumentNullException(nameof(subscribeResult));
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PacketDecoder
|
||||
{
|
||||
private static readonly MqttPingReqPacket PingReqPacket = new MqttPingReqPacket();
|
||||
static readonly MqttPingReqPacket PingReqPacket = new MqttPingReqPacket();
|
||||
|
||||
private static readonly MqttPingRespPacket PingRespPacket = new MqttPingRespPacket();
|
||||
static readonly MqttPingRespPacket PingRespPacket = new MqttPingRespPacket();
|
||||
|
||||
public MqttBasePacket Decode(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ namespace MQTTnet.Formatter.V5
|
||||
}
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeConnectPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeConnectPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeConnAckPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeConnAckPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -225,15 +225,17 @@ namespace MQTTnet.Formatter.V5
|
||||
IsSessionPresent = (acknowledgeFlags & 0x1) > 0,
|
||||
ReasonCode = (MqttConnectReasonCode)body.ReadByte()
|
||||
};
|
||||
|
||||
// Set all default values according to specification. When they are missing the often
|
||||
// indicate that a feature is available.
|
||||
packet.Properties.RetainAvailable = true;
|
||||
packet.Properties.SharedSubscriptionAvailable = true;
|
||||
packet.Properties.SubscriptionIdentifiersAvailable = true;
|
||||
packet.Properties.WildcardSubscriptionAvailable = true;
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (packet.Properties == null)
|
||||
{
|
||||
packet.Properties = new MqttConnAckPacketProperties();
|
||||
}
|
||||
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.SessionExpiryInterval)
|
||||
{
|
||||
packet.Properties.SessionExpiryInterval = propertiesReader.ReadSessionExpiryInterval();
|
||||
@@ -316,7 +318,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeDisconnectPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeDisconnectPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -363,7 +365,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeSubscribePacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeSubscribePacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -422,7 +424,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeSubAckPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeSubAckPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -467,7 +469,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeUnsubscribePacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeUnsubscribePacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -507,7 +509,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeUnsubAckPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeUnsubAckPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -552,17 +554,17 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePingReqPacket()
|
||||
static MqttBasePacket DecodePingReqPacket()
|
||||
{
|
||||
return PingReqPacket;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePingRespPacket()
|
||||
static MqttBasePacket DecodePingRespPacket()
|
||||
{
|
||||
return PingRespPacket;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePublishPacket(byte header, IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodePublishPacket(byte header, IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -647,7 +649,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubAckPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodePubAckPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -694,7 +696,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubRecPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodePubRecPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -741,7 +743,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubRelPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodePubRelPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -788,7 +790,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubCompPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodePubCompPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -835,7 +837,7 @@ namespace MQTTnet.Formatter.V5
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeAuthPacket(IMqttPacketBodyReader body)
|
||||
static MqttBasePacket DecodeAuthPacket(IMqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -888,7 +890,7 @@ namespace MQTTnet.Formatter.V5
|
||||
}
|
||||
|
||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
||||
private static void ThrowIfBodyIsEmpty(IMqttPacketBodyReader body)
|
||||
static void ThrowIfBodyIsEmpty(IMqttPacketBodyReader body)
|
||||
{
|
||||
if (body == null || body.Length == 0)
|
||||
{
|
||||
|
||||
@@ -173,12 +173,7 @@ namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
ThrowReasonCodeNotSetException();
|
||||
}
|
||||
|
||||
|
||||
byte connectAcknowledgeFlags = 0x0;
|
||||
if (packet.IsSessionPresent)
|
||||
{
|
||||
@@ -186,7 +181,7 @@ namespace MQTTnet.Formatter.V5
|
||||
}
|
||||
|
||||
packetWriter.Write(connectAcknowledgeFlags);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
packetWriter.Write((byte)packet.ReasonCode);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
@@ -247,19 +242,18 @@ namespace MQTTnet.Formatter.V5
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
if (packet.Properties.TopicAlias == 0)
|
||||
{
|
||||
throw new MqttProtocolViolationException("A Topic Alias of 0 is not permitted. A sender MUST NOT send a PUBLISH packet containing a Topic Alias which has the value 0 [MQTT-3.3.2-8].");
|
||||
}
|
||||
|
||||
propertiesWriter.WriteContentType(packet.Properties.ContentType);
|
||||
propertiesWriter.WriteCorrelationData(packet.Properties.CorrelationData);
|
||||
propertiesWriter.WriteMessageExpiryInterval(packet.Properties.MessageExpiryInterval);
|
||||
propertiesWriter.WritePayloadFormatIndicator(packet.Properties.PayloadFormatIndicator);
|
||||
propertiesWriter.WriteResponseTopic(packet.Properties.ResponseTopic);
|
||||
propertiesWriter.WriteSubscriptionIdentifiers(packet.Properties.SubscriptionIdentifiers);
|
||||
propertiesWriter.WriteTopicAlias(packet.Properties.TopicAlias);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
|
||||
if (packet.Properties.TopicAlias > 0)
|
||||
{
|
||||
propertiesWriter.WriteTopicAlias(packet.Properties.TopicAlias);
|
||||
}
|
||||
}
|
||||
|
||||
propertiesWriter.WriteTo(packetWriter);
|
||||
@@ -411,7 +405,11 @@ namespace MQTTnet.Formatter.V5
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteSubscriptionIdentifier(packet.Properties.SubscriptionIdentifier);
|
||||
if (packet.Properties.SubscriptionIdentifier > 0)
|
||||
{
|
||||
propertiesWriter.WriteSubscriptionIdentifier(packet.Properties.SubscriptionIdentifier);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
@@ -425,19 +423,19 @@ namespace MQTTnet.Formatter.V5
|
||||
|
||||
var options = (byte)topicFilter.QualityOfServiceLevel;
|
||||
|
||||
if (topicFilter.NoLocal == true)
|
||||
if (topicFilter.NoLocal)
|
||||
{
|
||||
options |= 1 << 2;
|
||||
}
|
||||
|
||||
if (topicFilter.RetainAsPublished == true)
|
||||
if (topicFilter.RetainAsPublished)
|
||||
{
|
||||
options |= 1 << 3;
|
||||
}
|
||||
|
||||
if (topicFilter.RetainHandling.HasValue)
|
||||
if (topicFilter.RetainHandling != MqttRetainHandling.SendAtSubscribe)
|
||||
{
|
||||
options |= (byte)((byte)topicFilter.RetainHandling.Value << 4);
|
||||
options |= (byte)((byte)topicFilter.RetainHandling << 4);
|
||||
}
|
||||
|
||||
packetWriter.Write(options);
|
||||
|
||||
@@ -74,12 +74,12 @@ namespace MQTTnet.Formatter.V5
|
||||
WriteAsFourByteInteger(MqttPropertyId.SessionExpiryInterval, value);
|
||||
}
|
||||
|
||||
public void WriteSubscriptionIdentifier(uint? value)
|
||||
public void WriteSubscriptionIdentifier(uint value)
|
||||
{
|
||||
WriteAsVariableLengthInteger(MqttPropertyId.SubscriptionIdentifier, value);
|
||||
}
|
||||
|
||||
public void WriteSubscriptionIdentifiers(IEnumerable<uint> value)
|
||||
public void WriteSubscriptionIdentifiers(ICollection<uint> value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
@@ -148,9 +148,15 @@ namespace MQTTnet.Formatter.V5
|
||||
WriteAsFourByteInteger(MqttPropertyId.MaximumPacketSize, value);
|
||||
}
|
||||
|
||||
public void WriteRetainAvailable(bool? value)
|
||||
public void WriteRetainAvailable(bool value)
|
||||
{
|
||||
Write(MqttPropertyId.RetainAvailable, value);
|
||||
if (value)
|
||||
{
|
||||
// Absence of the flag means it is supported!
|
||||
return;
|
||||
}
|
||||
|
||||
Write(MqttPropertyId.RetainAvailable, false);
|
||||
}
|
||||
|
||||
public void WriteAssignedClientIdentifier(string value)
|
||||
@@ -168,14 +174,26 @@ namespace MQTTnet.Formatter.V5
|
||||
Write(MqttPropertyId.WildcardSubscriptionAvailable, value);
|
||||
}
|
||||
|
||||
public void WriteSubscriptionIdentifiersAvailable(bool? value)
|
||||
public void WriteSubscriptionIdentifiersAvailable(bool value)
|
||||
{
|
||||
Write(MqttPropertyId.SubscriptionIdentifiersAvailable, value);
|
||||
if (value)
|
||||
{
|
||||
// Absence of the flag means it is supported!
|
||||
return;
|
||||
}
|
||||
|
||||
Write(MqttPropertyId.SubscriptionIdentifiersAvailable, false);
|
||||
}
|
||||
|
||||
public void WriteSharedSubscriptionAvailable(bool? value)
|
||||
public void WriteSharedSubscriptionAvailable(bool value)
|
||||
{
|
||||
Write(MqttPropertyId.SharedSubscriptionAvailable, value);
|
||||
if (value)
|
||||
{
|
||||
// Absence of the flag means it is supported!
|
||||
return;
|
||||
}
|
||||
|
||||
Write(MqttPropertyId.SharedSubscriptionAvailable, false);
|
||||
}
|
||||
|
||||
public void WriteServerKeepAlive(ushort? value)
|
||||
@@ -221,15 +239,10 @@ namespace MQTTnet.Formatter.V5
|
||||
_packetWriter.Write(value.Value);
|
||||
}
|
||||
|
||||
void WriteAsVariableLengthInteger(MqttPropertyId id, uint? value)
|
||||
void WriteAsVariableLengthInteger(MqttPropertyId id, uint value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteVariableLengthInteger(value.Value);
|
||||
_packetWriter.WriteVariableLengthInteger(value);
|
||||
}
|
||||
|
||||
void WriteAsFourByteInteger(MqttPropertyId id, uint? value)
|
||||
|
||||
Reference in New Issue
Block a user