Files
MQTTnet/Samples/Server/Server_Retained_Messages_Samples.cs
T
980a5d0a6d Improve performance and drop support for old frameworks (#2068)
* Remove WebSocket4Net extension library

* Remove UWP support

* Drop support for all old frameworks

* Update CI

* Update CI

* Update CI

* Update CI

* Remove obsolete code

* Set default protocol version to 5.0.0

* Remove obsolete tests

* Remove old dependencies

* Reset release notes

* Move server to dedicated project

* Fix unit tests

* Update and cleanup nuget packages

* Fix unit tests
Refactor code

* No longer throw exception when receiving non success CONNACK

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable code signing

* Enable code signing

* Enable code signing

* Fix client endpoint handling

* Improve CI

* Fix CI

* Fix CI

* Fix CI

* Fix CI

* Import changes from version 4

* Cleanup target frameworks and remove obsolete code

* Drop support for dotnet7.0

* Remove managed client

* Version5 auditmode (#2016)

Added NuGet audit mode and some other settings to get informed about security issues.

* Address warnings from analyzers

* Support for ReadOnlySequence as payload (#2046)

* use ReadOnlySequence as payload

* fix build

* fix build

* skip sign in forks

* remove unnecessary owner

* tests and extensions

* remove test

* simplify WritePacketBuffer, remove unused helper

* Adjust namespaces

* Fix build errors

* Import latest fixes from main branch

* Adjust namespaces

---------

Co-authored-by: SeppPenner <HansM2013@gmx.de>
Co-authored-by: Martin Regen <mregen@microsoft.com>
2024-08-24 11:47:21 +02:00

146 lines
5.8 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using System.Buffers;
using System.Text.Json;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Server;
namespace MQTTnet.Samples.Server;
public static class Server_Retained_Messages_Samples
{
public static async Task Persist_Retained_Messages()
{
/*
* This sample starts a simple MQTT server which will store all retained messages in a file.
*/
var storePath = Path.Combine(Path.GetTempPath(), "RetainedMessages.json");
var mqttServerFactory = new MqttServerFactory();
// Due to security reasons the "default" endpoint (which is unencrypted) is not enabled by default!
var mqttServerOptions = mqttServerFactory.CreateServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var server = mqttServerFactory.CreateMqttServer(mqttServerOptions))
{
// Make sure that the server will load the retained messages.
server.LoadingRetainedMessageAsync += async eventArgs =>
{
try
{
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)
{
// Ignore because nothing is stored yet.
Console.WriteLine("No retained messages stored yet.");
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
};
// Make sure to persist the changed retained messages.
server.RetainedMessageChangedAsync += async eventArgs =>
{
try
{
// This sample uses the property _StoredRetainedMessages_ which will contain all(!) retained messages.
// The event args also contain the affected retained message (property ChangedRetainedMessage). This can be
// 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 models = eventArgs.StoredRetainedMessages.Select(MqttRetainedMessageModel.Create);
var buffer = JsonSerializer.SerializeToUtf8Bytes(models);
await File.WriteAllBytesAsync(storePath, buffer);
Console.WriteLine("Retained messages saved.");
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
};
// Make sure to clear the retained messages when they are all deleted via API.
server.RetainedMessagesClearedAsync += _ =>
{
File.Delete(storePath);
return Task.CompletedTask;
};
await server.StartAsync();
Console.WriteLine("Press Enter to exit.");
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.Payload.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
};
}
}
}