mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-20 03:24:33 +08:00
Refactor namespaces.
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Net;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.AspNetCore.Client.Tcp;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace MQTTnet.AspNetCore
|
||||
|
||||
var bodySlice = copy.Slice(0, bodyLength);
|
||||
var buffer = bodySlice.GetArray();
|
||||
packet = formatter.Decode(new ReceivedMqttPacket(fixedheader, new MqttPacketBodyReader(buffer, 0, buffer.Length)));
|
||||
packet = formatter.Decode(new ReceivedMqttPacket(fixedheader, new MqttPacketBodyReader(buffer, 0, buffer.Length), buffer.Length + 2));
|
||||
consumed = bodySlice.End;
|
||||
observed = bodySlice.End;
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
@@ -4,13 +4,14 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using MqttClientConnectedEventArgs = MQTTnet.Client.MqttClientConnectedEventArgs;
|
||||
using MqttClientDisconnectedEventArgs = MQTTnet.Client.MqttClientDisconnectedEventArgs;
|
||||
using MqttClientConnectedEventArgs = MQTTnet.Client.Connecting.MqttClientConnectedEventArgs;
|
||||
using MqttClientDisconnectedEventArgs = MQTTnet.Client.Disconnecting.MqttClientDisconnectedEventArgs;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
{
|
||||
@@ -27,7 +28,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
private CancellationTokenSource _publishingCancellationToken;
|
||||
|
||||
private ManagedMqttClientStorageManager _storageManager;
|
||||
|
||||
|
||||
private bool _subscriptionsNotPushed;
|
||||
|
||||
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
|
||||
@@ -102,11 +103,12 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task PublishAsync(MqttApplicationMessage applicationMessage)
|
||||
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
return PublishAsync(new ManagedMqttApplicationMessageBuilder().WithApplicationMessage(applicationMessage).Build());
|
||||
await PublishAsync(new ManagedMqttApplicationMessageBuilder().WithApplicationMessage(applicationMessage).Build()).ConfigureAwait(false);
|
||||
return new MqttClientPublishResult();
|
||||
}
|
||||
|
||||
public async Task PublishAsync(ManagedMqttApplicationMessage applicationMessage)
|
||||
@@ -206,7 +208,15 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
finally
|
||||
{
|
||||
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while disconnecting.");
|
||||
}
|
||||
|
||||
_logger.Info("Stopped");
|
||||
}
|
||||
}
|
||||
@@ -345,7 +355,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
lock (_subscriptions)
|
||||
{
|
||||
subscriptions = _subscriptions.Select(i => new TopicFilter(i.Key, i.Value)).ToList();
|
||||
subscriptions = _subscriptions.Select(i => new TopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
|
||||
|
||||
unsubscriptions = new HashSet<string>(_unsubscriptions);
|
||||
_unsubscriptions.Clear();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace MQTTnet.Adapter
|
||||
string Endpoint { get; }
|
||||
|
||||
MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
|
||||
|
||||
|
||||
event EventHandler ReadingPacketStarted;
|
||||
|
||||
event EventHandler ReadingPacketCompleted;
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Diagnostics;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Adapter
|
||||
{
|
||||
public interface IMqttClientAdapterFactory
|
||||
{
|
||||
@@ -16,7 +16,7 @@ namespace MQTTnet.Adapter
|
||||
public class MqttChannelAdapter : IMqttChannelAdapter
|
||||
{
|
||||
private const uint ErrorOperationAborted = 0x800703E3;
|
||||
private const uint ReadBufferSize = 4096; // TODO: Move buffer size to config
|
||||
private const int ReadBufferSize = 4096; // TODO: Move buffer size to config
|
||||
|
||||
private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace MQTTnet.Adapter
|
||||
await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false);
|
||||
PacketFormatterAdapter.FreeBuffer();
|
||||
|
||||
_logger.Verbose("TX >>> {0}", packet);
|
||||
_logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -152,7 +152,7 @@ namespace MQTTnet.Adapter
|
||||
throw new MqttProtocolViolationException("Received malformed packet.");
|
||||
}
|
||||
|
||||
_logger.Verbose("RX <<< {0}", packet);
|
||||
_logger.Verbose("RX ({0} bytes) <<< {1}", receivedMqttPacket.TotalLength, packet);
|
||||
|
||||
return packet;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ namespace MQTTnet.Adapter
|
||||
|
||||
if (fixedHeader.RemainingLength == 0)
|
||||
{
|
||||
return new ReceivedMqttPacket(fixedHeader.Flags, null);
|
||||
return new ReceivedMqttPacket(fixedHeader.Flags, null, 2);
|
||||
}
|
||||
|
||||
var body = new byte[fixedHeader.RemainingLength];
|
||||
@@ -194,15 +194,15 @@ namespace MQTTnet.Adapter
|
||||
var bytesLeft = body.Length - bodyOffset;
|
||||
if (chunkSize > bytesLeft)
|
||||
{
|
||||
chunkSize = (uint)bytesLeft;
|
||||
chunkSize = bytesLeft;
|
||||
}
|
||||
|
||||
#if WINDOWS_UWP
|
||||
var readBytes = await _channel.ReadAsync(body, bodyOffset, (int)chunkSize, cancellationToken).ConfigureAwait(false);
|
||||
#else
|
||||
// async/await is not used to avoid the overhead of context switches. We assume that the reamining data
|
||||
// async/await is not used to avoid the overhead of context switches. We assume that the remaining data
|
||||
// has been sent from the sender directly after the initial bytes.
|
||||
var readBytes = _channel.ReadAsync(body, bodyOffset, (int)chunkSize, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
var readBytes = _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -211,7 +211,8 @@ namespace MQTTnet.Adapter
|
||||
bodyOffset += readBytes;
|
||||
} while (bodyOffset < body.Length);
|
||||
|
||||
return new ReceivedMqttPacket(fixedHeader.Flags, new MqttPacketBodyReader(body, 0, body.Length));
|
||||
var bodyReader = new MqttPacketBodyReader(body, 0, body.Length);
|
||||
return new ReceivedMqttPacket(fixedHeader.Flags, bodyReader, fixedHeader.TotalLength);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Exceptions;
|
||||
|
||||
namespace MQTTnet.Adapter
|
||||
{
|
||||
public class MqttConnectingFailedException : MqttCommunicationException
|
||||
{
|
||||
public MqttConnectingFailedException(MqttConnectReturnCode returnCode)
|
||||
: base($"Connecting with MQTT server failed ({returnCode}).")
|
||||
public MqttConnectingFailedException(MqttClientConnectResultCode resultCode)
|
||||
: base($"Connecting with MQTT server failed ({resultCode.ToString()}).")
|
||||
{
|
||||
ReturnCode = returnCode;
|
||||
ResultCode = resultCode;
|
||||
}
|
||||
|
||||
public MqttConnectReturnCode ReturnCode { get; }
|
||||
public MqttClientConnectResultCode ResultCode { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,17 @@ namespace MQTTnet.Adapter
|
||||
{
|
||||
public class ReceivedMqttPacket
|
||||
{
|
||||
public ReceivedMqttPacket(byte fixedHeader, MqttPacketBodyReader body)
|
||||
public ReceivedMqttPacket(byte fixedHeader, MqttPacketBodyReader body, int totalLength)
|
||||
{
|
||||
FixedHeader = fixedHeader;
|
||||
Body = body;
|
||||
TotalLength = totalLength;
|
||||
}
|
||||
|
||||
public byte FixedHeader { get; }
|
||||
|
||||
public MqttPacketBodyReader Body { get; }
|
||||
|
||||
public int TotalLength { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet
|
||||
@@ -29,7 +30,7 @@ namespace MQTTnet
|
||||
}
|
||||
}
|
||||
|
||||
public static Task PublishAsync(this IApplicationMessagePublisher publisher, string topic)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -38,7 +39,7 @@ namespace MQTTnet
|
||||
.WithTopic(topic));
|
||||
}
|
||||
|
||||
public static Task PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -48,7 +49,7 @@ namespace MQTTnet
|
||||
.WithPayload(payload));
|
||||
}
|
||||
|
||||
public static Task PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -59,7 +60,7 @@ namespace MQTTnet
|
||||
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
||||
}
|
||||
|
||||
public static Task PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -71,7 +72,7 @@ namespace MQTTnet
|
||||
.WithRetainFlag(retain));
|
||||
}
|
||||
|
||||
public static Task PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||
{
|
||||
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
||||
return publisher.PublishAsync(message);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MQTTnet.Client.Connecting
|
||||
{
|
||||
public class MqttClientConnectResult
|
||||
{
|
||||
public bool IsSessionPresent { get; set; }
|
||||
|
||||
public MqttClientConnectResultCode ResultCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MQTTnet.Client.Connecting
|
||||
{
|
||||
public enum MqttClientConnectResultCode
|
||||
{
|
||||
Success = 0,
|
||||
UnspecifiedError = 128,
|
||||
MalformedPacket = 129,
|
||||
ProtocolError = 130,
|
||||
ImplementationSpecificError = 131,
|
||||
UnsupportedProtocolVersion = 132,
|
||||
ClientIdentifierNotValid = 133,
|
||||
BadUserNameOrPassword = 134,
|
||||
NotAuthorized = 135,
|
||||
ServerUnavailable = 136,
|
||||
ServerBusy = 137,
|
||||
Banned = 138,
|
||||
BadAuthenticationMethod = 140,
|
||||
TopicNameInvalid = 144,
|
||||
PacketTooLarge = 149,
|
||||
QuotaExceeded = 151,
|
||||
PayloadFormatInvalid = 153,
|
||||
RetainNotSupported = 154,
|
||||
QoSNotSupported = 155,
|
||||
UseAnotherServer = 156,
|
||||
ServerMoved = 157,
|
||||
ConnectionRateExceeded = 159
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client.Connecting
|
||||
{
|
||||
public class MqttClientConnectedEventArgs : EventArgs
|
||||
{
|
||||
public MqttClientConnectedEventArgs(MqttClientConnectResult connectResult)
|
||||
{
|
||||
ConnectResult = connectResult ?? throw new ArgumentNullException(nameof(connectResult));
|
||||
}
|
||||
|
||||
public MqttClientConnectResult ConnectResult { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MQTTnet.Client.Disconnecting
|
||||
{
|
||||
public class MqttClientDisconnectOptions
|
||||
{
|
||||
public MqttClientDisconnectReason ReasonCode { get; set; } = MqttClientDisconnectReason.NormalDisconnection;
|
||||
|
||||
public string ReasonString { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace MQTTnet.Client.Disconnecting
|
||||
{
|
||||
public enum MqttClientDisconnectReason
|
||||
{
|
||||
NormalDisconnection = 0,
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Disconnecting
|
||||
{
|
||||
public class MqttClientDisconnectedEventArgs : EventArgs
|
||||
{
|
||||
@@ -1,6 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
@@ -13,9 +18,9 @@ namespace MQTTnet.Client
|
||||
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
|
||||
|
||||
Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options);
|
||||
Task DisconnectAsync();
|
||||
Task DisconnectAsync(MqttClientDisconnectOptions options);
|
||||
|
||||
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
||||
Task UnsubscribeAsync(IEnumerable<string> topics);
|
||||
Task<MqttClientSubscribeResult> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
||||
Task<MqttClientUnsubscribeResult> UnsubscribeAsync(IEnumerable<string> topics);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.PacketDispatcher;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
@@ -71,7 +76,7 @@ namespace MQTTnet.Client
|
||||
|
||||
StartReceivingPackets(_cancellationTokenSource.Token);
|
||||
|
||||
var connectResponse = await AuthenticateAsync(options.WillMessage, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
var connectResult = await AuthenticateAsync(options.WillMessage, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
_logger.Verbose("MQTT connection with server established.");
|
||||
|
||||
_sendTracker.Restart();
|
||||
@@ -82,10 +87,11 @@ namespace MQTTnet.Client
|
||||
}
|
||||
|
||||
IsConnected = true;
|
||||
Connected?.Invoke(this, new MqttClientConnectedEventArgs(connectResponse.IsSessionPresent));
|
||||
Connected?.Invoke(this, new MqttClientConnectedEventArgs(connectResult));
|
||||
|
||||
_logger.Info("Connected.");
|
||||
return new MqttClientConnectResult(connectResponse.IsSessionPresent);
|
||||
|
||||
return connectResult;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -100,7 +106,7 @@ namespace MQTTnet.Client
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DisconnectAsync()
|
||||
public async Task DisconnectAsync(MqttClientDisconnectOptions options)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -108,7 +114,8 @@ namespace MQTTnet.Client
|
||||
|
||||
if (IsConnected && !_cancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
await SendAsync(new MqttDisconnectPacket(), _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
var disconnectPacket = CreateDisconnectPacket(options);
|
||||
await SendAsync(disconnectPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -120,7 +127,7 @@ namespace MQTTnet.Client
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
|
||||
public async Task<MqttClientSubscribeResult> SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
@@ -128,21 +135,16 @@ namespace MQTTnet.Client
|
||||
|
||||
var subscribePacket = new MqttSubscribePacket
|
||||
{
|
||||
PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier(),
|
||||
TopicFilters = topicFilters.ToList()
|
||||
PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier()
|
||||
};
|
||||
|
||||
var response = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
subscribePacket.TopicFilters.AddRange(topicFilters);
|
||||
|
||||
if (response.SubscribeReturnCodes.Count != subscribePacket.TopicFilters.Count)
|
||||
{
|
||||
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
|
||||
}
|
||||
|
||||
return subscribePacket.TopicFilters.Select((t, i) => new MqttSubscribeResult(t, response.SubscribeReturnCodes[i])).ToList();
|
||||
var subAckPacket = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
return _adapter.PacketFormatterAdapter.DataConverter.CreateClientSubscribeResult(subscribePacket, subAckPacket);
|
||||
}
|
||||
|
||||
public Task UnsubscribeAsync(IEnumerable<string> topicFilters)
|
||||
public async Task<MqttClientUnsubscribeResult> UnsubscribeAsync(IEnumerable<string> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
@@ -150,36 +152,47 @@ namespace MQTTnet.Client
|
||||
|
||||
var unsubscribePacket = new MqttUnsubscribePacket
|
||||
{
|
||||
PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier(),
|
||||
TopicFilters = topicFilters.ToList()
|
||||
PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier()
|
||||
};
|
||||
|
||||
return SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, _cancellationTokenSource.Token);
|
||||
unsubscribePacket.TopicFilters.AddRange(topicFilters);
|
||||
|
||||
var unsubAckPacket = await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
return _adapter.PacketFormatterAdapter.DataConverter.CreateClientUnsubscribeResult(unsubscribePacket, unsubAckPacket);
|
||||
}
|
||||
|
||||
public Task PublishAsync(MqttApplicationMessage applicationMessage)
|
||||
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
ThrowIfNotConnected();
|
||||
|
||||
var publishPacket = _adapter.PacketFormatterAdapter.ConvertApplicationMessageToPublishPacket(applicationMessage);
|
||||
var publishPacket = _adapter.PacketFormatterAdapter.DataConverter.CreatePublishPacket(applicationMessage);
|
||||
|
||||
switch (applicationMessage.QualityOfServiceLevel)
|
||||
{
|
||||
case MqttQualityOfServiceLevel.AtMostOnce:
|
||||
{
|
||||
// No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier]
|
||||
return SendAsync(publishPacket, _cancellationTokenSource.Token);
|
||||
await SendAsync(publishPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
return new MqttClientPublishResult();
|
||||
}
|
||||
case MqttQualityOfServiceLevel.AtLeastOnce:
|
||||
{
|
||||
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
|
||||
return SendAndReceiveAsync<MqttPubAckPacket>(publishPacket, _cancellationTokenSource.Token);
|
||||
var response = await SendAndReceiveAsync<MqttPubAckPacket>(publishPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
||||
var result = new MqttClientPublishResult();
|
||||
if (response.ReasonCode != null)
|
||||
{
|
||||
result.ReasonCode = (MqttClientPublishReasonCode)response.ReasonCode;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
case MqttQualityOfServiceLevel.ExactlyOnce:
|
||||
{
|
||||
return PublishExactlyOnce(publishPacket, _cancellationTokenSource.Token);
|
||||
return await PublishExactlyOnceAsync(publishPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -198,28 +211,22 @@ namespace MQTTnet.Client
|
||||
_adapter = null;
|
||||
}
|
||||
|
||||
private async Task<MqttConnAckPacket> AuthenticateAsync(MqttApplicationMessage willApplicationMessage, CancellationToken cancellationToken)
|
||||
private async Task<MqttClientConnectResult> AuthenticateAsync(MqttApplicationMessage willApplicationMessage, CancellationToken cancellationToken)
|
||||
{
|
||||
var connectPacket = new MqttConnectPacket
|
||||
{
|
||||
ClientId = Options.ClientId,
|
||||
Username = Options.Credentials?.Username,
|
||||
Password = Options.Credentials?.Password,
|
||||
CleanSession = Options.CleanSession,
|
||||
KeepAlivePeriod = (ushort)Options.KeepAlivePeriod.TotalSeconds,
|
||||
WillMessage = willApplicationMessage
|
||||
};
|
||||
var connectPacket = _adapter.PacketFormatterAdapter.DataConverter.CreateConnectPacket(
|
||||
willApplicationMessage,
|
||||
Options);
|
||||
|
||||
//connectPacket.RequestProblemInformationProperty = true;
|
||||
//connectPacket.RequestResponseInformationProperty = true;
|
||||
var connAckPacket = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket, cancellationToken).ConfigureAwait(false);
|
||||
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
|
||||
var result = _adapter.PacketFormatterAdapter.DataConverter.CreateClientConnectResult(connAckPacket);
|
||||
|
||||
if (result.ResultCode != MqttClientConnectResultCode.Success)
|
||||
{
|
||||
throw new MqttConnectingFailedException(response.ConnectReturnCode);
|
||||
throw new MqttConnectingFailedException(result.ResultCode);
|
||||
}
|
||||
|
||||
return response;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ThrowIfNotConnected()
|
||||
@@ -237,7 +244,7 @@ namespace MQTTnet.Client
|
||||
var clientWasConnected = IsConnected;
|
||||
|
||||
InitiateDisconnect();
|
||||
|
||||
|
||||
IsConnected = false;
|
||||
|
||||
try
|
||||
@@ -249,7 +256,7 @@ namespace MQTTnet.Client
|
||||
|
||||
await WaitForTaskAsync(_packetReceiverTask, sender).ConfigureAwait(false);
|
||||
await WaitForTaskAsync(_keepAliveMessageSenderTask, sender).ConfigureAwait(false);
|
||||
|
||||
|
||||
_logger.Verbose("Disconnected from adapter.");
|
||||
}
|
||||
catch (Exception adapterException)
|
||||
@@ -311,9 +318,9 @@ namespace MQTTnet.Client
|
||||
try
|
||||
{
|
||||
await _adapter.SendPacketAsync(requestPacket, cancellationToken).ConfigureAwait(false);
|
||||
var respone = await Internal.TaskExtensions.TimeoutAfterAsync(ct => packetAwaiter.Task, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||
return await packetAwaiter.WaitOneAsync(Options.CommunicationTimeout);
|
||||
|
||||
return (TResponsePacket)respone;
|
||||
//return (TResponsePacket)await Internal.TaskExtensions.TimeoutAfterAsync(ct => packetAwaiter.Task, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (MqttCommunicationTimedOutException)
|
||||
{
|
||||
@@ -388,8 +395,7 @@ namespace MQTTnet.Client
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (packet != null && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -443,7 +449,7 @@ namespace MQTTnet.Client
|
||||
|
||||
if (packet is MqttDisconnectPacket)
|
||||
{
|
||||
return DisconnectAsync();
|
||||
return DisconnectAsync(null);
|
||||
}
|
||||
|
||||
if (packet is MqttPubRelPacket pubRelPacket)
|
||||
@@ -466,14 +472,14 @@ namespace MQTTnet.Client
|
||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
||||
{
|
||||
FireApplicationMessageReceivedEvent(publishPacket);
|
||||
return SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier }, cancellationToken);
|
||||
return SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier, ReasonCode = MqttPubAckReasonCode.Success }, cancellationToken);
|
||||
}
|
||||
|
||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
||||
{
|
||||
// QoS 2 is implement as method "B" (4.3.3 QoS 2: Exactly once delivery)
|
||||
FireApplicationMessageReceivedEvent(publishPacket);
|
||||
return SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }, cancellationToken);
|
||||
return SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier, ReasonCode = MqttPubRecReasonCode.Success }, cancellationToken);
|
||||
}
|
||||
|
||||
throw new MqttCommunicationException("Received a not supported QoS level.");
|
||||
@@ -483,23 +489,33 @@ namespace MQTTnet.Client
|
||||
{
|
||||
var response = new MqttPubCompPacket
|
||||
{
|
||||
PacketIdentifier = pubRelPacket.PacketIdentifier
|
||||
PacketIdentifier = pubRelPacket.PacketIdentifier,
|
||||
ReasonCode = MqttPubCompReasonCode.Success
|
||||
};
|
||||
|
||||
return SendAsync(response, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task PublishExactlyOnce(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
|
||||
private async Task<MqttClientPublishResult> PublishExactlyOnceAsync(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
|
||||
{
|
||||
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
|
||||
|
||||
var pubRecPacket = await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket, cancellationToken).ConfigureAwait(false);
|
||||
var pubRelPacket = new MqttPubRelPacket
|
||||
{
|
||||
PacketIdentifier = pubRecPacket.PacketIdentifier
|
||||
PacketIdentifier = pubRecPacket.PacketIdentifier,
|
||||
ReasonCode = MqttPubRelReasonCode.Success
|
||||
};
|
||||
|
||||
await SendAndReceiveAsync<MqttPubCompPacket>(pubRelPacket, cancellationToken).ConfigureAwait(false);
|
||||
var pubCompPacket = await SendAndReceiveAsync<MqttPubCompPacket>(pubRelPacket, cancellationToken).ConfigureAwait(false);
|
||||
var result = new MqttClientPublishResult();
|
||||
|
||||
if (pubRecPacket.ReasonCode != null)
|
||||
{
|
||||
result.ReasonCode = (MqttClientPublishReasonCode)pubRecPacket.ReasonCode;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void StartReceivingPackets(CancellationToken cancellationToken)
|
||||
@@ -507,7 +523,7 @@ namespace MQTTnet.Client
|
||||
_packetReceiverTask = Task.Factory.StartNew(
|
||||
() => ReceivePacketsAsync(cancellationToken),
|
||||
cancellationToken,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default).Unwrap();
|
||||
}
|
||||
|
||||
@@ -524,8 +540,7 @@ namespace MQTTnet.Client
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Move conversion to formatter.
|
||||
var applicationMessage = publishPacket.ToApplicationMessage();
|
||||
var applicationMessage = _adapter.PacketFormatterAdapter.DataConverter.CreateApplicationMessage(publishPacket);
|
||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(Options.ClientId, applicationMessage));
|
||||
}
|
||||
catch (Exception exception)
|
||||
@@ -559,5 +574,31 @@ namespace MQTTnet.Client
|
||||
{
|
||||
return Interlocked.CompareExchange(ref _disconnectGate, 1, 0) != 0;
|
||||
}
|
||||
|
||||
private MqttDisconnectPacket CreateDisconnectPacket(MqttClientDisconnectOptions options)
|
||||
{
|
||||
var packet = new MqttDisconnectPacket();
|
||||
|
||||
if (_adapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
packet.ReasonCode = MqttDisconnectReasonCode.NormalDisconnection;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.ReasonCode = (MqttDisconnectReasonCode)options.ReasonCode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options != null)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Reason codes for disconnect are only supported for MQTTv5.");
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public class MqttClientConnectResult
|
||||
{
|
||||
public MqttClientConnectResult(bool isSessionPresent)
|
||||
{
|
||||
IsSessionPresent = isSessionPresent;
|
||||
}
|
||||
|
||||
public bool IsSessionPresent { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public class MqttClientConnectedEventArgs : EventArgs
|
||||
{
|
||||
public MqttClientConnectedEventArgs(bool isSessionPresent)
|
||||
{
|
||||
IsSessionPresent = isSessionPresent;
|
||||
}
|
||||
|
||||
public bool IsSessionPresent { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public static class MqttClientExtensions
|
||||
{
|
||||
public static Task<IList<MqttSubscribeResult>> SubscribeAsync(this IMqttClient client, params TopicFilter[] topicFilters)
|
||||
public static Task DisconnectAsync(this IMqttClient client)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
return client.DisconnectAsync(null);
|
||||
}
|
||||
|
||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, params TopicFilter[] topicFilters)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
@@ -16,7 +24,7 @@ namespace MQTTnet.Client
|
||||
return client.SubscribeAsync(topicFilters.ToList());
|
||||
}
|
||||
|
||||
public static Task<IList<MqttSubscribeResult>> SubscribeAsync(this IMqttClient client, string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -24,7 +32,7 @@ namespace MQTTnet.Client
|
||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
||||
}
|
||||
|
||||
public static Task<IList<MqttSubscribeResult>> SubscribeAsync(this IMqttClient client, string topic)
|
||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, string topic)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -32,7 +40,7 @@ namespace MQTTnet.Client
|
||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
|
||||
}
|
||||
|
||||
public static Task UnsubscribeAsync(this IMqttClient client, params string[] topicFilters)
|
||||
public static Task<MqttClientUnsubscribeResult> UnsubscribeAsync(this IMqttClient client, params string[] topicFilters)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public class MqttSubscribeResult
|
||||
{
|
||||
public MqttSubscribeResult(TopicFilter topicFilter, MqttSubscribeReturnCode returnCode)
|
||||
{
|
||||
TopicFilter = topicFilter;
|
||||
ReturnCode = returnCode;
|
||||
}
|
||||
|
||||
public TopicFilter TopicFilter { get; }
|
||||
|
||||
public MqttSubscribeReturnCode ReturnCode { get; }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public interface IMqttClientChannelOptions
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public interface IMqttClientCredentials
|
||||
{
|
||||
+11
-1
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public interface IMqttClientOptions
|
||||
{
|
||||
@@ -16,5 +16,15 @@ namespace MQTTnet.Client
|
||||
TimeSpan? KeepAliveSendInterval { get; }
|
||||
|
||||
MqttApplicationMessage WillMessage { get; }
|
||||
uint? WillDelayInterval { get; }
|
||||
|
||||
string AuthenticationMethod { get; }
|
||||
byte[] AuthenticationData { get; }
|
||||
uint? MaximumPacketSize { get; }
|
||||
ushort? ReceiveMaximum { get; }
|
||||
bool? RequestProblemInformation { get; }
|
||||
bool? RequestResponseInformation { get; }
|
||||
uint? SessionExpiryInterval { get; }
|
||||
ushort? TopicAliasMaximum { get; }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientCredentials : IMqttClientCredentials
|
||||
{
|
||||
+13
-2
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientOptions : IMqttClientOptions
|
||||
{
|
||||
@@ -9,12 +9,23 @@ namespace MQTTnet.Client
|
||||
public bool CleanSession { get; set; } = true;
|
||||
public IMqttClientCredentials Credentials { get; set; } = new MqttClientCredentials();
|
||||
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
||||
public IMqttClientChannelOptions ChannelOptions { get; set; }
|
||||
|
||||
public IMqttClientChannelOptions ChannelOptions { get; set; }
|
||||
public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
||||
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(15);
|
||||
public TimeSpan? KeepAliveSendInterval { get; set; }
|
||||
|
||||
public MqttApplicationMessage WillMessage { get; set; }
|
||||
public uint? WillDelayInterval { get; set; }
|
||||
|
||||
public string AuthenticationMethod { get; set; }
|
||||
public byte[] AuthenticationData { get; set; }
|
||||
|
||||
public uint? MaximumPacketSize { get; set; }
|
||||
public ushort? ReceiveMaximum { get; set; }
|
||||
public bool? RequestProblemInformation { get; set; }
|
||||
public bool? RequestResponseInformation { get; set; }
|
||||
public uint? SessionExpiryInterval { get; set; }
|
||||
public ushort? TopicAliasMaximum { get; set; }
|
||||
}
|
||||
}
|
||||
+50
-1
@@ -2,7 +2,7 @@
|
||||
using System.Linq;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientOptionsBuilder
|
||||
{
|
||||
@@ -55,6 +55,55 @@ namespace MQTTnet.Client
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithAuthentication(string method, byte[] data)
|
||||
{
|
||||
_options.AuthenticationMethod = method;
|
||||
_options.AuthenticationData = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithWillDelayInterval(uint? willDelayInterval)
|
||||
{
|
||||
_options.WillDelayInterval = willDelayInterval;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithTopicAliasMaximum(ushort? topicAliasMaximum)
|
||||
{
|
||||
_options.TopicAliasMaximum = topicAliasMaximum;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithMaximumPacketSize(uint? maximumPacketSize)
|
||||
{
|
||||
_options.MaximumPacketSize = maximumPacketSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithReceiveMaximum(ushort? receiveMaximum)
|
||||
{
|
||||
_options.ReceiveMaximum = receiveMaximum;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithRequestProblemInformation(bool? requestProblemInformation = true)
|
||||
{
|
||||
_options.RequestProblemInformation = requestProblemInformation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithRequestResponseInformation(bool? requestResponseInformation = true)
|
||||
{
|
||||
_options.RequestResponseInformation = requestResponseInformation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithSessionExpiryInterval(uint? sessionExpiryInterval)
|
||||
{
|
||||
_options.SessionExpiryInterval = sessionExpiryInterval;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
|
||||
{
|
||||
_options.Credentials = new MqttClientCredentials
|
||||
+1
-1
@@ -4,7 +4,7 @@ using System.Net.Security;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientOptionsBuilderTlsParameters
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientTcpOptions : IMqttClientChannelOptions
|
||||
{
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public static class MqttClientTcpOptionsExtensions
|
||||
{
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientTlsOptions
|
||||
{
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientWebSocketOptions : IMqttClientChannelOptions
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.Options
|
||||
{
|
||||
public class MqttClientWebSocketProxyOptions
|
||||
{
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Client.PacketDispatcher
|
||||
{
|
||||
public interface IMqttPacketAwaiter
|
||||
{
|
||||
void Complete(MqttBasePacket packet);
|
||||
|
||||
void Fail(Exception exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Client.PacketDispatcher
|
||||
{
|
||||
public sealed class MqttPacketAwaiter<TPacket> : IMqttPacketAwaiter where TPacket : MqttBasePacket
|
||||
{
|
||||
private readonly TaskCompletionSource<MqttBasePacket> _packet = new TaskCompletionSource<MqttBasePacket>();
|
||||
|
||||
public async Task<TPacket> WaitOneAsync(TimeSpan timeout)
|
||||
{
|
||||
using (var timeoutToken = new CancellationTokenSource(timeout))
|
||||
{
|
||||
timeoutToken.Token.Register(() => _packet.TrySetCanceled());
|
||||
|
||||
var packet = await _packet.Task.ConfigureAwait(false);
|
||||
return (TPacket)packet;
|
||||
}
|
||||
}
|
||||
|
||||
public void Complete(MqttBasePacket packet)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
|
||||
_packet.TrySetResult(packet);
|
||||
}
|
||||
|
||||
public void Fail(Exception exception)
|
||||
{
|
||||
if (exception == null) throw new ArgumentNullException(nameof(exception));
|
||||
|
||||
_packet.TrySetException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -3,17 +3,17 @@ using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
namespace MQTTnet.Client.PacketDispatcher
|
||||
{
|
||||
public class MqttPacketDispatcher
|
||||
{
|
||||
private readonly ConcurrentDictionary<Tuple<ushort, Type>, TaskCompletionSource<MqttBasePacket>> _awaiters = new ConcurrentDictionary<Tuple<ushort, Type>, TaskCompletionSource<MqttBasePacket>>();
|
||||
|
||||
private readonly ConcurrentDictionary<Tuple<ushort, Type>, IMqttPacketAwaiter> _awaiters = new ConcurrentDictionary<Tuple<ushort, Type>, IMqttPacketAwaiter>();
|
||||
|
||||
public void Dispatch(Exception exception)
|
||||
{
|
||||
foreach (var awaiter in _awaiters)
|
||||
{
|
||||
Task.Run(() => awaiter.Value.TrySetException(exception)); // Task.Run fixes a dead lock. Without this the client only receives one message.
|
||||
Task.Run(() => awaiter.Value.Fail(exception)); // Task.Run fixes a dead lock. Without this the client only receives one message.
|
||||
}
|
||||
|
||||
_awaiters.Clear();
|
||||
@@ -31,10 +31,10 @@ namespace MQTTnet.Client
|
||||
|
||||
var type = packet.GetType();
|
||||
var key = new Tuple<ushort, Type>(identifier, type);
|
||||
|
||||
|
||||
if (_awaiters.TryRemove(key, out var awaiter))
|
||||
{
|
||||
Task.Run(() => awaiter.TrySetResult(packet)); // Task.Run fixes a dead lock. Without this the client only receives one message.
|
||||
Task.Run(() => awaiter.Complete(packet)); // Task.Run fixes a dead lock. Without this the client only receives one message.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,22 +46,22 @@ namespace MQTTnet.Client
|
||||
_awaiters.Clear();
|
||||
}
|
||||
|
||||
public TaskCompletionSource<MqttBasePacket> AddPacketAwaiter<TResponsePacket>(ushort? identifier) where TResponsePacket : MqttBasePacket
|
||||
public MqttPacketAwaiter<TResponsePacket> AddPacketAwaiter<TResponsePacket>(ushort? identifier) where TResponsePacket : MqttBasePacket
|
||||
{
|
||||
var tcs = new TaskCompletionSource<MqttBasePacket>();
|
||||
var awaiter = new MqttPacketAwaiter<TResponsePacket>();
|
||||
|
||||
if (!identifier.HasValue)
|
||||
{
|
||||
identifier = 0;
|
||||
}
|
||||
|
||||
var key = new Tuple<ushort, Type>(identifier ?? 0, typeof(TResponsePacket));
|
||||
if (!_awaiters.TryAdd(key, tcs))
|
||||
|
||||
var key = new Tuple<ushort, Type>(identifier.Value, typeof(TResponsePacket));
|
||||
if (!_awaiters.TryAdd(key, awaiter))
|
||||
{
|
||||
throw new InvalidOperationException($"The packet dispatcher already has an awaiter for packet of type '{key.Item2.Name}' with identifier {key.Item1}.");
|
||||
}
|
||||
|
||||
return tcs;
|
||||
return awaiter;
|
||||
}
|
||||
|
||||
public void RemovePacketAwaiter<TResponsePacket>(ushort? identifier) where TResponsePacket : MqttBasePacket
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace MQTTnet.Client.Publishing
|
||||
{
|
||||
public enum MqttClientPublishReasonCode
|
||||
{
|
||||
Success = 0,
|
||||
NoMatchingSubscribers = 16,
|
||||
UnspecifiedError = 128,
|
||||
ImplementationSpecificError = 131,
|
||||
NotAuthorized = 135,
|
||||
TopicNameInvalid = 144,
|
||||
PacketIdentifierInUse = 145,
|
||||
QuotaExceeded = 151,
|
||||
PayloadFormatInvalid = 153
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace MQTTnet.Client.Publishing
|
||||
{
|
||||
public class MqttClientPublishResult
|
||||
{
|
||||
public MqttClientPublishReasonCode ReasonCode { get; set; } = MqttClientPublishReasonCode.Success;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Client.Subscribing
|
||||
{
|
||||
public class MqttClientSubscribeResult
|
||||
{
|
||||
public List<MqttClientSubscribeResultItem> Items { get; } = new List<MqttClientSubscribeResultItem>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace MQTTnet.Client.Subscribing
|
||||
{
|
||||
public enum MqttClientSubscribeResultCode
|
||||
{
|
||||
GrantedQoS0 = 0,
|
||||
GrantedQoS1 = 1,
|
||||
GrantedQoS2 = 2,
|
||||
UnspecifiedError = 128,
|
||||
ImplementationSpecificError = 131,
|
||||
NotAuthorized = 135,
|
||||
TopicFilterInvalid = 143,
|
||||
PacketIdentifierInUse = 145,
|
||||
QuotaExceeded = 151,
|
||||
SharedSubscriptionsNotSupported = 158,
|
||||
SubscriptionIdentifiersNotSupported = 161,
|
||||
WildcardSubscriptionsNotSupported = 162
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client.Subscribing
|
||||
{
|
||||
public class MqttClientSubscribeResultItem
|
||||
{
|
||||
public MqttClientSubscribeResultItem(TopicFilter topicFilter, MqttClientSubscribeResultCode resultCode)
|
||||
{
|
||||
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
|
||||
ResultCode = resultCode;
|
||||
}
|
||||
|
||||
public TopicFilter TopicFilter { get; }
|
||||
|
||||
public MqttClientSubscribeResultCode ResultCode { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Client.Unsubscribing
|
||||
{
|
||||
public class MqttClientUnsubscribeResult
|
||||
{
|
||||
public List<MqttClientUnsubscribeResultItem> Items { get; } =new List<MqttClientUnsubscribeResultItem>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace MQTTnet.Client.Unsubscribing
|
||||
{
|
||||
public enum MqttClientUnsubscribeResultCode
|
||||
{
|
||||
Success = 0,
|
||||
NoSubscriptionExisted = 17,
|
||||
UnspecifiedError = 128,
|
||||
ImplementationSpecificError = 131,
|
||||
NotAuthorized = 135,
|
||||
TopicFilterInvalid = 143,
|
||||
PacketIdentifierInUse = 145
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Client.Unsubscribing
|
||||
{
|
||||
public class MqttClientUnsubscribeResultItem
|
||||
{
|
||||
public MqttClientUnsubscribeResultItem(string topicFilter, MqttClientUnsubscribeResultCode reasonCode)
|
||||
{
|
||||
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
|
||||
ReasonCode = reasonCode;
|
||||
}
|
||||
|
||||
public string TopicFilter { get; }
|
||||
|
||||
public MqttClientUnsubscribeResultCode ReasonCode { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Formatter
|
||||
{
|
||||
public interface IMqttDataConverter
|
||||
{
|
||||
MqttPublishPacket CreatePublishPacket(MqttApplicationMessage applicationMessage);
|
||||
|
||||
MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket);
|
||||
|
||||
MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket);
|
||||
|
||||
MqttConnectPacket CreateConnectPacket(MqttApplicationMessage willApplicationMessage, IMqttClientOptions options);
|
||||
|
||||
MqttClientSubscribeResult CreateClientSubscribeResult(MqttSubscribePacket subscribePacket, MqttSubAckPacket subAckPacket);
|
||||
|
||||
MqttClientUnsubscribeResult CreateClientUnsubscribeResult(MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket);
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,12 @@ namespace MQTTnet.Formatter
|
||||
{
|
||||
public interface IMqttPacketFormatter
|
||||
{
|
||||
IMqttDataConverter DataConverter { get; }
|
||||
|
||||
ArraySegment<byte> Encode(MqttBasePacket mqttPacket);
|
||||
|
||||
MqttBasePacket Decode(ReceivedMqttPacket receivedMqttPacket);
|
||||
|
||||
MqttPublishPacket ConvertApplicationMessageToPublishPacket(MqttApplicationMessage applicationMessage);
|
||||
|
||||
void FreeBuffer();
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,17 @@
|
||||
{
|
||||
public struct MqttFixedHeader
|
||||
{
|
||||
public MqttFixedHeader(byte flags, uint remainingLength)
|
||||
public MqttFixedHeader(byte flags, int remainingLength, int totalLength)
|
||||
{
|
||||
Flags = flags;
|
||||
RemainingLength = remainingLength;
|
||||
TotalLength = totalLength;
|
||||
}
|
||||
|
||||
public byte Flags { get; }
|
||||
|
||||
public uint RemainingLength { get; }
|
||||
public int RemainingLength { get; }
|
||||
|
||||
public int TotalLength { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Formatter.V310;
|
||||
using MQTTnet.Formatter.V311;
|
||||
using MQTTnet.Formatter.V500;
|
||||
using MQTTnet.Formatter.V3;
|
||||
using MQTTnet.Formatter.V5;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Formatter
|
||||
@@ -22,35 +21,26 @@ namespace MQTTnet.Formatter
|
||||
}
|
||||
|
||||
public MqttProtocolVersion? ProtocolVersion { get; private set; }
|
||||
|
||||
public MqttPublishPacket ConvertApplicationMessageToPublishPacket(MqttApplicationMessage applicationMessage)
|
||||
|
||||
public IMqttDataConverter DataConverter
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
if (_formatter == null)
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("Protocol version not set or detected.");
|
||||
ThrowIfFormatterNotSet();
|
||||
return _formatter.DataConverter;
|
||||
}
|
||||
|
||||
return _formatter.ConvertApplicationMessageToPublishPacket(applicationMessage);
|
||||
}
|
||||
|
||||
public ArraySegment<byte> Encode(MqttBasePacket packet)
|
||||
{
|
||||
if (_formatter == null)
|
||||
{
|
||||
throw new InvalidOperationException("Protocol version not set or detected.");
|
||||
}
|
||||
ThrowIfFormatterNotSet();
|
||||
|
||||
return _formatter.Encode(packet);
|
||||
}
|
||||
|
||||
public MqttBasePacket Decode(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
if (_formatter == null)
|
||||
{
|
||||
throw new InvalidOperationException("Protocol version not set or detected.");
|
||||
}
|
||||
ThrowIfFormatterNotSet();
|
||||
|
||||
return _formatter.Decode(receivedMqttPacket);
|
||||
}
|
||||
@@ -64,7 +54,7 @@ namespace MQTTnet.Formatter
|
||||
{
|
||||
var protocolVersion = ParseProtocolVersion(receivedMqttPacket);
|
||||
|
||||
// Reset the position of the stream beacuse the protocol version is part of
|
||||
// Reset the position of the stream because the protocol version is part of
|
||||
// the regular CONNECT packet. So it will not properly deserialized if this
|
||||
// data is missing.
|
||||
receivedMqttPacket.Body.Seek(0);
|
||||
@@ -138,5 +128,13 @@ namespace MQTTnet.Formatter
|
||||
|
||||
throw new MqttProtocolViolationException($"Protocol '{protocolName}' not supported.");
|
||||
}
|
||||
|
||||
private void ThrowIfFormatterNotSet()
|
||||
{
|
||||
if (_formatter == null)
|
||||
{
|
||||
throw new InvalidOperationException("Protocol version not set or detected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,29 +40,30 @@ namespace MQTTnet.Formatter
|
||||
var hasRemainingLength = buffer[1] != 0;
|
||||
if (!hasRemainingLength)
|
||||
{
|
||||
return new MqttFixedHeader(buffer[0], 0);
|
||||
return new MqttFixedHeader(buffer[0], 0, totalBytesRead);
|
||||
}
|
||||
|
||||
#if WINDOWS_UWP
|
||||
// UWP will have a dead lock when calling this not async.
|
||||
var bodyLength = await ReadBodyLengthAsync(buffer[1], cancellationToken).ConfigureAwait(false);
|
||||
#else
|
||||
// Here the async/await pattern is not used becuase the overhead of context switches
|
||||
// Here the async/await pattern is not used because the overhead of context switches
|
||||
// is too big for reading 1 byte in a row. We expect that the remaining data was sent
|
||||
// directly after the initial bytes. If the client disconnects just in this moment we
|
||||
// will get an exception anyway.
|
||||
var bodyLength = ReadBodyLength(buffer[1], cancellationToken);
|
||||
#endif
|
||||
|
||||
return new MqttFixedHeader(buffer[0], bodyLength);
|
||||
totalBytesRead += bodyLength;
|
||||
return new MqttFixedHeader(buffer[0], bodyLength, totalBytesRead);
|
||||
}
|
||||
|
||||
#if !WINDOWS_UWP
|
||||
private uint ReadBodyLength(byte initialEncodedByte, CancellationToken cancellationToken)
|
||||
private int ReadBodyLength(byte initialEncodedByte, CancellationToken cancellationToken)
|
||||
{
|
||||
var offset = 0;
|
||||
var multiplier = 128;
|
||||
var value = (uint)(initialEncodedByte & 127);
|
||||
var value = (initialEncodedByte & 127);
|
||||
int encodedByte = initialEncodedByte;
|
||||
|
||||
while ((encodedByte & 128) != 0)
|
||||
@@ -77,7 +78,7 @@ namespace MQTTnet.Formatter
|
||||
|
||||
encodedByte = ReadByte(cancellationToken);
|
||||
|
||||
value += (uint)((encodedByte & 127) * multiplier);
|
||||
value += (encodedByte & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
}
|
||||
|
||||
@@ -100,11 +101,11 @@ namespace MQTTnet.Formatter
|
||||
|
||||
#else
|
||||
|
||||
private async Task<uint> ReadBodyLengthAsync(byte initialEncodedByte, CancellationToken cancellationToken)
|
||||
private async Task<int> ReadBodyLengthAsync(byte initialEncodedByte, CancellationToken cancellationToken)
|
||||
{
|
||||
var offset = 0;
|
||||
var multiplier = 128;
|
||||
var value = (uint)(initialEncodedByte & 127);
|
||||
var value = initialEncodedByte & 127;
|
||||
int encodedByte = initialEncodedByte;
|
||||
|
||||
while ((encodedByte & 128) != 0)
|
||||
@@ -119,7 +120,7 @@ namespace MQTTnet.Formatter
|
||||
|
||||
encodedByte = await ReadByteAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
value += (uint)((encodedByte & 127) * multiplier);
|
||||
value += (encodedByte & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,12 +67,14 @@ namespace MQTTnet.Formatter
|
||||
|
||||
public void WriteWithLengthPrefix(byte[] value)
|
||||
{
|
||||
if (value == null) throw new ArgumentNullException(nameof(value));
|
||||
|
||||
EnsureAdditionalCapacity(value.Length + 2);
|
||||
|
||||
Write((ushort)value.Length);
|
||||
Write(value, 0, value.Length);
|
||||
}
|
||||
|
||||
|
||||
public void Write(byte @byte)
|
||||
{
|
||||
EnsureAdditionalCapacity(1);
|
||||
@@ -173,7 +175,7 @@ namespace MQTTnet.Formatter
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (newBufferLength < capacity)
|
||||
{
|
||||
newBufferLength *= 2;
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V3
|
||||
{
|
||||
public class MqttV310DataConverter : IMqttDataConverter
|
||||
{
|
||||
public MqttPublishPacket CreatePublishPacket(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
if (applicationMessage.UserProperties?.Any() == true)
|
||||
{
|
||||
throw new MqttProtocolViolationException("User properties are not supported in MQTT version 3.");
|
||||
}
|
||||
|
||||
return new MqttPublishPacket
|
||||
{
|
||||
Topic = applicationMessage.Topic,
|
||||
Payload = applicationMessage.Payload,
|
||||
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
|
||||
Retain = applicationMessage.Retain,
|
||||
Dup = false
|
||||
};
|
||||
}
|
||||
|
||||
public MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket)
|
||||
{
|
||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
||||
|
||||
return new MqttApplicationMessage
|
||||
{
|
||||
Topic = publishPacket.Topic,
|
||||
Payload = publishPacket.Payload,
|
||||
QualityOfServiceLevel = publishPacket.QualityOfServiceLevel,
|
||||
Retain = publishPacket.Retain
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
{
|
||||
if (connAckPacket == null) throw new ArgumentNullException(nameof(connAckPacket));
|
||||
|
||||
MqttClientConnectResultCode resultCode;
|
||||
switch (connAckPacket.ReturnCode.Value)
|
||||
{
|
||||
case MqttConnectReturnCode.ConnectionAccepted:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.Success;
|
||||
break;
|
||||
}
|
||||
|
||||
case MqttConnectReturnCode.ConnectionRefusedUnacceptableProtocolVersion:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.UnsupportedProtocolVersion;
|
||||
break;
|
||||
}
|
||||
|
||||
case MqttConnectReturnCode.ConnectionRefusedNotAuthorized:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.NotAuthorized;
|
||||
break;
|
||||
}
|
||||
|
||||
case MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.BadUserNameOrPassword;
|
||||
break;
|
||||
}
|
||||
|
||||
case MqttConnectReturnCode.ConnectionRefusedIdentifierRejected:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.ClientIdentifierNotValid;
|
||||
break;
|
||||
}
|
||||
|
||||
case MqttConnectReturnCode.ConnectionRefusedServerUnavailable:
|
||||
{
|
||||
resultCode = MqttClientConnectResultCode.ServerUnavailable;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new MqttProtocolViolationException("Received unexpected return code.");
|
||||
}
|
||||
|
||||
return new MqttClientConnectResult
|
||||
{
|
||||
IsSessionPresent = connAckPacket.IsSessionPresent,
|
||||
ResultCode = resultCode
|
||||
};
|
||||
}
|
||||
|
||||
public MqttConnectPacket CreateConnectPacket(MqttApplicationMessage willApplicationMessage, IMqttClientOptions options)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
|
||||
return new MqttConnectPacket
|
||||
{
|
||||
ClientId = options.ClientId,
|
||||
Username = options.Credentials?.Username,
|
||||
Password = options.Credentials?.Password,
|
||||
CleanSession = options.CleanSession,
|
||||
KeepAlivePeriod = (ushort)options.KeepAlivePeriod.TotalSeconds,
|
||||
WillMessage = willApplicationMessage
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientSubscribeResult CreateClientSubscribeResult(MqttSubscribePacket subscribePacket, MqttSubAckPacket subAckPacket)
|
||||
{
|
||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||
if (subAckPacket == null) throw new ArgumentNullException(nameof(subAckPacket));
|
||||
|
||||
if (subAckPacket.ReturnCodes.Count != subscribePacket.TopicFilters.Count)
|
||||
{
|
||||
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
|
||||
}
|
||||
|
||||
var result = new MqttClientSubscribeResult();
|
||||
|
||||
result.Items.AddRange(subscribePacket.TopicFilters.Select((t, i) =>
|
||||
new MqttClientSubscribeResultItem(t, (MqttClientSubscribeResultCode)subAckPacket.ReturnCodes[i])));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public MqttClientUnsubscribeResult CreateClientUnsubscribeResult(MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket)
|
||||
{
|
||||
if (unsubscribePacket == null) throw new ArgumentNullException(nameof(unsubscribePacket));
|
||||
if (unsubAckPacket == null) throw new ArgumentNullException(nameof(unsubAckPacket));
|
||||
|
||||
var result = new MqttClientUnsubscribeResult();
|
||||
|
||||
result.Items.AddRange(unsubscribePacket.TopicFilters.Select((t, i) =>
|
||||
new MqttClientUnsubscribeResultItem(t, MqttClientUnsubscribeResultCode.Success)));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
-78
@@ -6,7 +6,7 @@ using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V310
|
||||
namespace MQTTnet.Formatter.V3
|
||||
{
|
||||
public class MqttV310PacketFormatter : IMqttPacketFormatter
|
||||
{
|
||||
@@ -14,6 +14,8 @@ namespace MQTTnet.Formatter.V310
|
||||
|
||||
private readonly MqttPacketWriter _packetWriter = new MqttPacketWriter();
|
||||
|
||||
public IMqttDataConverter DataConverter { get; } = new MqttV310DataConverter();
|
||||
|
||||
public ArraySegment<byte> Encode(MqttBasePacket packet)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
@@ -22,7 +24,7 @@ namespace MQTTnet.Formatter.V310
|
||||
_packetWriter.Reset();
|
||||
_packetWriter.Seek(5);
|
||||
|
||||
var fixedHeader = SerializePacket(packet, _packetWriter);
|
||||
var fixedHeader = EncodePacket(packet, _packetWriter);
|
||||
var remainingLength = (uint)(_packetWriter.Length - 5);
|
||||
|
||||
var remainingLengthBuffer = MqttPacketWriter.EncodeVariableByteInteger(remainingLength);
|
||||
@@ -30,7 +32,7 @@ namespace MQTTnet.Formatter.V310
|
||||
var headerSize = FixedHeaderSize + remainingLengthBuffer.Count;
|
||||
var headerOffset = 5 - headerSize;
|
||||
|
||||
// Position cursor on correct offset on beginining of array (has leading 0x0)
|
||||
// Position cursor on correct offset on beginning of array (has leading 0x0)
|
||||
_packetWriter.Seek(headerOffset);
|
||||
_packetWriter.Write(fixedHeader);
|
||||
_packetWriter.Write(remainingLengthBuffer.Array, remainingLengthBuffer.Offset, remainingLengthBuffer.Count);
|
||||
@@ -51,70 +53,54 @@ namespace MQTTnet.Formatter.V310
|
||||
|
||||
switch ((MqttControlPacketType)controlPacketType)
|
||||
{
|
||||
case MqttControlPacketType.Connect: return DeserializeConnectPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.ConnAck: return DeserializeConnAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Connect: return DecodeConnectPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.ConnAck: return DecodeConnAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Disconnect: return new MqttDisconnectPacket();
|
||||
case MqttControlPacketType.Publish: return DeserializePublish(receivedMqttPacket);
|
||||
case MqttControlPacketType.PubAck: return DeserializePubAck(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRec: return DeserializePubRec(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRel: return DeserializePubRel(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubComp: return DeserializePubComp(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Publish: return DecodePublish(receivedMqttPacket);
|
||||
case MqttControlPacketType.PubAck: return DecodePubAck(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRec: return DecodePubRec(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRel: return DecodePubRel(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubComp: return DecodePubComp(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PingReq: return new MqttPingReqPacket();
|
||||
case MqttControlPacketType.PingResp: return new MqttPingRespPacket();
|
||||
case MqttControlPacketType.Subscribe: return DeserializeSubscribe(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.SubAck: return DeserializeSubAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Unsubscibe: return DeserializeUnsubscribe(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.UnsubAck: return DeserializeUnsubAck(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Subscribe: return DecodeSubscribe(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.SubAck: return DecodeSubAck(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Unsubscibe: return DecodeUnsubscribe(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.UnsubAck: return DecodeUnsubAck(receivedMqttPacket.Body);
|
||||
|
||||
default: throw new MqttProtocolViolationException($"Packet type ({controlPacketType}) not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual MqttPublishPacket ConvertApplicationMessageToPublishPacket(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage.UserProperties != null)
|
||||
{
|
||||
throw new MqttProtocolViolationException("User properties are not supported in MQTT version 3.");
|
||||
}
|
||||
|
||||
return new MqttPublishPacket
|
||||
{
|
||||
Topic = applicationMessage.Topic,
|
||||
Payload = applicationMessage.Payload,
|
||||
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
|
||||
Retain = applicationMessage.Retain,
|
||||
Dup = false
|
||||
};
|
||||
}
|
||||
|
||||
public void FreeBuffer()
|
||||
{
|
||||
_packetWriter.FreeBuffer();
|
||||
}
|
||||
|
||||
private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter packetWriter)
|
||||
private byte EncodePacket(MqttBasePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
switch (packet)
|
||||
{
|
||||
case MqttConnectPacket connectPacket: return SerializeConnectPacket(connectPacket, packetWriter);
|
||||
case MqttConnAckPacket connAckPacket: return SerializeConnAckPacket(connAckPacket, packetWriter);
|
||||
case MqttDisconnectPacket _: return SerializeEmptyPacket(MqttControlPacketType.Disconnect);
|
||||
case MqttPingReqPacket _: return SerializeEmptyPacket(MqttControlPacketType.PingReq);
|
||||
case MqttPingRespPacket _: return SerializeEmptyPacket(MqttControlPacketType.PingResp);
|
||||
case MqttPublishPacket publishPacket: return SerializePublishPacket(publishPacket, packetWriter);
|
||||
case MqttPubAckPacket pubAckPacket: return SerializePubAckPacket(pubAckPacket, packetWriter);
|
||||
case MqttPubRecPacket pubRecPacket: return SerializePubRecPacket(pubRecPacket, packetWriter);
|
||||
case MqttPubRelPacket pubRelPacket: return SerializePubRelPacket(pubRelPacket, packetWriter);
|
||||
case MqttPubCompPacket pubCompPacket: return SerializePubCompPacket(pubCompPacket, packetWriter);
|
||||
case MqttSubscribePacket subscribePacket: return SerializeSubscribePacket(subscribePacket, packetWriter);
|
||||
case MqttSubAckPacket subAckPacket: return SerializeSubAckPacket(subAckPacket, packetWriter);
|
||||
case MqttUnsubscribePacket unsubscribePacket: return SerializeUnsubscribePacket(unsubscribePacket, packetWriter);
|
||||
case MqttUnsubAckPacket unsubAckPacket: return SerializeUnsubAckPacket(unsubAckPacket, packetWriter);
|
||||
case MqttConnectPacket connectPacket: return EncodeConnectPacket(connectPacket, packetWriter);
|
||||
case MqttConnAckPacket connAckPacket: return EncodeConnAckPacket(connAckPacket, packetWriter);
|
||||
case MqttDisconnectPacket _: return EncodeEmptyPacket(MqttControlPacketType.Disconnect);
|
||||
case MqttPingReqPacket _: return EncodeEmptyPacket(MqttControlPacketType.PingReq);
|
||||
case MqttPingRespPacket _: return EncodeEmptyPacket(MqttControlPacketType.PingResp);
|
||||
case MqttPublishPacket publishPacket: return EncodePublishPacket(publishPacket, packetWriter);
|
||||
case MqttPubAckPacket pubAckPacket: return EncodePubAckPacket(pubAckPacket, packetWriter);
|
||||
case MqttPubRecPacket pubRecPacket: return EncodePubRecPacket(pubRecPacket, packetWriter);
|
||||
case MqttPubRelPacket pubRelPacket: return EncodePubRelPacket(pubRelPacket, packetWriter);
|
||||
case MqttPubCompPacket pubCompPacket: return EncodePubCompPacket(pubCompPacket, packetWriter);
|
||||
case MqttSubscribePacket subscribePacket: return EncodeSubscribePacket(subscribePacket, packetWriter);
|
||||
case MqttSubAckPacket subAckPacket: return EncodeSubAckPacket(subAckPacket, packetWriter);
|
||||
case MqttUnsubscribePacket unsubscribePacket: return EncodeUnsubscribePacket(unsubscribePacket, packetWriter);
|
||||
case MqttUnsubAckPacket unsubAckPacket: return EncodeUnsubAckPacket(unsubAckPacket, packetWriter);
|
||||
|
||||
default: throw new MqttProtocolViolationException("Packet type invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializeUnsubAck(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodeUnsubAck(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -124,7 +110,7 @@ namespace MQTTnet.Formatter.V310
|
||||
};
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializePubComp(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodePubComp(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -134,7 +120,7 @@ namespace MQTTnet.Formatter.V310
|
||||
};
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializePubRel(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodePubRel(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -144,7 +130,7 @@ namespace MQTTnet.Formatter.V310
|
||||
};
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializePubRec(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodePubRec(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -154,7 +140,7 @@ namespace MQTTnet.Formatter.V310
|
||||
};
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializePubAck(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodePubAck(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -164,7 +150,7 @@ namespace MQTTnet.Formatter.V310
|
||||
};
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializeUnsubscribe(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodeUnsubscribe(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -181,7 +167,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializeSubscribe(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodeSubscribe(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -192,15 +178,19 @@ namespace MQTTnet.Formatter.V310
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
packet.TopicFilters.Add(new TopicFilter(
|
||||
body.ReadStringWithLengthPrefix(),
|
||||
(MqttQualityOfServiceLevel)body.ReadByte()));
|
||||
var topicFilter = new TopicFilter
|
||||
{
|
||||
Topic = body.ReadStringWithLengthPrefix(),
|
||||
QualityOfServiceLevel = (MqttQualityOfServiceLevel)body.ReadByte()
|
||||
};
|
||||
|
||||
packet.TopicFilters.Add(topicFilter);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializePublish(ReceivedMqttPacket receivedMqttPacket)
|
||||
private static MqttBasePacket DecodePublish(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(receivedMqttPacket.Body);
|
||||
|
||||
@@ -229,7 +219,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return packet;
|
||||
}
|
||||
|
||||
private MqttBasePacket DeserializeConnectPacket(MqttPacketBodyReader body)
|
||||
private MqttBasePacket DecodeConnectPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -238,7 +228,7 @@ namespace MQTTnet.Formatter.V310
|
||||
ProtocolName = body.ReadStringWithLengthPrefix(),
|
||||
ProtocolLevel = body.ReadByte()
|
||||
};
|
||||
|
||||
|
||||
var connectFlags = body.ReadByte();
|
||||
if ((connectFlags & 0x1) > 0)
|
||||
{
|
||||
@@ -281,7 +271,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DeserializeSubAckPacket(MqttPacketBodyReader body)
|
||||
private static MqttBasePacket DecodeSubAck(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -292,20 +282,20 @@ namespace MQTTnet.Formatter.V310
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
packet.SubscribeReturnCodes.Add((MqttSubscribeReturnCode)body.ReadByte());
|
||||
packet.ReturnCodes.Add((MqttSubscribeReturnCode)body.ReadByte());
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
protected virtual MqttBasePacket DeserializeConnAckPacket(MqttPacketBodyReader body)
|
||||
protected virtual MqttBasePacket DecodeConnAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttConnAckPacket();
|
||||
|
||||
body.ReadByte(); // Reserved.
|
||||
packet.ConnectReturnCode = (MqttConnectReturnCode)body.ReadByte();
|
||||
packet.ReturnCode = (MqttConnectReturnCode)body.ReadByte();
|
||||
|
||||
return packet;
|
||||
}
|
||||
@@ -329,7 +319,7 @@ namespace MQTTnet.Formatter.V310
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual byte SerializeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
protected virtual byte EncodeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ValidateConnectPacket(packet);
|
||||
|
||||
@@ -391,15 +381,15 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect);
|
||||
}
|
||||
|
||||
protected virtual byte SerializeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
protected virtual byte EncodeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
packetWriter.Write(0); // Reserved.
|
||||
packetWriter.Write((byte)packet.ConnectReturnCode);
|
||||
packetWriter.Write((byte)packet.ReturnCode.Value);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||
}
|
||||
|
||||
private static byte SerializePubRelPacket(MqttPubRelPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodePubRelPacket(MqttPubRelPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -411,7 +401,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02);
|
||||
}
|
||||
|
||||
protected virtual byte SerializePublishPacket(MqttPublishPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodePublishPacket(MqttPublishPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ValidatePublishPacket(packet);
|
||||
|
||||
@@ -456,7 +446,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
|
||||
}
|
||||
|
||||
protected virtual byte SerializePubAckPacket(MqttPubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodePubAckPacket(MqttPubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -468,7 +458,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
|
||||
}
|
||||
|
||||
private static byte SerializePubRecPacket(MqttPubRecPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodePubRecPacket(MqttPubRecPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -480,7 +470,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRec);
|
||||
}
|
||||
|
||||
private static byte SerializePubCompPacket(MqttPubCompPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodePubCompPacket(MqttPubCompPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -492,7 +482,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp);
|
||||
}
|
||||
|
||||
private static byte SerializeSubscribePacket(MqttSubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodeSubscribePacket(MqttSubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
|
||||
|
||||
@@ -515,7 +505,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02);
|
||||
}
|
||||
|
||||
private static byte SerializeSubAckPacket(MqttSubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodeSubAckPacket(MqttSubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -524,9 +514,9 @@ namespace MQTTnet.Formatter.V310
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
if (packet.SubscribeReturnCodes?.Any() == true)
|
||||
if (packet.ReturnCodes?.Any() == true)
|
||||
{
|
||||
foreach (var packetSubscribeReturnCode in packet.SubscribeReturnCodes)
|
||||
foreach (var packetSubscribeReturnCode in packet.ReturnCodes)
|
||||
{
|
||||
packetWriter.Write((byte)packetSubscribeReturnCode);
|
||||
}
|
||||
@@ -535,7 +525,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck);
|
||||
}
|
||||
|
||||
private static byte SerializeUnsubscribePacket(MqttUnsubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
|
||||
|
||||
@@ -557,7 +547,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
|
||||
}
|
||||
|
||||
private static byte SerializeUnsubAckPacket(MqttUnsubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
private static byte EncodeUnsubAckPacket(MqttUnsubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
@@ -568,7 +558,7 @@ namespace MQTTnet.Formatter.V310
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck);
|
||||
}
|
||||
|
||||
private static byte SerializeEmptyPacket(MqttControlPacketType type)
|
||||
private static byte EncodeEmptyPacket(MqttControlPacketType type)
|
||||
{
|
||||
return MqttPacketWriter.BuildFixedHeader(type);
|
||||
}
|
||||
+6
-7
@@ -1,13 +1,12 @@
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Formatter.V310;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V311
|
||||
namespace MQTTnet.Formatter.V3
|
||||
{
|
||||
public class MqttV311PacketFormatter : MqttV310PacketFormatter
|
||||
{
|
||||
protected override byte SerializeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
protected override byte EncodeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ValidateConnectPacket(packet);
|
||||
|
||||
@@ -69,7 +68,7 @@ namespace MQTTnet.Formatter.V311
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect);
|
||||
}
|
||||
|
||||
protected override byte SerializeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
protected override byte EncodeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
byte connectAcknowledgeFlags = 0x0;
|
||||
if (packet.IsSessionPresent)
|
||||
@@ -78,12 +77,12 @@ namespace MQTTnet.Formatter.V311
|
||||
}
|
||||
|
||||
packetWriter.Write(connectAcknowledgeFlags);
|
||||
packetWriter.Write((byte)packet.ConnectReturnCode);
|
||||
packetWriter.Write((byte)packet.ReturnCode);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||
}
|
||||
|
||||
protected override MqttBasePacket DeserializeConnAckPacket(MqttPacketBodyReader body)
|
||||
protected override MqttBasePacket DecodeConnAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
@@ -92,7 +91,7 @@ namespace MQTTnet.Formatter.V311
|
||||
var acknowledgeFlags = body.ReadByte();
|
||||
|
||||
packet.IsSessionPresent = (acknowledgeFlags & 0x1) > 0;
|
||||
packet.ConnectReturnCode = (MqttConnectReturnCode)body.ReadByte();
|
||||
packet.ReturnCode = (MqttConnectReturnCode)body.ReadByte();
|
||||
|
||||
return packet;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500DataConverter : IMqttDataConverter
|
||||
{
|
||||
public MqttPublishPacket CreatePublishPacket(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
var packet = new MqttPublishPacket
|
||||
{
|
||||
Topic = applicationMessage.Topic,
|
||||
Payload = applicationMessage.Payload,
|
||||
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
|
||||
Retain = applicationMessage.Retain,
|
||||
Dup = false,
|
||||
Properties = new MqttPublishPacketProperties
|
||||
{
|
||||
ContentType = applicationMessage.ContentType,
|
||||
CorrelationData = applicationMessage.CorrelationData,
|
||||
MessageExpiryInterval = applicationMessage.MessageExpiryInterval,
|
||||
PayloadFormatIndicator = applicationMessage.PayloadFormatIndicator,
|
||||
ResponseTopic = applicationMessage.ResponseTopic,
|
||||
SubscriptionIdentifier = applicationMessage.SubscriptionIdentifier,
|
||||
TopicAlias = applicationMessage.TopicAlias
|
||||
}
|
||||
};
|
||||
|
||||
if (applicationMessage.UserProperties != null)
|
||||
{
|
||||
packet.Properties.UserProperties.AddRange(applicationMessage.UserProperties);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
public MqttApplicationMessage CreateApplicationMessage(MqttPublishPacket publishPacket)
|
||||
{
|
||||
return new MqttApplicationMessage
|
||||
{
|
||||
Topic = publishPacket.Topic,
|
||||
Payload = publishPacket.Payload,
|
||||
QualityOfServiceLevel = publishPacket.QualityOfServiceLevel,
|
||||
Retain = publishPacket.Retain,
|
||||
UserProperties = publishPacket.Properties?.UserProperties ?? new List<MqttUserProperty>()
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientConnectResult CreateClientConnectResult(MqttConnAckPacket connAckPacket)
|
||||
{
|
||||
if (connAckPacket == null) throw new ArgumentNullException(nameof(connAckPacket));
|
||||
|
||||
return new MqttClientConnectResult
|
||||
{
|
||||
IsSessionPresent = connAckPacket.IsSessionPresent,
|
||||
ResultCode = (MqttClientConnectResultCode)connAckPacket.ReasonCode.Value
|
||||
};
|
||||
}
|
||||
|
||||
public MqttConnectPacket CreateConnectPacket(MqttApplicationMessage willApplicationMessage, IMqttClientOptions options)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
|
||||
return new MqttConnectPacket
|
||||
{
|
||||
ClientId = options.ClientId,
|
||||
Username = options.Credentials?.Username,
|
||||
Password = options.Credentials?.Password,
|
||||
CleanSession = options.CleanSession,
|
||||
KeepAlivePeriod = (ushort)options.KeepAlivePeriod.TotalSeconds,
|
||||
WillMessage = willApplicationMessage,
|
||||
Properties = new MqttConnectPacketProperties
|
||||
{
|
||||
AuthenticationMethod = options.AuthenticationMethod,
|
||||
AuthenticationData = options.AuthenticationData,
|
||||
WillDelayInterval = options.WillDelayInterval,
|
||||
MaximumPacketSize = options.MaximumPacketSize,
|
||||
ReceiveMaximum = options.ReceiveMaximum,
|
||||
RequestProblemInformation = options.RequestProblemInformation,
|
||||
RequestResponseInformation = options.RequestResponseInformation,
|
||||
SessionExpiryInterval = options.SessionExpiryInterval,
|
||||
TopicAliasMaximum = options.TopicAliasMaximum
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientSubscribeResult CreateClientSubscribeResult(MqttSubscribePacket subscribePacket, MqttSubAckPacket subAckPacket)
|
||||
{
|
||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||
if (subAckPacket == null) throw new ArgumentNullException(nameof(subAckPacket));
|
||||
|
||||
if (subAckPacket.ReasonCodes.Count != subscribePacket.TopicFilters.Count)
|
||||
{
|
||||
throw new MqttProtocolViolationException("The reason codes are not matching the topic filters [MQTT-3.9.3-1].");
|
||||
}
|
||||
|
||||
var result = new MqttClientSubscribeResult();
|
||||
|
||||
result.Items.AddRange(subscribePacket.TopicFilters.Select((t, i) =>
|
||||
new MqttClientSubscribeResultItem(t, (MqttClientSubscribeResultCode)subAckPacket.ReasonCodes[i])));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public MqttClientUnsubscribeResult CreateClientUnsubscribeResult(MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket)
|
||||
{
|
||||
if (unsubscribePacket == null) throw new ArgumentNullException(nameof(unsubscribePacket));
|
||||
if (unsubAckPacket == null) throw new ArgumentNullException(nameof(unsubAckPacket));
|
||||
|
||||
if (unsubAckPacket.ReasonCodes.Count != unsubscribePacket.TopicFilters.Count)
|
||||
{
|
||||
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
|
||||
}
|
||||
|
||||
var result = new MqttClientUnsubscribeResult();
|
||||
|
||||
result.Items.AddRange(unsubscribePacket.TopicFilters.Select((t, i) =>
|
||||
new MqttClientUnsubscribeResultItem(t, (MqttClientUnsubscribeResultCode)unsubAckPacket.ReasonCodes[i])));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,717 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PacketDecoder
|
||||
{
|
||||
public MqttBasePacket Decode(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
if (receivedMqttPacket == null) throw new ArgumentNullException(nameof(receivedMqttPacket));
|
||||
|
||||
var controlPacketType = receivedMqttPacket.FixedHeader >> 4;
|
||||
if (controlPacketType < 1 || controlPacketType > 15)
|
||||
{
|
||||
throw new MqttProtocolViolationException($"The packet type is invalid ({controlPacketType}).");
|
||||
}
|
||||
|
||||
switch ((MqttControlPacketType)controlPacketType)
|
||||
{
|
||||
case MqttControlPacketType.Connect: return DecodeConnectPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.ConnAck: return DecodeConnAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Disconnect: return DecodeDisconnectPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Publish: return DecodePublishPacket(receivedMqttPacket.FixedHeader, receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubAck: return DecodePubAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRec: return DecodePubRecPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubRel: return DecodePubRelPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PubComp: return DecodePubCompPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.PingReq: return DecodePingReqPacket();
|
||||
case MqttControlPacketType.PingResp: return DecodePingRespPacket();
|
||||
case MqttControlPacketType.Subscribe: return DecodeSubscribePacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.SubAck: return DecodeSubAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Unsubscibe: return DecodeUnsubscribePacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.UnsubAck: return DecodeUnsubAckPacket(receivedMqttPacket.Body);
|
||||
case MqttControlPacketType.Auth: return DecodeAuthPacket(receivedMqttPacket.Body);
|
||||
|
||||
default: throw new MqttProtocolViolationException($"Packet type ({controlPacketType}) not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeConnectPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttConnectPacket
|
||||
{
|
||||
Properties = new MqttConnectPacketProperties()
|
||||
};
|
||||
|
||||
var protocolName = body.ReadStringWithLengthPrefix();
|
||||
var protocolVersion = body.ReadByte();
|
||||
|
||||
if (protocolName != "MQTT" && protocolVersion != 5)
|
||||
{
|
||||
throw new MqttProtocolViolationException("MQTT protocol name and version do not match MQTT v5.");
|
||||
}
|
||||
|
||||
var connectFlags = body.ReadByte();
|
||||
|
||||
var cleanSessionFlag = (connectFlags & 0x02) > 0;
|
||||
var willMessageFlag = (connectFlags & 0x04) > 0;
|
||||
var willMessageQoS = (byte)(connectFlags >> 3 & 3);
|
||||
var willMessageRetainFlag = (connectFlags & 0x20) > 0;
|
||||
var passwordFlag = (connectFlags & 0x40) > 0;
|
||||
var usernameFlag = (connectFlags & 0x80) > 0;
|
||||
|
||||
packet.CleanSession = cleanSessionFlag;
|
||||
|
||||
if (willMessageFlag)
|
||||
{
|
||||
packet.WillMessage = new MqttApplicationMessage
|
||||
{
|
||||
QualityOfServiceLevel = (MqttQualityOfServiceLevel)willMessageQoS,
|
||||
Retain = willMessageRetainFlag
|
||||
};
|
||||
}
|
||||
|
||||
packet.KeepAlivePeriod = body.ReadTwoByteInteger();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.SessionExpiryInterval)
|
||||
{
|
||||
packet.Properties.SessionExpiryInterval = propertiesReader.ReadSessionExpiryInterval();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationMethod)
|
||||
{
|
||||
packet.Properties.AuthenticationMethod = propertiesReader.ReadAuthenticationMethod();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.WillDelayInterval)
|
||||
{
|
||||
packet.Properties.WillDelayInterval = propertiesReader.ReadWillDelayInterval();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationData)
|
||||
{
|
||||
packet.Properties.AuthenticationData = propertiesReader.ReadAuthenticationData();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReceiveMaximum)
|
||||
{
|
||||
packet.Properties.ReceiveMaximum = propertiesReader.ReadReceiveMaximum();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.TopicAliasMaximum)
|
||||
{
|
||||
packet.Properties.TopicAliasMaximum = propertiesReader.ReadTopicAliasMaximum();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.MaximumPacketSize)
|
||||
{
|
||||
packet.Properties.MaximumPacketSize = propertiesReader.ReadMaximumPacketSize();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.RequestResponseInformation)
|
||||
{
|
||||
packet.Properties.RequestResponseInformation = propertiesReader.RequestResponseInformation();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.RequestProblemInformation)
|
||||
{
|
||||
packet.Properties.RequestProblemInformation = propertiesReader.RequestProblemInformation();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttConnAckPacket));
|
||||
}
|
||||
}
|
||||
|
||||
packet.ClientId = body.ReadStringWithLengthPrefix();
|
||||
|
||||
if (packet.WillMessage != null)
|
||||
{
|
||||
packet.WillMessage.Topic = body.ReadStringWithLengthPrefix();
|
||||
packet.WillMessage.Payload = body.ReadWithLengthPrefix().ToArray();
|
||||
}
|
||||
|
||||
if (usernameFlag)
|
||||
{
|
||||
packet.Username = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
if (passwordFlag)
|
||||
{
|
||||
packet.Password = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeConnAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var acknowledgeFlags = body.ReadByte();
|
||||
|
||||
var packet = new MqttConnAckPacket
|
||||
{
|
||||
IsSessionPresent = (acknowledgeFlags & 0x1) > 0,
|
||||
ReasonCode = (MqttConnectReasonCode)body.ReadByte(),
|
||||
Properties = new MqttConnAckPacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.SessionExpiryInterval)
|
||||
{
|
||||
packet.Properties.SessionExpiryInterval = propertiesReader.ReadSessionExpiryInterval();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationMethod)
|
||||
{
|
||||
packet.Properties.AuthenticationMethod = propertiesReader.ReadAuthenticationMethod();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationData)
|
||||
{
|
||||
packet.Properties.AuthenticationData = propertiesReader.ReadAuthenticationData();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.RetainAvailable)
|
||||
{
|
||||
packet.Properties.RetainAvailable = propertiesReader.ReadRetainAvailable();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReceiveMaximum)
|
||||
{
|
||||
packet.Properties.ReceiveMaximum = propertiesReader.ReadReceiveMaximum();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AssignedClientIdentifer)
|
||||
{
|
||||
packet.Properties.AssignedClientIdentifier = propertiesReader.ReadAssignedClientIdentifier();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.TopicAliasMaximum)
|
||||
{
|
||||
packet.Properties.TopicAliasMaximum = propertiesReader.ReadTopicAliasMaximum();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.MaximumPacketSize)
|
||||
{
|
||||
packet.Properties.MaximumPacketSize = propertiesReader.ReadMaximumPacketSize();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.WildcardSubscriptionAvailable)
|
||||
{
|
||||
packet.Properties.WildcardSubscriptionAvailable = propertiesReader.ReadWildcardSubscriptionAvailable();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.SubscriptionIdentifiersAvailable)
|
||||
{
|
||||
packet.Properties.SubscriptionIdentifiersAvailable = propertiesReader.ReadSubscriptionIdentifiersAvailable();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.SharedSubscriptionAvailable)
|
||||
{
|
||||
packet.Properties.SharedSubscriptionAvailable = propertiesReader.ReadSharedSubscriptionAvailable();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ServerKeepAlive)
|
||||
{
|
||||
packet.Properties.ServerKeepAlive = propertiesReader.ReadServerKeepAlive();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ResponseInformation)
|
||||
{
|
||||
packet.Properties.ResponseInformation = propertiesReader.ReadResponseInformation();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ServerReference)
|
||||
{
|
||||
packet.Properties.ServerReference = propertiesReader.ReadServerReference();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttConnAckPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeDisconnectPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttDisconnectPacket
|
||||
{
|
||||
ReasonCode = (MqttDisconnectReasonCode)body.ReadByte(),
|
||||
Properties = new MqttDisconnectPacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.SessionExpiryInterval)
|
||||
{
|
||||
packet.Properties.SessionExpiryInterval = propertiesReader.ReadSessionExpiryInterval();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ServerReference)
|
||||
{
|
||||
packet.Properties.ServerReference = propertiesReader.ReadServerReference();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttDisconnectPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeSubscribePacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttSubscribePacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttSubscribePacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.SubscriptionIdentifier)
|
||||
{
|
||||
packet.Properties.SubscriptionIdentifier = propertiesReader.ReadSubscriptionIdentifier();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttSubscribePacket));
|
||||
}
|
||||
}
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
var topic = body.ReadStringWithLengthPrefix();
|
||||
var options = body.ReadByte();
|
||||
|
||||
var qos = (MqttQualityOfServiceLevel)(options & 3);
|
||||
var noLocal = (options & (1 << 2)) > 0;
|
||||
var retainAsPublished = (options & (1 << 3)) > 0;
|
||||
var retainHandling = (MqttRetainHandling)((options >> 4) & 3);
|
||||
|
||||
packet.TopicFilters.Add(new TopicFilter
|
||||
{
|
||||
Topic = topic,
|
||||
QualityOfServiceLevel = qos,
|
||||
NoLocal = noLocal,
|
||||
RetainAsPublished = retainAsPublished,
|
||||
RetainHandling = retainHandling
|
||||
});
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeSubAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttSubAckPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttSubAckPacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttSubAckPacket));
|
||||
}
|
||||
}
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
var reasonCode = (MqttSubscribeReasonCode)body.ReadByte();
|
||||
packet.ReasonCodes.Add(reasonCode);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeUnsubscribePacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttUnsubscribePacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttUnsubscribePacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttUnsubscribePacket));
|
||||
}
|
||||
}
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
packet.TopicFilters.Add(body.ReadStringWithLengthPrefix());
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeUnsubAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttUnsubAckPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttUnsubAckPacketProperties()
|
||||
};
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttUnsubAckPacket));
|
||||
}
|
||||
}
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
var reasonCode = (MqttUnsubscribeReasonCode)body.ReadByte();
|
||||
packet.ReasonCodes.Add(reasonCode);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePingReqPacket()
|
||||
{
|
||||
return new MqttPingReqPacket();
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePingRespPacket()
|
||||
{
|
||||
return new MqttPingRespPacket();
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePublishPacket(byte header, MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var retain = (header & 1) > 0;
|
||||
var qos = (MqttQualityOfServiceLevel)(header >> 1 & 3);
|
||||
var dup = (header >> 3 & 1) > 0;
|
||||
|
||||
var packet = new MqttPublishPacket
|
||||
{
|
||||
Topic = body.ReadStringWithLengthPrefix(),
|
||||
Retain = retain,
|
||||
QualityOfServiceLevel = qos,
|
||||
Dup = dup,
|
||||
Properties = new MqttPublishPacketProperties()
|
||||
};
|
||||
|
||||
if (qos > 0)
|
||||
{
|
||||
packet.PacketIdentifier = body.ReadTwoByteInteger();
|
||||
}
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.PayloadFormatIndicator)
|
||||
{
|
||||
packet.Properties.PayloadFormatIndicator = propertiesReader.ReadPayloadFormatIndicator();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.MessageExpiryInterval)
|
||||
{
|
||||
packet.Properties.MessageExpiryInterval = propertiesReader.ReadMessageExpiryInterval();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.TopicAlias)
|
||||
{
|
||||
packet.Properties.TopicAlias = propertiesReader.ReadTopicAlias();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ResponseTopic)
|
||||
{
|
||||
packet.Properties.ResponseTopic = propertiesReader.ReadResponseTopic();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.CorrelationData)
|
||||
{
|
||||
packet.Properties.CorrelationData = propertiesReader.ReadCorrelationData();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.SubscriptionIdentifier)
|
||||
{
|
||||
packet.Properties.SubscriptionIdentifier = propertiesReader.ReadSubscriptionIdentifier();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ContentType)
|
||||
{
|
||||
packet.Properties.ContentType = propertiesReader.ReadContentType();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPublishPacket));
|
||||
}
|
||||
}
|
||||
|
||||
packet.Payload = body.ReadRemainingData().ToArray();
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttPubAckPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttPubAckPacketProperties()
|
||||
};
|
||||
|
||||
if (body.EndOfStream)
|
||||
{
|
||||
packet.ReasonCode = MqttPubAckReasonCode.Success;
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet.ReasonCode = (MqttPubAckReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubAckPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubRecPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttPubRecPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttPubRecPacketProperties()
|
||||
};
|
||||
|
||||
if (body.EndOfStream)
|
||||
{
|
||||
packet.ReasonCode = MqttPubRecReasonCode.Success;
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet.ReasonCode = (MqttPubRecReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubRecPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubRelPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttPubRelPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttPubRelPacketProperties()
|
||||
};
|
||||
|
||||
if (body.EndOfStream)
|
||||
{
|
||||
packet.ReasonCode = MqttPubRelReasonCode.Success;
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet.ReasonCode = (MqttPubRelReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubRelPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodePubCompPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttPubCompPacket
|
||||
{
|
||||
PacketIdentifier = body.ReadTwoByteInteger(),
|
||||
Properties = new MqttPubCompPacketProperties()
|
||||
};
|
||||
|
||||
if (body.EndOfStream)
|
||||
{
|
||||
packet.ReasonCode = MqttPubCompReasonCode.Success;
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet.ReasonCode = (MqttPubCompReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubCompPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static MqttBasePacket DecodeAuthPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttAuthPacket
|
||||
{
|
||||
Properties = new MqttAuthPacketProperties()
|
||||
};
|
||||
|
||||
if (body.EndOfStream)
|
||||
{
|
||||
packet.ReasonCode = MqttAuthenticateReasonCode.Success;
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet.ReasonCode = (MqttAuthenticateReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesReader = new MqttV500PropertiesReader(body);
|
||||
while (propertiesReader.MoveNext())
|
||||
{
|
||||
if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationMethod)
|
||||
{
|
||||
packet.Properties.AuthenticationMethod = propertiesReader.ReadAuthenticationMethod();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.AuthenticationData)
|
||||
{
|
||||
packet.Properties.AuthenticationData = propertiesReader.ReadAuthenticationData();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = propertiesReader.ReadReasonString();
|
||||
}
|
||||
else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||
{
|
||||
propertiesReader.FillUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttAuthPacket));
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
||||
private static void ThrowIfBodyIsEmpty(MqttPacketBodyReader body)
|
||||
{
|
||||
if (body == null || body.Length == 0)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Data from the body is required but not present.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PacketEncoder
|
||||
{
|
||||
private readonly MqttPacketWriter _packetWriter = new MqttPacketWriter();
|
||||
|
||||
public ArraySegment<byte> Encode(MqttBasePacket packet)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
|
||||
// Leave enough head space for max header size (fixed + 4 variable remaining length = 5 bytes)
|
||||
_packetWriter.Reset();
|
||||
_packetWriter.Seek(5);
|
||||
|
||||
var fixedHeader = EncodePacket(packet, _packetWriter);
|
||||
var remainingLength = (uint)(_packetWriter.Length - 5);
|
||||
|
||||
var remainingLengthBuffer = MqttPacketWriter.EncodeVariableByteInteger(remainingLength);
|
||||
|
||||
var headerSize = 1 + remainingLengthBuffer.Count;
|
||||
var headerOffset = 5 - headerSize;
|
||||
|
||||
// Position cursor on correct offset on beginning of array (has leading 0x0)
|
||||
_packetWriter.Seek(headerOffset);
|
||||
_packetWriter.Write(fixedHeader);
|
||||
_packetWriter.Write(remainingLengthBuffer.Array, remainingLengthBuffer.Offset, remainingLengthBuffer.Count);
|
||||
|
||||
var buffer = _packetWriter.GetBuffer();
|
||||
return new ArraySegment<byte>(buffer, headerOffset, _packetWriter.Length - headerOffset);
|
||||
}
|
||||
|
||||
public void FreeBuffer()
|
||||
{
|
||||
_packetWriter.FreeBuffer();
|
||||
}
|
||||
|
||||
private static byte EncodePacket(MqttBasePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
switch (packet)
|
||||
{
|
||||
case MqttConnectPacket connectPacket: return EncodeConnectPacket(connectPacket, packetWriter);
|
||||
case MqttConnAckPacket connAckPacket: return EncodeConnAckPacket(connAckPacket, packetWriter);
|
||||
case MqttDisconnectPacket disconnectPacket: return EncodeDisconnectPacket(disconnectPacket, packetWriter);
|
||||
case MqttPingReqPacket _: return EncodePingReqPacket();
|
||||
case MqttPingRespPacket _: return EncodePingRespPacket();
|
||||
case MqttPublishPacket publishPacket: return EncodePublishPacket(publishPacket, packetWriter);
|
||||
case MqttPubAckPacket pubAckPacket: return EncodePubAckPacket(pubAckPacket, packetWriter);
|
||||
case MqttPubRecPacket pubRecPacket: return EncodePubRecPacket(pubRecPacket, packetWriter);
|
||||
case MqttPubRelPacket pubRelPacket: return EncodePubRelPacket(pubRelPacket, packetWriter);
|
||||
case MqttPubCompPacket pubCompPacket: return EncodePubCompPacket(pubCompPacket, packetWriter);
|
||||
case MqttSubscribePacket subscribePacket: return EncodeSubscribePacket(subscribePacket, packetWriter);
|
||||
case MqttSubAckPacket subAckPacket: return EncodeSubAckPacket(subAckPacket, packetWriter);
|
||||
case MqttUnsubscribePacket unsubscribePacket: return EncodeUnsubscribePacket(unsubscribePacket, packetWriter);
|
||||
case MqttUnsubAckPacket unsubAckPacket: return EncodeUnsubAckPacket(unsubAckPacket, packetWriter);
|
||||
case MqttAuthPacket authPacket: return EncodeAuthPacket(authPacket, packetWriter);
|
||||
|
||||
default: throw new MqttProtocolViolationException("Packet type invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
private static byte EncodeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession)
|
||||
{
|
||||
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
|
||||
}
|
||||
|
||||
packetWriter.WriteWithLengthPrefix("MQTT");
|
||||
packetWriter.Write(5); // [3.1.2.2 Protocol Version]
|
||||
|
||||
byte connectFlags = 0x0;
|
||||
if (packet.CleanSession)
|
||||
{
|
||||
connectFlags |= 0x2;
|
||||
}
|
||||
|
||||
if (packet.WillMessage != null)
|
||||
{
|
||||
connectFlags |= 0x4;
|
||||
connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);
|
||||
|
||||
if (packet.WillMessage.Retain)
|
||||
{
|
||||
connectFlags |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.Password != null && packet.Username == null)
|
||||
{
|
||||
throw new MqttProtocolViolationException("If the User Name Flag is set to 0, the Password Flag MUST be set to 0 [MQTT-3.1.2-22].");
|
||||
}
|
||||
|
||||
if (packet.Password != null)
|
||||
{
|
||||
connectFlags |= 0x40;
|
||||
}
|
||||
|
||||
if (packet.Username != null)
|
||||
{
|
||||
connectFlags |= 0x80;
|
||||
}
|
||||
|
||||
packetWriter.Write(connectFlags);
|
||||
packetWriter.Write(packet.KeepAlivePeriod);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteWillDelayInterval(packet.Properties.WillDelayInterval);
|
||||
propertiesWriter.WriteSessionExpiryInterval(packet.Properties.SessionExpiryInterval);
|
||||
propertiesWriter.WriteAuthenticationMethod(packet.Properties.AuthenticationMethod);
|
||||
propertiesWriter.WriteAuthenticationData(packet.Properties.AuthenticationData);
|
||||
propertiesWriter.WriteRequestProblemInformation(packet.Properties.RequestProblemInformation);
|
||||
propertiesWriter.WriteRequestResponseInformation(packet.Properties.RequestResponseInformation);
|
||||
propertiesWriter.WriteReceiveMaximum(packet.Properties.ReceiveMaximum);
|
||||
propertiesWriter.WriteTopicAlias(packet.Properties.TopicAliasMaximum);
|
||||
propertiesWriter.WriteMaximumPacketSize(packet.Properties.MaximumPacketSize);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
packetWriter.WriteWithLengthPrefix(packet.ClientId);
|
||||
|
||||
if (packet.WillMessage != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
|
||||
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
|
||||
}
|
||||
|
||||
if (packet.Username != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.Username);
|
||||
}
|
||||
|
||||
if (packet.Password != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.Password);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect);
|
||||
}
|
||||
|
||||
private static byte EncodeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
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)
|
||||
{
|
||||
connectAcknowledgeFlags |= 0x1;
|
||||
}
|
||||
|
||||
packetWriter.Write(connectAcknowledgeFlags);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteSessionExpiryInterval(packet.Properties.SessionExpiryInterval);
|
||||
propertiesWriter.WriteAuthenticationMethod(packet.Properties.AuthenticationMethod);
|
||||
propertiesWriter.WriteAuthenticationData(packet.Properties.AuthenticationData);
|
||||
propertiesWriter.WriteRetainAvailable(packet.Properties.RetainAvailable);
|
||||
propertiesWriter.WriteReceiveMaximum(packet.Properties.ReceiveMaximum);
|
||||
propertiesWriter.WriteAssignedClientIdentifier(packet.Properties.AssignedClientIdentifier);
|
||||
propertiesWriter.WriteTopicAliasMaximum(packet.Properties.TopicAliasMaximum);
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteMaximumPacketSize(packet.Properties.MaximumPacketSize);
|
||||
propertiesWriter.WriteWildcardSubscriptionAvailable(packet.Properties.WildcardSubscriptionAvailable);
|
||||
propertiesWriter.WriteSubscriptionIdentifiersAvailable(packet.Properties.SubscriptionIdentifiersAvailable);
|
||||
propertiesWriter.WriteSharedSubscriptionAvailable(packet.Properties.SharedSubscriptionAvailable);
|
||||
propertiesWriter.WriteServerKeepAlive(packet.Properties.ServerKeepAlive);
|
||||
propertiesWriter.WriteResponseInformation(packet.Properties.ResponseInformation);
|
||||
propertiesWriter.WriteServerReference(packet.Properties.ServerReference);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||
}
|
||||
|
||||
private static byte EncodePublishPacket(MqttPublishPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
|
||||
}
|
||||
|
||||
packetWriter.WriteWithLengthPrefix(packet.Topic);
|
||||
|
||||
if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Publish packet has no packet identifier.");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packet.PacketIdentifier > 0)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Packet identifier must be 0 if QoS == 0 [MQTT-2.3.1-5].");
|
||||
}
|
||||
}
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WritePayloadFormatIndicator(packet.Properties.PayloadFormatIndicator);
|
||||
propertiesWriter.WriteMessageExpiryInterval(packet.Properties.MessageExpiryInterval);
|
||||
propertiesWriter.WriteTopicAlias(packet.Properties.TopicAlias);
|
||||
propertiesWriter.WriteResponseTopic(packet.Properties.ResponseTopic);
|
||||
propertiesWriter.WriteCorrelationData(packet.Properties.CorrelationData);
|
||||
propertiesWriter.WriteSubscriptionIdentifier(packet.Properties.SubscriptionIdentifier);
|
||||
propertiesWriter.WriteContentType(packet.Properties.ContentType);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
if (packet.Payload?.Length > 0)
|
||||
{
|
||||
packetWriter.Write(packet.Payload, 0, packet.Payload.Length);
|
||||
}
|
||||
|
||||
byte fixedHeader = 0;
|
||||
|
||||
if (packet.Retain)
|
||||
{
|
||||
fixedHeader |= 0x01;
|
||||
}
|
||||
|
||||
fixedHeader |= (byte)((byte)packet.QualityOfServiceLevel << 1);
|
||||
|
||||
if (packet.Dup)
|
||||
{
|
||||
fixedHeader |= 0x08;
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
|
||||
}
|
||||
|
||||
private static byte EncodePubAckPacket(MqttPubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("PubAck packet has no packet identifier.");
|
||||
}
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("PubAck packet must contain a connect reason.");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubAckReasonCode.Success)
|
||||
{
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
|
||||
}
|
||||
|
||||
private static byte EncodePubRecPacket(MqttPubRecPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
ThrowReasonCodeNotSetException();
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubRecReasonCode.Success)
|
||||
{
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRec);
|
||||
}
|
||||
|
||||
private static byte EncodePubRelPacket(MqttPubRelPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
ThrowReasonCodeNotSetException();
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubRelReasonCode.Success)
|
||||
{
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02);
|
||||
}
|
||||
|
||||
private static byte EncodePubCompPacket(MqttPubCompPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
ThrowReasonCodeNotSetException();
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubCompReasonCode.Success)
|
||||
{
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp);
|
||||
}
|
||||
|
||||
private static byte EncodeSubscribePacket(MqttSubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
|
||||
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteSubscriptionIdentifier(packet.Properties.SubscriptionIdentifier);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
if (packet.TopicFilters?.Count > 0)
|
||||
{
|
||||
foreach (var topicFilter in packet.TopicFilters)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(topicFilter.Topic);
|
||||
|
||||
var options = (byte)topicFilter.QualityOfServiceLevel;
|
||||
|
||||
if (topicFilter.NoLocal == true)
|
||||
{
|
||||
options |= 1 << 2;
|
||||
}
|
||||
|
||||
if (topicFilter.RetainAsPublished == true)
|
||||
{
|
||||
options |= 1 << 3;
|
||||
}
|
||||
|
||||
if (topicFilter.RetainHandling.HasValue)
|
||||
{
|
||||
options |= (byte)((byte)topicFilter.RetainHandling.Value << 4);
|
||||
}
|
||||
|
||||
packetWriter.Write(options);
|
||||
}
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02);
|
||||
}
|
||||
|
||||
private static byte EncodeSubAckPacket(MqttSubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
if (packet.ReasonCodes == null || !packet.ReasonCodes.Any())
|
||||
{
|
||||
throw new MqttProtocolViolationException("At least one reason code must be set[MQTT - 3.8.3 - 3].");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
foreach (var reasonCode in packet.ReasonCodes)
|
||||
{
|
||||
packetWriter.Write((byte)reasonCode);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck);
|
||||
}
|
||||
|
||||
private static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
|
||||
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
foreach (var topicFilter in packet.TopicFilters)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(topicFilter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
|
||||
}
|
||||
|
||||
private static byte EncodeUnsubAckPacket(MqttUnsubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
ThrowIfPacketIdentifierIsInvalid(packet);
|
||||
|
||||
if (packet.ReasonCodes == null || !packet.ReasonCodes.Any())
|
||||
{
|
||||
throw new MqttProtocolViolationException("At least one reason code must be set[MQTT - 3.8.3 - 3].");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
foreach (var reasonCode in packet.ReasonCodes)
|
||||
{
|
||||
packetWriter.Write((byte)reasonCode);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck);
|
||||
}
|
||||
|
||||
private static byte EncodeDisconnectPacket(MqttDisconnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
ThrowReasonCodeNotSetException();
|
||||
}
|
||||
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteServerReference(packet.Properties.ServerReference);
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteSessionExpiryInterval(packet.Properties.SessionExpiryInterval);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Disconnect);
|
||||
}
|
||||
|
||||
private static byte EncodePingReqPacket()
|
||||
{
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PingReq);
|
||||
}
|
||||
|
||||
private static byte EncodePingRespPacket()
|
||||
{
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PingResp);
|
||||
}
|
||||
|
||||
private static byte EncodeAuthPacket(MqttAuthPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
packetWriter.Write((byte)packet.ReasonCode);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteAuthenticationMethod(packet.Properties.AuthenticationMethod);
|
||||
propertiesWriter.WriteAuthenticationData(packet.Properties.AuthenticationData);
|
||||
propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
}
|
||||
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Auth);
|
||||
}
|
||||
|
||||
private static void ThrowReasonCodeNotSetException()
|
||||
{
|
||||
throw new MqttProtocolViolationException("The ReasonCode must be set for MQTT version 5.");
|
||||
}
|
||||
|
||||
private static void ThrowIfPacketIdentifierIsInvalid(IMqttPacketWithIdentifier packet)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException($"Packet identifier is not set for {packet.GetType().Name}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PacketFormatter : IMqttPacketFormatter
|
||||
{
|
||||
private readonly MqttV500PacketEncoder _encoder = new MqttV500PacketEncoder();
|
||||
private readonly MqttV500PacketDecoder _decoder = new MqttV500PacketDecoder();
|
||||
|
||||
public IMqttDataConverter DataConverter { get; } = new MqttV500DataConverter();
|
||||
|
||||
public ArraySegment<byte> Encode(MqttBasePacket mqttPacket)
|
||||
{
|
||||
if (mqttPacket == null) throw new ArgumentNullException(nameof(mqttPacket));
|
||||
|
||||
return _encoder.Encode(mqttPacket);
|
||||
}
|
||||
|
||||
public MqttBasePacket Decode(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
if (receivedMqttPacket == null) throw new ArgumentNullException(nameof(receivedMqttPacket));
|
||||
|
||||
return _decoder.Decode(receivedMqttPacket);
|
||||
}
|
||||
|
||||
public void FreeBuffer()
|
||||
{
|
||||
_encoder.FreeBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PropertiesReader
|
||||
{
|
||||
private readonly MqttPacketBodyReader _body;
|
||||
private readonly uint _length;
|
||||
private readonly ulong _targetOffset;
|
||||
|
||||
public MqttV500PropertiesReader(MqttPacketBodyReader body)
|
||||
{
|
||||
_body = body ?? throw new ArgumentNullException(nameof(body));
|
||||
|
||||
if (!body.EndOfStream)
|
||||
{
|
||||
_length = body.ReadVariableLengthInteger();
|
||||
}
|
||||
|
||||
_targetOffset = body.Offset + _length;
|
||||
}
|
||||
|
||||
public MqttPropertyId CurrentPropertyId { get; private set; }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_body.Offset >= _targetOffset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentPropertyId = (MqttPropertyId)_body.ReadByte();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void FillUserProperties(List<MqttUserProperty> userProperties)
|
||||
{
|
||||
if (userProperties == null) throw new ArgumentNullException(nameof(userProperties));
|
||||
|
||||
var userPropertiesLength = _body.ReadVariableLengthInteger();
|
||||
if (userPropertiesLength == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPosition = _body.Offset + userPropertiesLength;
|
||||
while (_body.Offset < targetPosition)
|
||||
{
|
||||
var name = _body.ReadStringWithLengthPrefix();
|
||||
var value = _body.ReadStringWithLengthPrefix();
|
||||
|
||||
userProperties.Add(new MqttUserProperty(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
public string ReadReasonString()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public string ReadAuthenticationMethod()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public byte[] ReadAuthenticationData()
|
||||
{
|
||||
return _body.ReadWithLengthPrefix().ToArray();
|
||||
}
|
||||
|
||||
public bool? ReadRetainAvailable()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public uint? ReadSessionExpiryInterval()
|
||||
{
|
||||
return _body.ReadFourByteInteger();
|
||||
}
|
||||
|
||||
public ushort? ReadReceiveMaximum()
|
||||
{
|
||||
return _body.ReadTwoByteInteger();
|
||||
}
|
||||
|
||||
public string ReadAssignedClientIdentifier()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public string ReadServerReference()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public ushort? ReadTopicAliasMaximum()
|
||||
{
|
||||
return _body.ReadTwoByteInteger();
|
||||
}
|
||||
|
||||
public uint? ReadMaximumPacketSize()
|
||||
{
|
||||
return _body.ReadFourByteInteger();
|
||||
}
|
||||
|
||||
public ushort? ReadServerKeepAlive()
|
||||
{
|
||||
return _body.ReadTwoByteInteger();
|
||||
}
|
||||
|
||||
public string ReadResponseInformation()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public bool? ReadSharedSubscriptionAvailable()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public bool? ReadSubscriptionIdentifiersAvailable()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public bool? ReadWildcardSubscriptionAvailable()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public uint? ReadSubscriptionIdentifier()
|
||||
{
|
||||
return _body.ReadVariableLengthInteger();
|
||||
}
|
||||
|
||||
public MqttPayloadFormatIndicator? ReadPayloadFormatIndicator()
|
||||
{
|
||||
return (MqttPayloadFormatIndicator)_body.ReadByte();
|
||||
}
|
||||
|
||||
public uint? ReadMessageExpiryInterval()
|
||||
{
|
||||
return _body.ReadFourByteInteger();
|
||||
}
|
||||
|
||||
public ushort? ReadTopicAlias()
|
||||
{
|
||||
return _body.ReadTwoByteInteger();
|
||||
}
|
||||
|
||||
public string ReadResponseTopic()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public byte[] ReadCorrelationData()
|
||||
{
|
||||
return _body.ReadWithLengthPrefix().ToArray();
|
||||
}
|
||||
|
||||
public string ReadContentType()
|
||||
{
|
||||
return _body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
|
||||
public uint? ReadWillDelayInterval()
|
||||
{
|
||||
return _body.ReadFourByteInteger();
|
||||
}
|
||||
|
||||
public bool? RequestResponseInformation()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public bool? RequestProblemInformation()
|
||||
{
|
||||
return _body.ReadBoolean();
|
||||
}
|
||||
|
||||
public void ThrowInvalidPropertyIdException(Type type)
|
||||
{
|
||||
throw new MqttProtocolViolationException($"Property ID '{CurrentPropertyId}' is not supported for package type '{type.Name}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public class MqttV500PropertiesWriter
|
||||
{
|
||||
private readonly MqttPacketWriter _packetWriter = new MqttPacketWriter();
|
||||
|
||||
public void WriteUserProperties(List<MqttUserProperty> userProperties)
|
||||
{
|
||||
if (userProperties == null || userProperties.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var propertyWriter = new MqttPacketWriter();
|
||||
foreach (var property in userProperties)
|
||||
{
|
||||
propertyWriter.WriteWithLengthPrefix(property.Name);
|
||||
propertyWriter.WriteWithLengthPrefix(property.Value);
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)MqttPropertyId.UserProperty);
|
||||
_packetWriter.WriteVariableLengthInteger((uint)propertyWriter.Length);
|
||||
_packetWriter.Write(propertyWriter);
|
||||
}
|
||||
|
||||
public void WriteCorrelationData(byte[] value)
|
||||
{
|
||||
Write(MqttPropertyId.CorrelationData, value);
|
||||
}
|
||||
|
||||
public void WriteAuthenticationData(byte[] value)
|
||||
{
|
||||
Write(MqttPropertyId.AuthenticationData, value);
|
||||
}
|
||||
|
||||
public void WriteReasonString(string value)
|
||||
{
|
||||
Write(MqttPropertyId.ReasonString, value);
|
||||
}
|
||||
|
||||
public void WriteResponseTopic(string value)
|
||||
{
|
||||
Write(MqttPropertyId.ResponseTopic, value);
|
||||
}
|
||||
|
||||
public void WriteContentType(string value)
|
||||
{
|
||||
Write(MqttPropertyId.ContentType, value);
|
||||
}
|
||||
|
||||
public void WriteServerReference(string value)
|
||||
{
|
||||
Write(MqttPropertyId.ServerReference, value);
|
||||
}
|
||||
|
||||
public void WriteAuthenticationMethod(string value)
|
||||
{
|
||||
Write(MqttPropertyId.AuthenticationMethod, value);
|
||||
}
|
||||
|
||||
public void WriteToPacket(MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
packetWriter.WriteVariableLengthInteger((uint)_packetWriter.Length);
|
||||
packetWriter.Write(_packetWriter);
|
||||
}
|
||||
|
||||
public void WriteSessionExpiryInterval(uint? value)
|
||||
{
|
||||
WriteAsFourByteInteger(MqttPropertyId.SessionExpiryInterval, value);
|
||||
}
|
||||
|
||||
public void WriteSubscriptionIdentifier(uint? value)
|
||||
{
|
||||
WriteAsVariableLengthInteger(MqttPropertyId.SubscriptionIdentifier, value);
|
||||
}
|
||||
|
||||
public void WriteTopicAlias(ushort? value)
|
||||
{
|
||||
Write(MqttPropertyId.TopicAlias, value);
|
||||
}
|
||||
|
||||
public void WriteMessageExpiryInterval(uint? value)
|
||||
{
|
||||
WriteAsFourByteInteger(MqttPropertyId.MessageExpiryInterval, value);
|
||||
}
|
||||
|
||||
public void WritePayloadFormatIndicator(MqttPayloadFormatIndicator? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Write(MqttPropertyId.PayloadFormatIndicator, (byte)value.Value);
|
||||
}
|
||||
|
||||
public void WriteWillDelayInterval(uint? value)
|
||||
{
|
||||
WriteAsFourByteInteger(MqttPropertyId.WillDelayInterval, value);
|
||||
}
|
||||
|
||||
public void WriteRequestProblemInformation(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.RequestProblemInformation, value);
|
||||
}
|
||||
|
||||
public void WriteRequestResponseInformation(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.RequestResponseInformation, value);
|
||||
}
|
||||
|
||||
public void WriteReceiveMaximum(ushort? value)
|
||||
{
|
||||
Write(MqttPropertyId.RequestResponseInformation, value);
|
||||
}
|
||||
|
||||
public void WriteMaximumPacketSize(uint? value)
|
||||
{
|
||||
WriteAsFourByteInteger(MqttPropertyId.MaximumPacketSize, value);
|
||||
}
|
||||
|
||||
public void WriteRetainAvailable(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.RetainAvailable, value);
|
||||
}
|
||||
|
||||
public void WriteAssignedClientIdentifier(string value)
|
||||
{
|
||||
Write(MqttPropertyId.AssignedClientIdentifer, value);
|
||||
}
|
||||
|
||||
public void WriteTopicAliasMaximum(ushort? value)
|
||||
{
|
||||
Write(MqttPropertyId.TopicAliasMaximum, value);
|
||||
}
|
||||
|
||||
public void WriteWildcardSubscriptionAvailable(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.WildcardSubscriptionAvailable, value);
|
||||
}
|
||||
|
||||
public void WriteSubscriptionIdentifiersAvailable(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.SubscriptionIdentifiersAvailable, value);
|
||||
}
|
||||
|
||||
public void WriteSharedSubscriptionAvailable(bool? value)
|
||||
{
|
||||
Write(MqttPropertyId.SharedSubscriptionAvailable, value);
|
||||
}
|
||||
|
||||
public void WriteServerKeepAlive(ushort? value)
|
||||
{
|
||||
Write(MqttPropertyId.ServerKeepAlive, value);
|
||||
}
|
||||
|
||||
public void WriteResponseInformation(string value)
|
||||
{
|
||||
Write(MqttPropertyId.ResponseInformation, value);
|
||||
}
|
||||
|
||||
private void Write(MqttPropertyId id, bool? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write(value.Value ? (byte)0x1 : (byte)0x0);
|
||||
}
|
||||
|
||||
private void Write(MqttPropertyId id, ushort? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write(value.Value);
|
||||
}
|
||||
|
||||
private void WriteAsVariableLengthInteger(MqttPropertyId id, uint? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteVariableLengthInteger(value.Value);
|
||||
}
|
||||
|
||||
private void WriteAsFourByteInteger(MqttPropertyId id, uint? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write((byte)(value.Value >> 24));
|
||||
_packetWriter.Write((byte)(value.Value >> 16));
|
||||
_packetWriter.Write((byte)(value.Value >> 8));
|
||||
_packetWriter.Write((byte)value.Value);
|
||||
}
|
||||
|
||||
private void Write(MqttPropertyId id, string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteWithLengthPrefix(value);
|
||||
}
|
||||
|
||||
private void Write(MqttPropertyId id, byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteWithLengthPrefix(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V500
|
||||
{
|
||||
public class MqttV500PacketDecoder
|
||||
{
|
||||
public MqttBasePacket DecodeConnAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
if (body == null) throw new ArgumentNullException(nameof(body));
|
||||
|
||||
ThrowIfBodyIsEmpty(body);
|
||||
|
||||
var packet = new MqttConnAckPacket();
|
||||
|
||||
var acknowledgeFlags = body.ReadByte();
|
||||
|
||||
packet.IsSessionPresent = (acknowledgeFlags & 0x1) > 0;
|
||||
packet.ConnectReturnCode = (MqttConnectReturnCode)body.ReadByte();
|
||||
packet.ReasonCode = (MqttConnectReasonCode)body.ReadByte();
|
||||
|
||||
var propertiesLength = body.ReadVariableLengthInteger();
|
||||
if (propertiesLength > 0)
|
||||
{
|
||||
packet.Properties = new MqttConnAckPacketProperties();
|
||||
|
||||
while (!body.EndOfStream)
|
||||
{
|
||||
var propertyID = (MqttPropertyID)body.ReadByte();
|
||||
|
||||
if (propertyID == MqttPropertyID.SessionExpiryInterval)
|
||||
{
|
||||
packet.Properties.SessionExpiryInterval = body.ReadFourByteInteger();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.AuthenticationMethod)
|
||||
{
|
||||
packet.Properties.AuthenticationMethod = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.AuthenticationData)
|
||||
{
|
||||
packet.Properties.AuthenticationData = body.ReadWithLengthPrefix().ToArray();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.RetainAvailable)
|
||||
{
|
||||
packet.Properties.RetainAvailable = body.ReadBoolean();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.ReceiveMaximum)
|
||||
{
|
||||
packet.Properties.ReceiveMaximum = body.ReadTwoByteInteger();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.AssignedClientIdentifer)
|
||||
{
|
||||
packet.Properties.AssignedClientIdentifier = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.TopicAliasMaximum)
|
||||
{
|
||||
packet.Properties.TopicAliasMaximum = body.ReadTwoByteInteger();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.ReasonString)
|
||||
{
|
||||
packet.Properties.ReasonString = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.MaximumPacketSize)
|
||||
{
|
||||
packet.Properties.MaximumPacketSize = body.ReadFourByteInteger();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.WildcardSubscriptionAvailable)
|
||||
{
|
||||
packet.Properties.WildcardSubscriptionAvailable = body.ReadBoolean();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.SubscriptionIdentifierAvailable)
|
||||
{
|
||||
packet.Properties.SubscriptionIdentifiersAvailable = body.ReadBoolean();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.SharedSubscriptionAvailable)
|
||||
{
|
||||
packet.Properties.SharedSubscriptionAvailable = body.ReadBoolean();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.ServerKeepAlive)
|
||||
{
|
||||
packet.Properties.ServerKeepAlive = body.ReadTwoByteInteger();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.ResponseInformation)
|
||||
{
|
||||
packet.Properties.ResponseInformation = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.ServerReference)
|
||||
{
|
||||
packet.Properties.ServerReference = body.ReadStringWithLengthPrefix();
|
||||
}
|
||||
else if (propertyID == MqttPropertyID.UserProperty)
|
||||
{
|
||||
packet.Properties.UserProperties = ReadUserProperties(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
||||
private static void ThrowIfBodyIsEmpty(MqttPacketBodyReader body)
|
||||
{
|
||||
if (body == null || body.Length == 0)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Data from the body is required but not present.");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<MqttUserProperty> ReadUserProperties(MqttPacketBodyReader reader)
|
||||
{
|
||||
var userPropertiesLength = reader.ReadVariableLengthInteger();
|
||||
if (userPropertiesLength == 0)
|
||||
{
|
||||
return new List<MqttUserProperty>();
|
||||
}
|
||||
|
||||
var userProperties = new List<MqttUserProperty>();
|
||||
var targetPosition = reader.Offset + userPropertiesLength;
|
||||
while (reader.Offset < targetPosition)
|
||||
{
|
||||
var name = reader.ReadStringWithLengthPrefix();
|
||||
var value = reader.ReadStringWithLengthPrefix();
|
||||
|
||||
userProperties.Add(new MqttUserProperty(name, value));
|
||||
}
|
||||
|
||||
return userProperties;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
using System;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V500
|
||||
{
|
||||
public class MqttV500PacketEncoder
|
||||
{
|
||||
public byte EncodeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession)
|
||||
{
|
||||
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
|
||||
}
|
||||
|
||||
packetWriter.WriteWithLengthPrefix("MQTT");
|
||||
packetWriter.Write(5); // [3.1.2.2 Protocol Version]
|
||||
|
||||
byte connectFlags = 0x0;
|
||||
if (packet.CleanSession)
|
||||
{
|
||||
connectFlags |= 0x2;
|
||||
}
|
||||
|
||||
if (packet.WillMessage != null)
|
||||
{
|
||||
connectFlags |= 0x4;
|
||||
connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);
|
||||
|
||||
if (packet.WillMessage.Retain)
|
||||
{
|
||||
connectFlags |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.Password != null && packet.Username == null)
|
||||
{
|
||||
throw new MqttProtocolViolationException("If the User Name Flag is set to 0, the Password Flag MUST be set to 0 [MQTT-3.1.2-22].");
|
||||
}
|
||||
|
||||
if (packet.Password != null)
|
||||
{
|
||||
connectFlags |= 0x40;
|
||||
}
|
||||
|
||||
if (packet.Username != null)
|
||||
{
|
||||
connectFlags |= 0x80;
|
||||
}
|
||||
|
||||
packetWriter.Write(connectFlags);
|
||||
packetWriter.Write(packet.KeepAlivePeriod);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.WillDelayInterval, packet.Properties.WillDelayInterval);
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.SessionExpiryInterval, packet.Properties.SessionExpiryInterval);
|
||||
propertiesWriter.Write(MqttPropertyID.AuthenticationMethod, packet.Properties.AuthenticationMethod);
|
||||
propertiesWriter.Write(MqttPropertyID.AuthenticationData, packet.Properties.AuthenticationData);
|
||||
propertiesWriter.Write(MqttPropertyID.RequestProblemInformation, packet.Properties.RequestProblemInformation);
|
||||
propertiesWriter.Write(MqttPropertyID.RequestResponseInformation, packet.Properties.RequestResponseInformation);
|
||||
propertiesWriter.Write(MqttPropertyID.ReceiveMaximum, packet.Properties.ReceiveMaximum);
|
||||
propertiesWriter.Write(MqttPropertyID.TopicAlias, packet.Properties.TopicAliasMaximum);
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.MaximumPacketSize, packet.Properties.MaximumPacketSize);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
packetWriter.WriteWithLengthPrefix(packet.ClientId);
|
||||
|
||||
if (packet.WillMessage != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
|
||||
packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
|
||||
}
|
||||
|
||||
if (packet.Username != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.Username);
|
||||
}
|
||||
|
||||
if (packet.Password != null)
|
||||
{
|
||||
packetWriter.WriteWithLengthPrefix(packet.Password);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect);
|
||||
}
|
||||
|
||||
public byte EncodeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("The ReasonCode must be set for MQTT version 5.");
|
||||
}
|
||||
|
||||
byte connectAcknowledgeFlags = 0x0;
|
||||
if (packet.IsSessionPresent)
|
||||
{
|
||||
connectAcknowledgeFlags |= 0x1;
|
||||
}
|
||||
|
||||
packetWriter.Write(connectAcknowledgeFlags);
|
||||
packetWriter.Write((byte)packet.ConnectReturnCode);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
if (packet.Properties != null)
|
||||
{
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.SessionExpiryInterval, packet.Properties.SessionExpiryInterval);
|
||||
propertiesWriter.Write(MqttPropertyID.AuthenticationMethod, packet.Properties.AuthenticationMethod);
|
||||
propertiesWriter.Write(MqttPropertyID.AuthenticationData, packet.Properties.AuthenticationData);
|
||||
propertiesWriter.Write(MqttPropertyID.RetainAvailable, packet.Properties.RetainAvailable);
|
||||
propertiesWriter.Write(MqttPropertyID.ReceiveMaximum, packet.Properties.ReceiveMaximum);
|
||||
propertiesWriter.Write(MqttPropertyID.AssignedClientIdentifer, packet.Properties.AssignedClientIdentifier);
|
||||
propertiesWriter.Write(MqttPropertyID.TopicAliasMaximum, packet.Properties.TopicAliasMaximum);
|
||||
propertiesWriter.Write(MqttPropertyID.ReasonString, packet.Properties.ReasonString);
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.MaximumPacketSize, packet.Properties.MaximumPacketSize);
|
||||
propertiesWriter.Write(MqttPropertyID.WildcardSubscriptionAvailable, packet.Properties.WildcardSubscriptionAvailable);
|
||||
propertiesWriter.Write(MqttPropertyID.SubscriptionIdentifierAvailable, packet.Properties.SubscriptionIdentifiersAvailable);
|
||||
propertiesWriter.Write(MqttPropertyID.SharedSubscriptionAvailable, packet.Properties.SharedSubscriptionAvailable);
|
||||
propertiesWriter.Write(MqttPropertyID.ServerKeepAlive, packet.Properties.ServerKeepAlive);
|
||||
propertiesWriter.Write(MqttPropertyID.ResponseInformation, packet.Properties.ResponseInformation);
|
||||
propertiesWriter.Write(MqttPropertyID.ServerReference, packet.Properties.ServerReference);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||
}
|
||||
|
||||
public byte EncodePublishPacket(MqttPublishPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
|
||||
}
|
||||
|
||||
packetWriter.WriteWithLengthPrefix(packet.Topic);
|
||||
|
||||
if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Publish packet has no packet identifier.");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packet.PacketIdentifier > 0)
|
||||
{
|
||||
throw new MqttProtocolViolationException("Packet identifier must be empty if QoS == 0 [MQTT-2.3.1-5].");
|
||||
}
|
||||
}
|
||||
|
||||
var propertiesWriter = new MqttV500PropertiesWriter();
|
||||
propertiesWriter.Write(MqttPropertyID.PayloadFormatIndicator, packet.Properties.PayloadFormatIndicator);
|
||||
propertiesWriter.WriteAsFourByteInteger(MqttPropertyID.MessageExpiryInterval, packet.Properties.MessageExpiryInterval);
|
||||
propertiesWriter.Write(MqttPropertyID.TopicAlias, packet.Properties.TopicAlias);
|
||||
propertiesWriter.Write(MqttPropertyID.ResponseTopic, packet.Properties.ResponseTopic);
|
||||
propertiesWriter.Write(MqttPropertyID.CorrelationData, packet.Properties.CorrelationData);
|
||||
propertiesWriter.WriteAsVariableLengthInteger(MqttPropertyID.SubscriptionIdentifier, packet.Properties.SubscriptionIdentifier);
|
||||
propertiesWriter.Write(MqttPropertyID.ContentType, packet.Properties.ContentType);
|
||||
propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
|
||||
propertiesWriter.WriteToPacket(packetWriter);
|
||||
|
||||
if (packet.Payload?.Length > 0)
|
||||
{
|
||||
packetWriter.Write(packet.Payload, 0, packet.Payload.Length);
|
||||
}
|
||||
|
||||
byte fixedHeader = 0;
|
||||
|
||||
if (packet.Retain)
|
||||
{
|
||||
fixedHeader |= 0x01;
|
||||
}
|
||||
|
||||
fixedHeader |= (byte)((byte)packet.QualityOfServiceLevel << 1);
|
||||
|
||||
if (packet.Dup)
|
||||
{
|
||||
fixedHeader |= 0x08;
|
||||
}
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
|
||||
}
|
||||
|
||||
public byte EncodePubAckPacket(MqttPubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
if (!packet.PacketIdentifier.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("PubAck packet has no packet identifier.");
|
||||
}
|
||||
|
||||
if (!packet.ReasonCode.HasValue)
|
||||
{
|
||||
throw new MqttProtocolViolationException("PubAck packet must contain a connect reason.");
|
||||
}
|
||||
|
||||
packetWriter.Write(packet.PacketIdentifier.Value);
|
||||
packetWriter.Write((byte)packet.ReasonCode.Value);
|
||||
|
||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Formatter.V311;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Formatter.V500
|
||||
{
|
||||
public class MqttV500PacketFormatter : MqttV311PacketFormatter
|
||||
{
|
||||
private readonly MqttV500PacketEncoder _encoder = new MqttV500PacketEncoder();
|
||||
private readonly MqttV500PacketDecoder _decoder = new MqttV500PacketDecoder();
|
||||
|
||||
public override MqttPublishPacket ConvertApplicationMessageToPublishPacket(MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
return new MqttPublishPacket
|
||||
{
|
||||
Topic = applicationMessage.Topic,
|
||||
Payload = applicationMessage.Payload,
|
||||
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
|
||||
Retain = applicationMessage.Retain,
|
||||
Dup = false,
|
||||
Properties = new MqttPublishPacketProperties
|
||||
{
|
||||
UserProperties = new List<MqttUserProperty>(applicationMessage.UserProperties)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override byte SerializeConnectPacket(MqttConnectPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
return _encoder.EncodeConnectPacket(packet, packetWriter);
|
||||
}
|
||||
|
||||
protected override byte SerializeConnAckPacket(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
return _encoder.EncodeConnAckPacket(packet, packetWriter);
|
||||
}
|
||||
|
||||
protected override MqttBasePacket DeserializeConnAckPacket(MqttPacketBodyReader body)
|
||||
{
|
||||
return _decoder.DecodeConnAckPacket(body);
|
||||
}
|
||||
|
||||
protected override byte SerializePublishPacket(MqttPublishPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
return _encoder.EncodePublishPacket(packet, packetWriter);
|
||||
}
|
||||
|
||||
protected override byte SerializePubAckPacket(MqttPubAckPacket packet, MqttPacketWriter packetWriter)
|
||||
{
|
||||
return _encoder.EncodePubAckPacket(packet, packetWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Formatter.V500
|
||||
{
|
||||
public class MqttV500PropertiesWriter
|
||||
{
|
||||
private readonly MqttPacketWriter _packetWriter = new MqttPacketWriter();
|
||||
|
||||
public void Write(MqttPropertyID id, bool? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write(value.Value ? (byte)0x1 : (byte)0x0);
|
||||
}
|
||||
|
||||
public void Write(MqttPropertyID id, ushort? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write(value.Value);
|
||||
}
|
||||
|
||||
public void WriteAsVariableLengthInteger(MqttPropertyID id, uint? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteVariableLengthInteger(value.Value);
|
||||
}
|
||||
|
||||
public void WriteAsFourByteInteger(MqttPropertyID id, uint? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.Write((byte)(value.Value >> 24));
|
||||
_packetWriter.Write((byte)(value.Value >> 16));
|
||||
_packetWriter.Write((byte)(value.Value >> 8));
|
||||
_packetWriter.Write((byte)value.Value);
|
||||
}
|
||||
|
||||
public void Write(MqttPropertyID id, string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteWithLengthPrefix(value);
|
||||
}
|
||||
|
||||
public void Write(MqttPropertyID id, byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)id);
|
||||
_packetWriter.WriteWithLengthPrefix(value);
|
||||
}
|
||||
|
||||
public void WriteUserProperties(List<MqttUserProperty> userProperties)
|
||||
{
|
||||
if (userProperties == null || userProperties.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var propertyWriter = new MqttPacketWriter();
|
||||
foreach (var property in userProperties)
|
||||
{
|
||||
propertyWriter.WriteWithLengthPrefix(property.Name);
|
||||
propertyWriter.WriteWithLengthPrefix(property.Value);
|
||||
}
|
||||
|
||||
_packetWriter.Write((byte)MqttPropertyID.UserProperty);
|
||||
_packetWriter.WriteVariableLengthInteger((uint)propertyWriter.Length);
|
||||
_packetWriter.Write(propertyWriter);
|
||||
}
|
||||
|
||||
public void WriteToPacket(MqttPacketWriter packetWriter)
|
||||
{
|
||||
if (packetWriter == null) throw new ArgumentNullException(nameof(packetWriter));
|
||||
|
||||
packetWriter.WriteVariableLengthInteger((uint)_packetWriter.Length);
|
||||
packetWriter.Write(packetWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client.Publishing;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public interface IApplicationMessagePublisher
|
||||
{
|
||||
Task PublishAsync(MqttApplicationMessage applicationMessage);
|
||||
Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using Windows.Networking;
|
||||
using Windows.Networking.Sockets;
|
||||
using Windows.Security.Cryptography.Certificates;
|
||||
using MQTTnet.Channel;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Implementations
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MQTTnet.Channel;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
|
||||
namespace MQTTnet.Implementations
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Channel;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
|
||||
namespace MQTTnet.Implementations
|
||||
{
|
||||
@@ -155,9 +155,7 @@ namespace MQTTnet.Implementations
|
||||
|
||||
if (!string.IsNullOrEmpty(_options.ProxyOptions.Username) && !string.IsNullOrEmpty(_options.ProxyOptions.Password))
|
||||
{
|
||||
var credentials =
|
||||
new NetworkCredential(_options.ProxyOptions.Username, _options.ProxyOptions.Password, _options.ProxyOptions.Domain);
|
||||
|
||||
var credentials = new NetworkCredential(_options.ProxyOptions.Username, _options.ProxyOptions.Password, _options.ProxyOptions.Domain);
|
||||
return new WebProxy(proxyUri, _options.ProxyOptions.BypassOnLocal, _options.ProxyOptions.BypassList, credentials);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Internal
|
||||
{
|
||||
public static class MqttApplicationMessageExtensions
|
||||
{
|
||||
public static MqttApplicationMessage ToApplicationMessage(this MqttPublishPacket publishPacket)
|
||||
{
|
||||
return new MqttApplicationMessage
|
||||
{
|
||||
Topic = publishPacket.Topic,
|
||||
Payload = publishPacket.Payload,
|
||||
QualityOfServiceLevel = publishPacket.QualityOfServiceLevel,
|
||||
Retain = publishPacket.Retain
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,22 @@ namespace MQTTnet
|
||||
|
||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
|
||||
public bool Retain { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; } = new List<MqttUserProperty>();
|
||||
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public string ResponseTopic { get; set; }
|
||||
|
||||
public MqttPayloadFormatIndicator? PayloadFormatIndicator { get; set; }
|
||||
|
||||
public uint? MessageExpiryInterval { get; set; }
|
||||
|
||||
public ushort? TopicAlias { get; set; }
|
||||
|
||||
public byte[] CorrelationData { get; set; }
|
||||
|
||||
public uint? SubscriptionIdentifier { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,26 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public class MqttApplicationMessageBuilder
|
||||
{
|
||||
private readonly List<MqttUserProperty> _userProperties = new List<MqttUserProperty>();
|
||||
|
||||
private MqttQualityOfServiceLevel _qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
|
||||
private string _topic;
|
||||
private byte[] _payload;
|
||||
private bool _retain;
|
||||
private string _contentType;
|
||||
private string _responseTopic;
|
||||
private byte[] _correlationData;
|
||||
private ushort? _topicAlias;
|
||||
private uint? _subscriptionIdentifier;
|
||||
private uint? _messageExpiryInterval;
|
||||
private MqttPayloadFormatIndicator? _payloadFormatIndicator;
|
||||
|
||||
public MqttApplicationMessageBuilder WithTopic(string topic)
|
||||
{
|
||||
@@ -100,6 +110,78 @@ namespace MQTTnet
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithUserProperty(string name, string value)
|
||||
{
|
||||
_userProperties.Add(new MqttUserProperty(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithContentType(string contentType)
|
||||
{
|
||||
_contentType = contentType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithResponseTopic(string responseTopic)
|
||||
{
|
||||
_responseTopic = responseTopic;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithCorrelationData(byte[] correlationData)
|
||||
{
|
||||
_correlationData = correlationData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithTopicAlias(ushort topicAlias)
|
||||
{
|
||||
_topicAlias = topicAlias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithSubscriptionIdentifier(uint subscriptionIdentifier)
|
||||
{
|
||||
_subscriptionIdentifier = subscriptionIdentifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithMessageExpiryInterval(uint messageExpiryInterval)
|
||||
{
|
||||
_messageExpiryInterval = messageExpiryInterval;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is only supported when using MQTTv5.
|
||||
/// </summary>
|
||||
public MqttApplicationMessageBuilder WithPayloadFormatIndicator(MqttPayloadFormatIndicator payloadFormatIndicator)
|
||||
{
|
||||
_payloadFormatIndicator = payloadFormatIndicator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttApplicationMessage Build()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_topic))
|
||||
@@ -107,13 +189,24 @@ namespace MQTTnet
|
||||
throw new MqttProtocolViolationException("Topic is not set.");
|
||||
}
|
||||
|
||||
return new MqttApplicationMessage
|
||||
var applicationMessage = new MqttApplicationMessage
|
||||
{
|
||||
Topic = _topic,
|
||||
Payload = _payload ?? new byte[0],
|
||||
QualityOfServiceLevel = _qualityOfServiceLevel,
|
||||
Retain = _retain
|
||||
Retain = _retain,
|
||||
ContentType = _contentType,
|
||||
ResponseTopic = _responseTopic,
|
||||
CorrelationData = _correlationData,
|
||||
TopicAlias = _topicAlias,
|
||||
SubscriptionIdentifier = _subscriptionIdentifier,
|
||||
MessageExpiryInterval = _messageExpiryInterval,
|
||||
PayloadFormatIndicator = _payloadFormatIndicator
|
||||
};
|
||||
|
||||
applicationMessage.UserProperties.AddRange(_userProperties);
|
||||
|
||||
return applicationMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,7 @@ namespace MQTTnet.Packets
|
||||
public class MqttAuthPacket : MqttBasePacket
|
||||
{
|
||||
public MqttAuthenticateReasonCode ReasonCode { get; set; }
|
||||
|
||||
public MqttAuthPacketProperties Properties { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttAuthPacketProperties
|
||||
{
|
||||
public string AuthenticationMethod { get; set; }
|
||||
|
||||
public byte[] AuthenticationData { get; set; }
|
||||
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,15 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttConnAckPacket : MqttBasePacket
|
||||
{
|
||||
public MqttConnectReturnCode ConnectReturnCode { get; set; }
|
||||
public MqttConnectReturnCode? ReturnCode { get; set; }
|
||||
|
||||
#region Added in MQTTv3.1.1
|
||||
|
||||
/// <summary>
|
||||
/// Added in MQTTv3.1.1.
|
||||
/// </summary>
|
||||
public bool IsSessionPresent { get; set; }
|
||||
|
||||
#region Added in MQTTv5
|
||||
#endregion
|
||||
|
||||
#region Added in MQTTv5.0.0
|
||||
|
||||
public MqttConnectReasonCode? ReasonCode { get; set; }
|
||||
|
||||
@@ -21,7 +22,7 @@ namespace MQTTnet.Packets
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Concat("ConnAck: [ConnectReturnCode=", ConnectReturnCode, "] [ReasonCode=", ReasonCode, "] [IsSessionPresent=", IsSessionPresent, "]");
|
||||
return string.Concat("ConnAck: [ReturnCode=", ReturnCode, "] [ReasonCode=", ReasonCode, "] [IsSessionPresent=", IsSessionPresent, "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public uint? SessionExpiryInterval { get; set; }
|
||||
|
||||
// TODO: Add enum
|
||||
public ushort? ReceiveMaximum { get; set; }
|
||||
|
||||
public bool? RetainAvailable { get; set; }
|
||||
@@ -19,7 +18,7 @@ namespace MQTTnet.Packets
|
||||
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
|
||||
public bool? WildcardSubscriptionAvailable { get; set; }
|
||||
|
||||
|
||||
@@ -14,14 +14,12 @@
|
||||
|
||||
public ushort KeepAlivePeriod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MQTTv5: Also called "Clean Start".
|
||||
/// </summary>
|
||||
// Also called "Clean Start" in MQTTv5.
|
||||
public bool CleanSession { get; set; }
|
||||
|
||||
public MqttApplicationMessage WillMessage { get; set; }
|
||||
|
||||
#region Added in MQTTv5
|
||||
#region Added in MQTTv5.0.0
|
||||
|
||||
public MqttConnectPacketProperties Properties { get; set; }
|
||||
|
||||
|
||||
@@ -22,6 +22,6 @@ namespace MQTTnet.Packets
|
||||
|
||||
public uint? MaximumPacketSize { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
namespace MQTTnet.Packets
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttDisconnectPacket : MqttBasePacket
|
||||
{
|
||||
#region Added in MQTTv5
|
||||
|
||||
public MqttDisconnectReasonCode? ReasonCode { get; set; }
|
||||
|
||||
public MqttDisconnectPacketProperties Properties { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Disconnect";
|
||||
return string.Concat("Disconnect: [ReasonCode=", ReasonCode, "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttDisconnectPacketProperties
|
||||
{
|
||||
public uint? SessionExpiryInterval { get; set; }
|
||||
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
|
||||
public string ServerReference { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace MQTTnet.Packets
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Concat("PubAck: [PacketIdentifier=", PacketIdentifier, "] [ConnectReasonCode=", ReasonCode, "]");
|
||||
return string.Concat("PubAck: [PacketIdentifier=", PacketIdentifier, "] [ReasonCode=", ReasonCode, "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttPublishPacketProperties
|
||||
{
|
||||
public byte? PayloadFormatIndicator { get; set; }
|
||||
public MqttPayloadFormatIndicator? PayloadFormatIndicator { get; set; }
|
||||
|
||||
public uint? MessageExpiryInterval { get; set; }
|
||||
|
||||
@@ -14,7 +15,7 @@ namespace MQTTnet.Packets
|
||||
|
||||
public byte[] CorrelationData { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
|
||||
public uint? SubscriptionIdentifier { get; set; }
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public ushort? PacketIdentifier { get; set; }
|
||||
|
||||
public List<MqttSubscribeReturnCode> SubscribeReturnCodes { get; } = new List<MqttSubscribeReturnCode>();
|
||||
public List<MqttSubscribeReturnCode> ReturnCodes { get; } = new List<MqttSubscribeReturnCode>();
|
||||
|
||||
#region Added in MQTTv5
|
||||
#region Added in MQTTv5.0.0
|
||||
|
||||
public List<MqttSubscribeReasonCode?> ReasonCodes { get; set; }
|
||||
public List<MqttSubscribeReasonCode> ReasonCodes { get; } = new List<MqttSubscribeReasonCode>();
|
||||
|
||||
public MqttSubAckPacketProperties Properties { get; set; }
|
||||
|
||||
@@ -20,8 +20,10 @@ namespace MQTTnet.Packets
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var subscribeReturnCodesText = string.Join(",", SubscribeReturnCodes.Select(f => f.ToString()));
|
||||
return string.Concat("SubAck: [PacketIdentifier=", PacketIdentifier, "] [SubscribeReturnCodes=", subscribeReturnCodesText, "]");
|
||||
var returnCodesText = string.Join(",", ReturnCodes.Select(f => f.ToString()));
|
||||
var reasonCodesText = string.Join(",", ReasonCodes.Select(f => f.ToString()));
|
||||
|
||||
return string.Concat("SubAck: [PacketIdentifier=", PacketIdentifier, "] [ReturnCodes=", returnCodesText, "] [ReasonCode=", reasonCodesText, "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public ushort? PacketIdentifier { get; set; }
|
||||
|
||||
public IList<TopicFilter> TopicFilters { get; set; } = new List<TopicFilter>();
|
||||
public List<TopicFilter> TopicFilters { get; } = new List<TopicFilter>();
|
||||
|
||||
#region Added in MQTTv5
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public uint? SubscriptionIdentifier { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; set; }
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
namespace MQTTnet.Packets
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttUnsubAckPacket : MqttBasePacket, IMqttPacketWithIdentifier
|
||||
{
|
||||
public ushort? PacketIdentifier { get; set; }
|
||||
|
||||
#region Added in MQTTv5
|
||||
|
||||
public MqttUnsubAckPacketProperties Properties { get; set; }
|
||||
|
||||
public List<MqttUnsubscribeReasonCode> ReasonCodes { get; } = new List<MqttUnsubscribeReasonCode>();
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Concat("UnsubAck: [PacketIdentifier=", PacketIdentifier, "]");
|
||||
var reasonCodesText = string.Join(",", ReasonCodes.Select(f => f.ToString()));
|
||||
|
||||
return string.Concat("UnsubAck: [PacketIdentifier=", PacketIdentifier, "] [ReasonCodes=", reasonCodesText, "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttUnsubAckPacketProperties
|
||||
{
|
||||
public string ReasonString { get; set; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -6,7 +6,13 @@ namespace MQTTnet.Packets
|
||||
{
|
||||
public ushort? PacketIdentifier { get; set; }
|
||||
|
||||
public IList<string> TopicFilters { get; set; } = new List<string>();
|
||||
public List<string> TopicFilters { get; } = new List<string>();
|
||||
|
||||
#region Added in MQTTv5
|
||||
|
||||
public MqttUnsubscribePacketProperties Properties { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MQTTnet.Packets
|
||||
{
|
||||
public class MqttUnsubscribePacketProperties
|
||||
{
|
||||
public List<MqttUserProperty> UserProperties { get; } = new List<MqttUserProperty>();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
ImplementationSpecificError = 131,
|
||||
UnsupportedProtocolVersion = 132,
|
||||
ClientIdentifierNotValid = 133,
|
||||
BadUserNameorPassword = 134,
|
||||
BadUserNameOrPassword = 134,
|
||||
NotAuthorized = 135,
|
||||
ServerUnavailable = 136,
|
||||
ServerBusy = 137,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
UnsubAck = 11,
|
||||
PingReq = 12,
|
||||
PingResp = 13,
|
||||
Disconnect = 14
|
||||
Disconnect = 14,
|
||||
Auth = 15
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user