...
 
Commits (3)
    https://gitcode.net/dotnet/MQTTnet/-/commit/a97e88be29979c976ae8910d91869d90c1bf5a99 Update Client_Subscribe_Samples.cs (#1766) 2023-06-15T17:31:01+02:00 HansM HansM2013@gmx.de Fixes <a href="https://github.com/dotnet/MQTTnet/issues/1765" rel="nofollow noreferrer noopener" target="_blank">https://github.com/dotnet/MQTTnet/issues/1765</a>. https://gitcode.net/dotnet/MQTTnet/-/commit/560e80455ff40dbf4b4724dd58f1b4edb2398625 Update samples (#1768) 2023-06-15T18:32:28+02:00 Christian 6939810+chkr1011@users.noreply.github.com https://gitcode.net/dotnet/MQTTnet/-/commit/18614d4e81b64ca486a5f951a806eea2d495eb21 Expose configuration of packet fragmentation in server options. (#1769) 2023-06-15T18:51:43+02:00 Christian 6939810+chkr1011@users.noreply.github.com
* [Client] Fixed _PlatformNotSupportedException_ when using Blazor (#1755, thanks to @Nickztar).
* [Server] Fixed _NullReferenceException_ in retained messages management (#1762, thanks to @logicaloud).
* [Server] Exposed new option which allows disabling packet fragmentation (#1753).
......@@ -6,6 +6,7 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Packets;
using MQTTnet.Protocol;
......@@ -176,4 +177,4 @@ public static class Client_Subscribe_Samples
response.DumpToConsole();
}
}
}
\ No newline at end of file
}
......@@ -7,6 +7,8 @@
// ReSharper disable InconsistentNaming
using System.Text.Json;
using MQTTnet.Packets;
using MQTTnet.Protocol;
namespace MQTTnet.Samples.Server;
......@@ -32,7 +34,10 @@ public static class Server_Retained_Messages_Samples
{
try
{
eventArgs.LoadedRetainedMessages = await JsonSerializer.DeserializeAsync<List<MqttApplicationMessage>>(File.OpenRead(storePath));
var models = await JsonSerializer.DeserializeAsync<List<MqttRetainedMessageModel>>(File.OpenRead(storePath)) ?? new List<MqttRetainedMessageModel>();
var retainedMessages = models.Select(m => m.ToApplicationMessage()).ToList();
eventArgs.LoadedRetainedMessages = retainedMessages;
Console.WriteLine("Retained messages loaded.");
}
catch (FileNotFoundException)
......@@ -56,7 +61,9 @@ public static class Server_Retained_Messages_Samples
// used to write all retained messages to dedicated files etc. Then all files must be loaded and a full list
// of retained messages must be provided in the loaded event.
var buffer = JsonSerializer.SerializeToUtf8Bytes(eventArgs.StoredRetainedMessages);
var models = eventArgs.StoredRetainedMessages.Select(MqttRetainedMessageModel.Create);
var buffer = JsonSerializer.SerializeToUtf8Bytes(models);
await File.WriteAllBytesAsync(storePath, buffer);
Console.WriteLine("Retained messages saved.");
}
......@@ -79,4 +86,59 @@ public static class Server_Retained_Messages_Samples
Console.ReadLine();
}
}
sealed class MqttRetainedMessageModel
{
public string? ContentType { get; set; }
public byte[]? CorrelationData { get; set; }
public byte[]? Payload { get; set; }
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; }
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
public string? ResponseTopic { get; set; }
public string? Topic { get; set; }
public List<MqttUserProperty>? UserProperties { get; set; }
public static MqttRetainedMessageModel Create(MqttApplicationMessage message)
{
if (message == null)
{
throw new ArgumentNullException(nameof(message));
}
return new MqttRetainedMessageModel
{
Topic = message.Topic,
// Create a copy of the buffer from the payload segment because
// it cannot be serialized and deserialized with the JSON serializer.
Payload = message.PayloadSegment.ToArray(),
UserProperties = message.UserProperties,
ResponseTopic = message.ResponseTopic,
CorrelationData = message.CorrelationData,
ContentType = message.ContentType,
PayloadFormatIndicator = message.PayloadFormatIndicator,
QualityOfServiceLevel = message.QualityOfServiceLevel
// Other properties like "Retain" are not if interest in the storage.
// That's why a custom model makes sense.
};
}
public MqttApplicationMessage ToApplicationMessage()
{
return new MqttApplicationMessage
{
Topic = Topic,
PayloadSegment = new ArraySegment<byte>(Payload ?? Array.Empty<byte>()),
PayloadFormatIndicator = PayloadFormatIndicator,
ResponseTopic = ResponseTopic,
CorrelationData = CorrelationData,
ContentType = ContentType,
UserProperties = UserProperties,
QualityOfServiceLevel = QualityOfServiceLevel,
Dup = false,
Retain = true
};
}
}
}
\ No newline at end of file
......@@ -231,6 +231,7 @@ namespace MQTTnet.Implementations
using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, _rootLogger))
{
clientAdapter.AllowPacketFragmentation = _options.AllowPacketFragmentation;
await clientHandler(clientAdapter).ConfigureAwait(false);
}
}
......@@ -255,6 +256,7 @@ namespace MQTTnet.Implementations
{
try
{
// ReSharper disable once MethodHasAsyncOverload
stream?.Dispose();
clientSocket?.Dispose();
}
......
......@@ -227,11 +227,12 @@ namespace MQTTnet.Implementations
{
clientWebSocket.Options.UseDefaultCredentials = _options.UseDefaultCredentials;
}
#endif
if (_options.KeepAliveInterval != WebSocket.DefaultKeepAliveInterval)
{
clientWebSocket.Options.KeepAliveInterval = _options.KeepAliveInterval;
}
#endif
#endif
if (_options.Credentials != null)
{
......
......@@ -131,6 +131,18 @@ namespace MQTTnet.Server
return this;
}
/// <summary>
/// Usually the MQTT packets can be send partially to improve memory allocations.
/// This is done by using multiple TCP packets or WebSocket frames etc.
/// Unfortunately not all clients do support this and will close the connection when receiving partial packets.
/// </summary>
public MqttServerOptionsBuilder WithoutPacketFragmentation()
{
_options.DefaultEndpointOptions.AllowPacketFragmentation = false;
_options.TlsEndpointOptions.AllowPacketFragmentation = false;
return this;
}
public MqttServerOptionsBuilder WithPersistentSessions(bool value = true)
{
_options.EnablePersistentSessions = value;
......
......@@ -23,6 +23,14 @@ namespace MQTTnet.Server
/// </summary>
public bool? KeepAlive { get; set; }
/// <summary>
/// Usually the MQTT packets can be send partially. This is done by using multiple TCP packets
/// or WebSocket frames etc. Unfortunately not all clients do support this feature and
/// will close the connection when receiving such packets. If such clients are connecting to this
/// server the flag must be set to _false_.
/// </summary>
public bool AllowPacketFragmentation { get; set; } = true;
/// <summary>
/// Gets or sets the TCP keep alive interval.
/// The value _null_ indicates that the OS and framework defaults should be used.
......