mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 01:03:01 +08:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8321806acf | ||
|
|
081ef3077a | ||
|
|
a3fbb928d6 | ||
|
|
42ba46b885 | ||
|
|
07409e3a35 | ||
|
|
1a3e97afec |
+13
-11
@@ -17,20 +17,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.0.x
|
8.0.x
|
||||||
|
10.0.x
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Load strong name certificate
|
- name: Load strong name certificate
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
run: |
|
run: |
|
||||||
echo "$SNC_BASE64" | base64 --decode > "${{ github.workspace }}/certificate.snk"
|
echo "$SNC_BASE64" | base64 --decode > "${{ github.workspace }}/certificate.snk"
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
SNC_BASE64: ${{ secrets.SNC_BASE64 }}
|
SNC_BASE64: ${{ secrets.SNC_BASE64 }}
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package (signed)
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
run: dotnet build MQTTnet.sln --configuration Release /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.VERSION }} /p:PackageVersion=${{ env.VERSION }}${{ env.PACKAGE_SUFFIX }} /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=${{ github.workspace }}/certificate.snk
|
run: dotnet build MQTTnet.sln --configuration Release /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.VERSION }} /p:PackageVersion=${{ env.VERSION }}${{ env.PACKAGE_SUFFIX }} /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=${{ github.workspace }}/certificate.snk
|
||||||
|
|
||||||
|
- name: Build package (unsigned)
|
||||||
|
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
|
||||||
|
run: dotnet build MQTTnet.sln --configuration Release /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.VERSION }} /p:PackageVersion=${{ env.VERSION }}${{ env.PACKAGE_SUFFIX }}
|
||||||
|
|
||||||
- name: Upload nuget packages
|
- name: Upload nuget packages
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -48,24 +55,19 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.0.x
|
8.0.x
|
||||||
|
10.0.x
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Execute tests
|
- name: Execute tests
|
||||||
run: dotnet test --framework net8.0 --configuration Release Source/MQTTnet.Tests/MQTTnet.Tests.csproj
|
run: dotnet test --framework net10.0 --configuration Release --project Source/MQTTnet.Tests/MQTTnet.Tests.csproj
|
||||||
|
|
||||||
sign:
|
sign:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: windows-latest # Code signing must run on a Windows agent for Authenticode signing (dll/exe)
|
runs-on: windows-latest # Code signing must run on a Windows agent for Authenticode signing (dll/exe)
|
||||||
if: github.repository == 'dotnet/MQTTnet'
|
if: github.repository == 'dotnet/MQTTnet' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
|
||||||
steps:
|
steps:
|
||||||
- name: Setup .NET SDK
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
6.0.x
|
|
||||||
|
|
||||||
- name: Download nuget packages
|
- name: Download nuget packages
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -73,7 +75,7 @@ jobs:
|
|||||||
path: nugets
|
path: nugets
|
||||||
|
|
||||||
- name: Install sign CLI tool
|
- name: Install sign CLI tool
|
||||||
run: dotnet tool install --tool-path . sign --version 0.9.0-beta.23127.3
|
run: dotnet tool install --tool-path . sign --version 0.9.1-beta.25379.1
|
||||||
|
|
||||||
- name: Sign nugets
|
- name: Sign nugets
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
@@ -114,7 +116,7 @@ jobs:
|
|||||||
run: dotnet nuget push ${{ github.workspace }}/nugets/**/*.nupkg -k ${{ secrets.MYGET_API_KEY }} -s https://www.myget.org/F/mqttnet/api/v3/index.json --skip-duplicate
|
run: dotnet nuget push ${{ github.workspace }}/nugets/**/*.nupkg -k ${{ secrets.MYGET_API_KEY }} -s https://www.myget.org/F/mqttnet/api/v3/index.json --skip-duplicate
|
||||||
|
|
||||||
publish-nuget:
|
publish-nuget:
|
||||||
# Tag schema is 'v5.0.0-rc' etc.
|
# Tag schema is 'v5.1.0-rc' etc.
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
needs: [sign, test]
|
needs: [sign, test]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
+3
-27
@@ -1,6 +1,6 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
|
||||||
<Product>MQTTnet</Product>
|
<Product>MQTTnet</Product>
|
||||||
<Authors>The contributors of MQTTnet</Authors>
|
<Authors>The contributors of MQTTnet</Authors>
|
||||||
<Company>The contributors of MQTTnet</Company>
|
<Company>The contributors of MQTTnet</Company>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>disable</Nullable>
|
||||||
|
|
||||||
<NeutralLanguage>en-US</NeutralLanguage>
|
<NeutralLanguage>en-US</NeutralLanguage>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
@@ -24,35 +25,10 @@
|
|||||||
<AnalysisLevel>latest</AnalysisLevel>
|
<AnalysisLevel>latest</AnalysisLevel>
|
||||||
<AnalysisMode>recommended</AnalysisMode>
|
<AnalysisMode>recommended</AnalysisMode>
|
||||||
<AnalysisModeStyle>default</AnalysisModeStyle>
|
<AnalysisModeStyle>default</AnalysisModeStyle>
|
||||||
|
|
||||||
<TestingPlatformShowTestsFailure>true</TestingPlatformShowTestsFailure>
|
|
||||||
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
|
|
||||||
<EnableMSTestRunner>true</EnableMSTestRunner>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
|
<PropertyGroup Condition="'$(GITHUB_ACTIONS)'=='true'">
|
||||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(GeneratePackageOnBuild)'=='true'">
|
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
|
||||||
<PackageIcon>nuget.png</PackageIcon>
|
|
||||||
<PackageProjectUrl>https://github.com/dotnet/MQTTnet</PackageProjectUrl>
|
|
||||||
<RepositoryUrl>https://github.com/dotnet/MQTTnet.git</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<IncludeSymbols>true</IncludeSymbols>
|
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
|
||||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(GeneratePackageOnBuild)'=='true'">
|
|
||||||
<None Include="README.md" Pack="true" PackagePath="" Condition="Exists('README.md')" />
|
|
||||||
<None Include="..\..\Images\nuget.png" Pack="true" PackagePath="" />
|
|
||||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(IncludeSymbols)'=='true'">
|
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<Project>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(GeneratePackageOnBuild)'=='true'">
|
||||||
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
|
<PackageIcon>nuget.png</PackageIcon>
|
||||||
|
<PackageProjectUrl>https://github.com/dotnet/MQTTnet</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/dotnet/MQTTnet.git</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(GeneratePackageOnBuild)'=='true'">
|
||||||
|
<None Include="README.md" Pack="true" PackagePath="" Condition="Exists('README.md')" />
|
||||||
|
<None Include="..\..\Images\nuget.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(IncludeSymbols)'=='true'">
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
Source\ReleaseNotes.md = Source\ReleaseNotes.md
|
Source\ReleaseNotes.md = Source\ReleaseNotes.md
|
||||||
|
Directory.Build.targets = Directory.Build.targets
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore", "Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj", "{F10C4060-F7EE-4A83-919F-FF723E72F94A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore", "Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj", "{F10C4060-F7EE-4A83-919F-FF723E72F94A}"
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MQTTnet.Samples.Client;
|
namespace MQTTnet.Samples.Client;
|
||||||
|
|
||||||
public static class Client_Publish_Samples
|
public static class Client_Publish_Samples
|
||||||
@@ -84,4 +87,21 @@ public static class Client_Publish_Samples
|
|||||||
|
|
||||||
Console.WriteLine("MQTT application message is published.");
|
Console.WriteLine("MQTT application message is published.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MqttApplicationMessage Create_Message_With_Binary_User_Property()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* MQTT v5 user properties are encoded as UTF-8 strings. When the UTF-8 payload is already available
|
||||||
|
* as a byte buffer, the builder APIs can avoid creating intermediate strings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var encodedValue = Encoding.UTF8.GetBytes("sensor-01");
|
||||||
|
|
||||||
|
return new MqttApplicationMessageBuilder()
|
||||||
|
.WithTopic("samples/metadata/binary")
|
||||||
|
.WithUserProperty("client-id", encodedValue.AsMemory())
|
||||||
|
.WithUserProperty("checksum", new ArraySegment<byte>(encodedValue))
|
||||||
|
.WithPayload("metadata")
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
// ReSharper disable UnusedMember.Local
|
// ReSharper disable UnusedMember.Local
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Samples.Helpers;
|
using MQTTnet.Samples.Helpers;
|
||||||
@@ -67,7 +68,7 @@ public static class Client_Subscribe_Samples
|
|||||||
args.ResponseReasonString = "That did not work!";
|
args.ResponseReasonString = "That did not work!";
|
||||||
|
|
||||||
// User properties require MQTT v5!
|
// User properties require MQTT v5!
|
||||||
args.ResponseUserProperties.Add(new MqttUserProperty("My", "Data"));
|
args.ResponseUserProperties.Add(new MqttUserProperty("My", Encoding.UTF8.GetBytes("Data")));
|
||||||
|
|
||||||
// Now the broker will resend the message again.
|
// Now the broker will resend the message again.
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
@@ -59,10 +59,12 @@ public static class Server_TLS_Samples
|
|||||||
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
|
|
||||||
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
||||||
|
#pragma warning disable SYSLIB0057
|
||||||
var pfxCertificate = new X509Certificate2(
|
var pfxCertificate = new X509Certificate2(
|
||||||
certificate.Export(X509ContentType.Pfx),
|
certificate.Export(X509ContentType.Pfx),
|
||||||
(string)null!,
|
(string)null!,
|
||||||
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
||||||
|
#pragma warning restore SYSLIB0057
|
||||||
|
|
||||||
return pfxCertificate;
|
return pfxCertificate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ public sealed class MqttServerClientDisconnectOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance `WithUserProperty` with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public MqttServerClientDisconnectOptionsBuilder WithUserProperty(string name, string value)
|
public MqttServerClientDisconnectOptionsBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
if (_options.UserProperties == null)
|
if (_options.UserProperties == null)
|
||||||
@@ -50,4 +51,26 @@ public sealed class MqttServerClientDisconnectOptionsBuilder
|
|||||||
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttServerClientDisconnectOptionsBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttServerClientDisconnectOptionsBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+29
@@ -51,6 +51,7 @@ public sealed class ExchangeEnhancedAuthenticationOptionsFactory
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance `WithUserProperty` with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public ExchangeEnhancedAuthenticationOptionsFactory WithUserProperty(string name, string value)
|
public ExchangeEnhancedAuthenticationOptionsFactory WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(name);
|
ArgumentNullException.ThrowIfNull(name);
|
||||||
@@ -64,4 +65,32 @@ public sealed class ExchangeEnhancedAuthenticationOptionsFactory
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExchangeEnhancedAuthenticationOptionsFactory WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(name);
|
||||||
|
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExchangeEnhancedAuthenticationOptionsFactory WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(name);
|
||||||
|
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +202,14 @@ public sealed class MqttTcpServerListener : IDisposable
|
|||||||
|
|
||||||
clientCertificate = sslStream.RemoteCertificate as X509Certificate2;
|
clientCertificate = sslStream.RemoteCertificate as X509Certificate2;
|
||||||
|
|
||||||
|
// TODO: Check why this export is needed. Is there something else in the RemoteCertificate as a X509Certificate2???
|
||||||
if (clientCertificate == null && sslStream.RemoteCertificate != null)
|
if (clientCertificate == null && sslStream.RemoteCertificate != null)
|
||||||
{
|
{
|
||||||
|
#if NET10_0_OR_GREATER
|
||||||
|
clientCertificate = X509CertificateLoader.LoadCertificate(sslStream.RemoteCertificate.Export(X509ContentType.Cert));
|
||||||
|
#else
|
||||||
clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert));
|
clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<DebugType>Full</DebugType>
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using MQTTnet.Server.EnhancedAuthentication;
|
using MQTTnet.Server.EnhancedAuthentication;
|
||||||
@@ -143,7 +144,7 @@ public sealed class MqttClient_Connection_Tests : BaseTestClass
|
|||||||
|
|
||||||
var client = await testEnvironment.ConnectClient();
|
var client = await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithUserProperty("test_name", "test_value").Build();
|
var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithUserProperty("test_name", Encoding.UTF8.GetBytes("test_value")).Build();
|
||||||
|
|
||||||
// Perform a clean disconnect.
|
// Perform a clean disconnect.
|
||||||
await client.DisconnectAsync(disconnectOptions);
|
await client.DisconnectAsync(disconnectOptions);
|
||||||
@@ -154,7 +155,7 @@ public sealed class MqttClient_Connection_Tests : BaseTestClass
|
|||||||
Assert.IsNotNull(eventArgs.UserProperties);
|
Assert.IsNotNull(eventArgs.UserProperties);
|
||||||
Assert.HasCount(1, eventArgs.UserProperties);
|
Assert.HasCount(1, eventArgs.UserProperties);
|
||||||
Assert.AreEqual("test_name", eventArgs.UserProperties[0].Name);
|
Assert.AreEqual("test_name", eventArgs.UserProperties[0].Name);
|
||||||
Assert.AreEqual("test_value", eventArgs.UserProperties[0].Value);
|
Assert.AreEqual("test_value", eventArgs.UserProperties[0].ReadValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class TestClientKerberosAuthenticationHandler : IMqttEnhancedAuthenticationHandler
|
sealed class TestClientKerberosAuthenticationHandler : IMqttEnhancedAuthenticationHandler
|
||||||
@@ -260,7 +261,7 @@ public sealed class MqttClient_Connection_Tests : BaseTestClass
|
|||||||
|
|
||||||
server.ValidatingConnectionAsync += args =>
|
server.ValidatingConnectionAsync += args =>
|
||||||
{
|
{
|
||||||
args.ResponseUserProperties = [new("Property", "Value")];
|
args.ResponseUserProperties = [new("Property", Encoding.UTF8.GetBytes("Value"))];
|
||||||
|
|
||||||
args.ReasonCode = MqttConnectReasonCode.QuotaExceeded;
|
args.ReasonCode = MqttConnectReasonCode.QuotaExceeded;
|
||||||
|
|
||||||
@@ -274,7 +275,7 @@ public sealed class MqttClient_Connection_Tests : BaseTestClass
|
|||||||
Assert.IsNotNull(response);
|
Assert.IsNotNull(response);
|
||||||
Assert.AreEqual(MqttClientConnectResultCode.QuotaExceeded, response.ResultCode);
|
Assert.AreEqual(MqttClientConnectResultCode.QuotaExceeded, response.ResultCode);
|
||||||
Assert.AreEqual("Property", response.UserProperties[0].Name);
|
Assert.AreEqual("Property", response.UserProperties[0].Name);
|
||||||
Assert.AreEqual("Value", response.UserProperties[0].Value);
|
Assert.AreEqual("Value", response.UserProperties[0].ReadValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
@@ -45,7 +46,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
SubscriptionIdentifiersAvailable = true,
|
SubscriptionIdentifiersAvailable = true,
|
||||||
TopicAliasMaximum = 963,
|
TopicAliasMaximum = 963,
|
||||||
WildcardSubscriptionAvailable = true,
|
WildcardSubscriptionAvailable = true,
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V311);
|
||||||
@@ -96,7 +97,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
SubscriptionIdentifiersAvailable = true,
|
SubscriptionIdentifiersAvailable = true,
|
||||||
TopicAliasMaximum = 963,
|
TopicAliasMaximum = 963,
|
||||||
WildcardSubscriptionAvailable = true,
|
WildcardSubscriptionAvailable = true,
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V310);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V310);
|
||||||
@@ -152,8 +153,8 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
WillResponseTopic = "WillResponseTopic",
|
WillResponseTopic = "WillResponseTopic",
|
||||||
WillMessageExpiryInterval = 542,
|
WillMessageExpiryInterval = 542,
|
||||||
WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
||||||
UserProperties = [new("Foo", "Bar")],
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))],
|
||||||
WillUserProperties = [new("WillFoo", "WillBar")]
|
WillUserProperties = [new("WillFoo", Encoding.UTF8.GetBytes("WillBar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V311);
|
||||||
@@ -195,7 +196,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
ServerReference = "ServerReference",
|
ServerReference = "ServerReference",
|
||||||
SessionExpiryInterval = 234,
|
SessionExpiryInterval = 234,
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V311);
|
||||||
@@ -235,7 +236,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers,
|
ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V311);
|
||||||
@@ -254,7 +255,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound,
|
ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V311);
|
||||||
@@ -284,7 +285,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
SubscriptionIdentifiers = [123],
|
SubscriptionIdentifiers = [123],
|
||||||
MessageExpiryInterval = 38,
|
MessageExpiryInterval = 38,
|
||||||
PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V311);
|
||||||
@@ -313,7 +314,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubRecReasonCode.UnspecifiedError,
|
ReasonCode = MqttPubRecReasonCode.UnspecifiedError,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V311);
|
||||||
@@ -333,7 +334,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound,
|
ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V311);
|
||||||
@@ -353,7 +354,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1],
|
ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1],
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V311);
|
||||||
@@ -383,7 +384,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
|
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V311);
|
||||||
@@ -407,7 +408,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError],
|
ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError],
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V311);
|
||||||
@@ -425,7 +426,7 @@ public sealed class MqttPacketSerialization_V3_Tests
|
|||||||
{
|
{
|
||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
TopicFilters = ["TopicFilter1"],
|
TopicFilters = ["TopicFilter1"],
|
||||||
UserProperties = [new("Foo", "Bar")]
|
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V311);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V311);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
@@ -32,7 +33,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
AuthenticationMethod = "AuthenticationMethod",
|
AuthenticationMethod = "AuthenticationMethod",
|
||||||
ReasonCode = MqttAuthenticateReasonCode.ContinueAuthentication,
|
ReasonCode = MqttAuthenticateReasonCode.ContinueAuthentication,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(authPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(authPacket, MqttProtocolVersion.V500);
|
||||||
@@ -68,7 +69,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
SubscriptionIdentifiersAvailable = true,
|
SubscriptionIdentifiersAvailable = true,
|
||||||
TopicAliasMaximum = 963,
|
TopicAliasMaximum = 963,
|
||||||
WildcardSubscriptionAvailable = true,
|
WildcardSubscriptionAvailable = true,
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V500);
|
||||||
@@ -124,8 +125,8 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
WillResponseTopic = "WillResponseTopic",
|
WillResponseTopic = "WillResponseTopic",
|
||||||
WillMessageExpiryInterval = 542,
|
WillMessageExpiryInterval = 542,
|
||||||
WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")],
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))],
|
||||||
WillUserProperties = [new MqttUserProperty("WillFoo", "WillBar")]
|
WillUserProperties = [new MqttUserProperty("WillFoo", Encoding.UTF8.GetBytes("WillBar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V500);
|
||||||
@@ -167,7 +168,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
ServerReference = "ServerReference",
|
ServerReference = "ServerReference",
|
||||||
SessionExpiryInterval = 234,
|
SessionExpiryInterval = 234,
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V500);
|
||||||
@@ -207,7 +208,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers,
|
ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V500);
|
||||||
@@ -226,7 +227,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound,
|
ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V500);
|
||||||
@@ -255,7 +256,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
SubscriptionIdentifiers = [123],
|
SubscriptionIdentifiers = [123],
|
||||||
MessageExpiryInterval = 38,
|
MessageExpiryInterval = 38,
|
||||||
PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V500);
|
||||||
@@ -284,7 +285,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubRecReasonCode.UnspecifiedError,
|
ReasonCode = MqttPubRecReasonCode.UnspecifiedError,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V500);
|
||||||
@@ -303,7 +304,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound,
|
ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V500);
|
||||||
@@ -322,7 +323,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1],
|
ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1],
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V500);
|
||||||
@@ -352,7 +353,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
|
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V500);
|
||||||
@@ -376,7 +377,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError],
|
ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError],
|
||||||
ReasonString = "ReasonString",
|
ReasonString = "ReasonString",
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V500);
|
||||||
@@ -395,7 +396,7 @@ public sealed class MqttPacketSerialization_V5_Tests
|
|||||||
{
|
{
|
||||||
PacketIdentifier = 123,
|
PacketIdentifier = 123,
|
||||||
TopicFilters = ["TopicFilter1"],
|
TopicFilters = ["TopicFilter1"],
|
||||||
UserProperties = [new MqttUserProperty("Foo", "Bar")]
|
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))]
|
||||||
};
|
};
|
||||||
|
|
||||||
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V500);
|
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V500);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>default</LangVersion>
|
<LangVersion>default</LangVersion>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<NoWarn>$(NoWarn);CA1707</NoWarn>
|
<NoWarn>$(NoWarn);CA1707</NoWarn>
|
||||||
|
<EnableMSTestRunner>true</EnableMSTestRunner>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
<PackageReference Include="MSTest" Version="4.0.2" />
|
||||||
<PackageReference Include="MSTest" Version="4.0.1" />
|
|
||||||
|
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -25,4 +23,10 @@
|
|||||||
<ProjectReference Include="..\MQTTnet.Extensions.TopicTemplate\MQTTnet.Extensions.TopicTemplate.csproj" />
|
<ProjectReference Include="..\MQTTnet.Extensions.TopicTemplate\MQTTnet.Extensions.TopicTemplate.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include=".\..\..\global.json"
|
||||||
|
Link="global.json"
|
||||||
|
CopyToOutputDirectory="PreserveNewest"/>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.IO;
|
using Microsoft.IO;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
@@ -64,8 +65,8 @@ public sealed class Client_Tests : BaseTestClass
|
|||||||
await client.PublishAsync(
|
await client.PublishAsync(
|
||||||
new MqttApplicationMessageBuilder().WithTopic("a")
|
new MqttApplicationMessageBuilder().WithTopic("a")
|
||||||
.WithPayload("x")
|
.WithPayload("x")
|
||||||
.WithUserProperty("a", "1")
|
.WithUserProperty("a", Encoding.UTF8.GetBytes("1"))
|
||||||
.WithUserProperty("b", "2")
|
.WithUserProperty("b", Encoding.UTF8.GetBytes("2"))
|
||||||
.WithPayloadFormatIndicator(MqttPayloadFormatIndicator.CharacterData)
|
.WithPayloadFormatIndicator(MqttPayloadFormatIndicator.CharacterData)
|
||||||
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
|
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
|
||||||
.Build());
|
.Build());
|
||||||
@@ -98,8 +99,8 @@ public sealed class Client_Tests : BaseTestClass
|
|||||||
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
||||||
.WithPayload("World")
|
.WithPayload("World")
|
||||||
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
.WithUserProperty("x", "1")
|
.WithUserProperty("x", Encoding.UTF8.GetBytes("1"))
|
||||||
.WithUserProperty("y", "2")
|
.WithUserProperty("y", Encoding.UTF8.GetBytes("2"))
|
||||||
.WithResponseTopic("response")
|
.WithResponseTopic("response")
|
||||||
.WithContentType("text")
|
.WithContentType("text")
|
||||||
.WithMessageExpiryInterval(50)
|
.WithMessageExpiryInterval(50)
|
||||||
@@ -214,8 +215,8 @@ public sealed class Client_Tests : BaseTestClass
|
|||||||
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
||||||
.WithPayload("World")
|
.WithPayload("World")
|
||||||
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
.WithUserProperty("x", "1")
|
.WithUserProperty("x", Encoding.UTF8.GetBytes("1"))
|
||||||
.WithUserProperty("y", "2")
|
.WithUserProperty("y", Encoding.UTF8.GetBytes("2"))
|
||||||
.WithResponseTopic("response")
|
.WithResponseTopic("response")
|
||||||
.WithContentType("text")
|
.WithContentType("text")
|
||||||
.WithMessageExpiryInterval(50)
|
.WithMessageExpiryInterval(50)
|
||||||
@@ -250,8 +251,8 @@ public sealed class Client_Tests : BaseTestClass
|
|||||||
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("Hello")
|
||||||
.WithPayload(memoryStream.GetReadOnlySequence())
|
.WithPayload(memoryStream.GetReadOnlySequence())
|
||||||
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
.WithUserProperty("x", "1")
|
.WithUserProperty("x", Encoding.UTF8.GetBytes("1"))
|
||||||
.WithUserProperty("y", "2")
|
.WithUserProperty("y", Encoding.UTF8.GetBytes("2"))
|
||||||
.WithResponseTopic("response")
|
.WithResponseTopic("response")
|
||||||
.WithContentType("text")
|
.WithContentType("text")
|
||||||
.WithMessageExpiryInterval(50)
|
.WithMessageExpiryInterval(50)
|
||||||
|
|||||||
@@ -2,7 +2,12 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Formatter.V5;
|
||||||
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
|
||||||
namespace MQTTnet.Tests;
|
namespace MQTTnet.Tests;
|
||||||
@@ -59,4 +64,64 @@ public sealed class MqttApplicationMessageBuilder_Tests
|
|||||||
Assert.IsTrue(message.Retain);
|
Assert.IsTrue(message.Retain);
|
||||||
Assert.AreEqual(MqttQualityOfServiceLevel.ExactlyOnce, message.QualityOfServiceLevel);
|
Assert.AreEqual(MqttQualityOfServiceLevel.ExactlyOnce, message.QualityOfServiceLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateApplicationMessage_UserProperty_ReadOnlyMemoryValue()
|
||||||
|
{
|
||||||
|
var value = "utf8";
|
||||||
|
var buffer = Encoding.UTF8.GetBytes(value);
|
||||||
|
|
||||||
|
var message = new MqttApplicationMessageBuilder().WithTopic("topic").WithUserProperty("name", buffer.AsMemory()).Build();
|
||||||
|
|
||||||
|
Assert.IsNotNull(message.UserProperties);
|
||||||
|
Assert.HasCount(1, message.UserProperties);
|
||||||
|
|
||||||
|
var userProperty = message.UserProperties[0];
|
||||||
|
CollectionAssert.AreEqual(buffer, userProperty.ValueBuffer.ToArray());
|
||||||
|
Assert.AreEqual(value, userProperty.ReadValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateApplicationMessage_UserProperty_ArraySegmentValue()
|
||||||
|
{
|
||||||
|
var buffer = Encoding.UTF8.GetBytes("segment");
|
||||||
|
var segment = new ArraySegment<byte>(buffer);
|
||||||
|
|
||||||
|
var message = new MqttApplicationMessageBuilder().WithTopic("topic").WithUserProperty("name", segment).Build();
|
||||||
|
|
||||||
|
Assert.IsNotNull(message.UserProperties);
|
||||||
|
Assert.HasCount(1, message.UserProperties);
|
||||||
|
|
||||||
|
var userProperty = message.UserProperties[0];
|
||||||
|
CollectionAssert.AreEqual(buffer, userProperty.ValueBuffer.ToArray());
|
||||||
|
Assert.AreEqual("segment", userProperty.ReadValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void WriteUserProperty_FromBinaryBuffer_EqualsStringEncoding()
|
||||||
|
{
|
||||||
|
var name = "name";
|
||||||
|
var value = "value";
|
||||||
|
var encoded = Encoding.UTF8.GetBytes(value);
|
||||||
|
|
||||||
|
var binaryWriter = new MqttBufferWriter(32, 256);
|
||||||
|
var binaryPropertiesWriter = new MqttV5PropertiesWriter(binaryWriter);
|
||||||
|
binaryPropertiesWriter.WriteUserProperties(new List<MqttUserProperty> { new(name, encoded.AsMemory()) });
|
||||||
|
|
||||||
|
var stringWriter = new MqttBufferWriter(32, 256);
|
||||||
|
var stringPropertiesWriter = new MqttV5PropertiesWriter(stringWriter);
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
stringPropertiesWriter.WriteUserProperties(new List<MqttUserProperty> { new(name, value) });
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(GetWrittenBytes(stringWriter), GetWrittenBytes(binaryWriter));
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] GetWrittenBytes(MqttBufferWriter writer)
|
||||||
|
{
|
||||||
|
var length = writer.Length;
|
||||||
|
var copy = new byte[length];
|
||||||
|
Array.Copy(writer.GetBuffer(), copy, length);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
|
||||||
namespace MQTTnet.Tests;
|
namespace MQTTnet.Tests;
|
||||||
@@ -27,7 +28,7 @@ public sealed class MqttApplicationMessageValidator_Tests
|
|||||||
public void Succeed_When_Using_UserProperties_And_MQTT_500()
|
public void Succeed_When_Using_UserProperties_And_MQTT_500()
|
||||||
{
|
{
|
||||||
MqttApplicationMessageValidator.ThrowIfNotSupported(
|
MqttApplicationMessageValidator.ThrowIfNotSupported(
|
||||||
new MqttApplicationMessageBuilder().WithTopic("A").WithUserProperty("User", "Property").Build(),
|
new MqttApplicationMessageBuilder().WithTopic("A").WithUserProperty("User", Encoding.UTF8.GetBytes("Property")).Build(),
|
||||||
MqttProtocolVersion.V500);
|
MqttProtocolVersion.V500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ public sealed class MqttApplicationMessageValidator_Tests
|
|||||||
public void Succeed_When_Using_WillUserProperties_And_MQTT_311()
|
public void Succeed_When_Using_WillUserProperties_And_MQTT_311()
|
||||||
{
|
{
|
||||||
Assert.ThrowsExactly<NotSupportedException>(() => MqttApplicationMessageValidator.ThrowIfNotSupported(
|
Assert.ThrowsExactly<NotSupportedException>(() => MqttApplicationMessageValidator.ThrowIfNotSupported(
|
||||||
new MqttApplicationMessageBuilder().WithTopic("B").WithUserProperty("User", "Property").Build(),
|
new MqttApplicationMessageBuilder().WithTopic("B").WithUserProperty("User", Encoding.UTF8.GetBytes("Property")).Build(),
|
||||||
MqttProtocolVersion.V311));
|
MqttProtocolVersion.V311));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
|
||||||
namespace MQTTnet.Tests;
|
namespace MQTTnet.Tests;
|
||||||
@@ -13,27 +14,27 @@ public sealed class MqttClientOptionsValidator_Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Succeed_When_Using_UserProperties_And_MQTT_500()
|
public void Succeed_When_Using_UserProperties_And_MQTT_500()
|
||||||
{
|
{
|
||||||
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithUserProperty("User", "Property").WithTcpServer("FAKE").Build();
|
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithUserProperty("User", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Succeed_When_Using_WillUserProperties_And_MQTT_311()
|
public void Succeed_When_Using_WillUserProperties_And_MQTT_311()
|
||||||
{
|
{
|
||||||
Assert.ThrowsExactly<NotSupportedException>(() =>
|
Assert.ThrowsExactly<NotSupportedException>(() =>
|
||||||
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithWillUserProperty("User", "Property").WithTcpServer("FAKE").Build());
|
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithWillUserProperty("User", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Succeed_When_Using_WillUserProperties_And_MQTT_500()
|
public void Succeed_When_Using_WillUserProperties_And_MQTT_500()
|
||||||
{
|
{
|
||||||
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithWillUserProperty("User", "Property").WithTcpServer("FAKE").Build();
|
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithWillUserProperty("User", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Throw_When_Using_UserProperties_And_MQTT_311()
|
public void Throw_When_Using_UserProperties_And_MQTT_311()
|
||||||
{
|
{
|
||||||
Assert.ThrowsExactly<NotSupportedException>(() =>
|
Assert.ThrowsExactly<NotSupportedException>(() =>
|
||||||
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithUserProperty("User", "Property").WithTcpServer("FAKE").Build());
|
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithUserProperty("User", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ public class MqttTcpChannel_Tests
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 50001));
|
serverSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||||
|
var serverPort = ((IPEndPoint)serverSocket.LocalEndPoint).Port;
|
||||||
serverSocket.Listen(0);
|
serverSocket.Listen(0);
|
||||||
|
|
||||||
#pragma warning disable 4014
|
#pragma warning disable 4014
|
||||||
@@ -37,7 +38,7 @@ public class MqttTcpChannel_Tests
|
|||||||
},
|
},
|
||||||
ct.Token);
|
ct.Token);
|
||||||
|
|
||||||
var remoteEndPoint = new DnsEndPoint("localhost", 50001);
|
var remoteEndPoint = new DnsEndPoint("localhost", serverPort);
|
||||||
using var clientSocket = new CrossPlatformSocket(AddressFamily.InterNetwork, ProtocolType.Tcp);
|
using var clientSocket = new CrossPlatformSocket(AddressFamily.InterNetwork, ProtocolType.Tcp);
|
||||||
await clientSocket.ConnectAsync(remoteEndPoint, CancellationToken.None);
|
await clientSocket.ConnectAsync(remoteEndPoint, CancellationToken.None);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public sealed class Cross_Version_Tests : BaseTestClass
|
|||||||
|
|
||||||
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("My/Message")
|
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("My/Message")
|
||||||
.WithPayload("My_Payload")
|
.WithPayload("My_Payload")
|
||||||
.WithUserProperty("A", "B")
|
.WithUserProperty("A", Encoding.UTF8.GetBytes("B"))
|
||||||
.WithResponseTopic("Response")
|
.WithResponseTopic("Response")
|
||||||
.WithCorrelationData(Encoding.UTF8.GetBytes("Correlation"))
|
.WithCorrelationData(Encoding.UTF8.GetBytes("Correlation"))
|
||||||
.Build();
|
.Build();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
@@ -26,6 +27,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
using var client01 = new ClientTestHarness();
|
using var client01 = new ClientTestHarness();
|
||||||
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
||||||
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
||||||
|
client01.SetServerPort(server.EncryptedPort);
|
||||||
|
|
||||||
await server.StartServer();
|
await server.StartServer();
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
using var client01 = new ClientTestHarness();
|
using var client01 = new ClientTestHarness();
|
||||||
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
||||||
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
||||||
|
client01.SetServerPort(server.EncryptedPort);
|
||||||
|
|
||||||
await server.StartServer();
|
await server.StartServer();
|
||||||
|
|
||||||
@@ -70,6 +73,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
using var client01 = new ClientTestHarness();
|
using var client01 = new ClientTestHarness();
|
||||||
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
||||||
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
||||||
|
client01.SetServerPort(server.EncryptedPort);
|
||||||
|
|
||||||
await server.StartServer();
|
await server.StartServer();
|
||||||
await client01.Connect();
|
await client01.Connect();
|
||||||
@@ -91,6 +95,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
using var client01 = new ClientTestHarness();
|
using var client01 = new ClientTestHarness();
|
||||||
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
server.InstallNewClientCert(client01.GetCurrentClientCert());
|
||||||
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
client01.InstallNewServerCert(server.GetCurrentServerCert());
|
||||||
|
client01.SetServerPort(server.EncryptedPort);
|
||||||
|
|
||||||
await server.StartServer();
|
await server.StartServer();
|
||||||
await client01.Connect();
|
await client01.Connect();
|
||||||
@@ -122,10 +127,12 @@ public sealed class HotSwapCerts_Tests
|
|||||||
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
|
|
||||||
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
||||||
|
#pragma warning disable SYSLIB0057
|
||||||
var pfxCertificate = new X509Certificate2(
|
var pfxCertificate = new X509Certificate2(
|
||||||
certificate.Export(X509ContentType.Pfx),
|
certificate.Export(X509ContentType.Pfx),
|
||||||
(string)null,
|
(string)null,
|
||||||
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
||||||
|
#pragma warning restore SYSLIB0057
|
||||||
|
|
||||||
return pfxCertificate;
|
return pfxCertificate;
|
||||||
}
|
}
|
||||||
@@ -133,10 +140,11 @@ public sealed class HotSwapCerts_Tests
|
|||||||
sealed class ClientTestHarness : IDisposable
|
sealed class ClientTestHarness : IDisposable
|
||||||
{
|
{
|
||||||
readonly HotSwappableClientCertProvider _hotSwapClient = new HotSwappableClientCertProvider();
|
readonly HotSwappableClientCertProvider _hotSwapClient = new HotSwappableClientCertProvider();
|
||||||
|
int _serverPort = 8883;
|
||||||
|
|
||||||
IMqttClient _client;
|
IMqttClient _client;
|
||||||
|
|
||||||
public string ClientId => _client.Options.ClientId;
|
public string ClientId => _client?.Options?.ClientId;
|
||||||
|
|
||||||
public Task Connect()
|
public Task Connect()
|
||||||
{
|
{
|
||||||
@@ -145,10 +153,15 @@ public sealed class HotSwapCerts_Tests
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_client.Dispose();
|
_client?.Dispose();
|
||||||
_hotSwapClient.Dispose();
|
_hotSwapClient.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetServerPort(int port)
|
||||||
|
{
|
||||||
|
_serverPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
public X509Certificate2 GetCurrentClientCert()
|
public X509Certificate2 GetCurrentClientCert()
|
||||||
{
|
{
|
||||||
var result = _hotSwapClient.GetCertificates()[0];
|
var result = _hotSwapClient.GetCertificates()[0];
|
||||||
@@ -214,7 +227,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
o => o.WithClientCertificatesProvider(_hotSwapClient)
|
o => o.WithClientCertificatesProvider(_hotSwapClient)
|
||||||
.WithCertificateValidationHandler(_hotSwapClient.OnCertificateValidation)
|
.WithCertificateValidationHandler(_hotSwapClient.OnCertificateValidation)
|
||||||
.WithSslProtocols(SslProtocols.Tls12))
|
.WithSslProtocols(SslProtocols.Tls12))
|
||||||
.WithTcpServer("localhost")
|
.WithTcpServer("localhost", _serverPort)
|
||||||
.WithCleanSession()
|
.WithCleanSession()
|
||||||
.WithProtocolVersion(MqttProtocolVersion.V500);
|
.WithProtocolVersion(MqttProtocolVersion.V500);
|
||||||
|
|
||||||
@@ -240,6 +253,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
sealed class ServerTestHarness : IDisposable
|
sealed class ServerTestHarness : IDisposable
|
||||||
{
|
{
|
||||||
readonly HotSwappableServerCertProvider _hotSwapServer = new HotSwappableServerCertProvider();
|
readonly HotSwappableServerCertProvider _hotSwapServer = new HotSwappableServerCertProvider();
|
||||||
|
readonly int _encryptedPort = GetFreeTcpPort();
|
||||||
|
|
||||||
MqttServer _server;
|
MqttServer _server;
|
||||||
|
|
||||||
@@ -259,6 +273,8 @@ public sealed class HotSwapCerts_Tests
|
|||||||
return _server.DisconnectClientAsync(client.ClientId, MqttDisconnectReasonCode.UnspecifiedError);
|
return _server.DisconnectClientAsync(client.ClientId, MqttDisconnectReasonCode.UnspecifiedError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int EncryptedPort => _encryptedPort;
|
||||||
|
|
||||||
public X509Certificate2 GetCurrentServerCert()
|
public X509Certificate2 GetCurrentServerCert()
|
||||||
{
|
{
|
||||||
return _hotSwapServer.GetCertificate();
|
return _hotSwapServer.GetCertificate();
|
||||||
@@ -279,6 +295,7 @@ public sealed class HotSwapCerts_Tests
|
|||||||
var mqttServerFactory = new MqttServerFactory();
|
var mqttServerFactory = new MqttServerFactory();
|
||||||
|
|
||||||
var mqttServerOptions = new MqttServerOptionsBuilder().WithEncryptionCertificate(_hotSwapServer)
|
var mqttServerOptions = new MqttServerOptionsBuilder().WithEncryptionCertificate(_hotSwapServer)
|
||||||
|
.WithEncryptedEndpointPort(_encryptedPort)
|
||||||
.WithRemoteCertificateValidationCallback(_hotSwapServer.RemoteCertificateValidationCallback)
|
.WithRemoteCertificateValidationCallback(_hotSwapServer.RemoteCertificateValidationCallback)
|
||||||
.WithEncryptedEndpoint()
|
.WithEncryptedEndpoint()
|
||||||
.Build();
|
.Build();
|
||||||
@@ -288,6 +305,17 @@ public sealed class HotSwapCerts_Tests
|
|||||||
_server = mqttServerFactory.CreateMqttServer(mqttServerOptions);
|
_server = mqttServerFactory.CreateMqttServer(mqttServerOptions);
|
||||||
return _server.StartAsync();
|
return _server.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetFreeTcpPort()
|
||||||
|
{
|
||||||
|
var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||||
|
listener.Start();
|
||||||
|
|
||||||
|
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||||
|
listener.Stop();
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class HotSwappableClientCertProvider : IMqttClientCertificatesProvider, IDisposable
|
sealed class HotSwappableClientCertProvider : IMqttClientCertificatesProvider, IDisposable
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
@@ -98,7 +99,7 @@ public sealed class Subscribe_Tests : BaseTestClass
|
|||||||
|
|
||||||
var client = await testEnvironment.ConnectClient();
|
var client = await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
var subscribeOptions = testEnvironment.ClientFactory.CreateSubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
|
var subscribeOptions = testEnvironment.ClientFactory.CreateSubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", Encoding.UTF8.GetBytes("1")).Build();
|
||||||
await client.SubscribeAsync(subscribeOptions);
|
await client.SubscribeAsync(subscribeOptions);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(subscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
|
CollectionAssert.AreEqual(subscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
@@ -520,10 +521,11 @@ public sealed class SubscriptionTopicHashTests : IDisposable
|
|||||||
static byte[] GetBytes(ulong value)
|
static byte[] GetBytes(ulong value)
|
||||||
{
|
{
|
||||||
var bytes = BitConverter.GetBytes(value);
|
var bytes = BitConverter.GetBytes(value);
|
||||||
|
|
||||||
// Ensure that highest byte comes first for comparison left to right
|
// Ensure that highest byte comes first for comparison left to right
|
||||||
if (BitConverter.IsLittleEndian)
|
if (BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
return bytes.Reverse().ToArray();
|
bytes = bytes.AsEnumerable().Reverse().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|||||||
@@ -31,10 +31,12 @@ public sealed class Tls_Tests : BaseTestClass
|
|||||||
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
|
|
||||||
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
using var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
||||||
|
#pragma warning disable SYSLIB0057
|
||||||
var pfxCertificate = new X509Certificate2(
|
var pfxCertificate = new X509Certificate2(
|
||||||
certificate.Export(X509ContentType.Pfx),
|
certificate.Export(X509ContentType.Pfx),
|
||||||
(string)null,
|
(string)null,
|
||||||
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
||||||
|
#pragma warning restore SYSLIB0057
|
||||||
|
|
||||||
return pfxCertificate;
|
return pfxCertificate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
@@ -45,7 +46,7 @@ public sealed class Unsubscribe_Tests : BaseTestClass
|
|||||||
|
|
||||||
var client = await testEnvironment.ConnectClient();
|
var client = await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
var unsubscribeOptions = testEnvironment.ClientFactory.CreateUnsubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
|
var unsubscribeOptions = testEnvironment.ClientFactory.CreateUnsubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", Encoding.UTF8.GetBytes("1")).Build();
|
||||||
await client.UnsubscribeAsync(unsubscribeOptions);
|
await client.UnsubscribeAsync(unsubscribeOptions);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(unsubscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
|
CollectionAssert.AreEqual(unsubscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
@@ -26,10 +27,10 @@ public class Feature_Tests
|
|||||||
|
|
||||||
var message = new MqttApplicationMessageBuilder()
|
var message = new MqttApplicationMessageBuilder()
|
||||||
.WithTopic("A")
|
.WithTopic("A")
|
||||||
.WithUserProperty("x", "1")
|
.WithUserProperty("x", Encoding.UTF8.GetBytes("1"))
|
||||||
.WithUserProperty("y", "2")
|
.WithUserProperty("y", Encoding.UTF8.GetBytes("2"))
|
||||||
.WithUserProperty("z", "3")
|
.WithUserProperty("z", Encoding.UTF8.GetBytes("3"))
|
||||||
.WithUserProperty("z", "4"); // z is here two times to test list of items
|
.WithUserProperty("z", Encoding.UTF8.GetBytes("4")); // z is here two times to test list of items
|
||||||
|
|
||||||
await receiver.SubscribeAsync(new MqttClientSubscribeOptions
|
await receiver.SubscribeAsync(new MqttClientSubscribeOptions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,17 @@ public class BlobCertificateProvider(byte[] blob) : ICertificateProvider
|
|||||||
|
|
||||||
public X509Certificate2 GetCertificate()
|
public X509Certificate2 GetCertificate()
|
||||||
{
|
{
|
||||||
|
#if NET10_0_OR_GREATER
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Password))
|
||||||
|
{
|
||||||
|
return X509CertificateLoader.LoadCertificate(Blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return X509CertificateLoader.LoadPkcs12(Blob, Password);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Password))
|
if (string.IsNullOrEmpty(Password))
|
||||||
{
|
{
|
||||||
// Use a different overload when no password is specified. Otherwise, the constructor will fail.
|
// Use a different overload when no password is specified. Otherwise, the constructor will fail.
|
||||||
@@ -21,5 +32,7 @@ public class BlobCertificateProvider(byte[] blob) : ICertificateProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new X509Certificate2(Blob, Password);
|
return new X509Certificate2(Blob, Password);
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ public static class MqttClientConnectResultFactory
|
|||||||
RetainAvailable = connAckPacket.RetainAvailable,
|
RetainAvailable = connAckPacket.RetainAvailable,
|
||||||
AssignedClientIdentifier = connAckPacket.AssignedClientIdentifier,
|
AssignedClientIdentifier = connAckPacket.AssignedClientIdentifier,
|
||||||
AuthenticationMethod = connAckPacket.AuthenticationMethod,
|
AuthenticationMethod = connAckPacket.AuthenticationMethod,
|
||||||
AuthenticationData = connAckPacket.AuthenticationData.ToArray(),
|
AuthenticationData = connAckPacket.AuthenticationData,
|
||||||
MaximumPacketSize = connAckPacket.MaximumPacketSize,
|
MaximumPacketSize = connAckPacket.MaximumPacketSize,
|
||||||
ReasonString = connAckPacket.ReasonString,
|
ReasonString = connAckPacket.ReasonString,
|
||||||
ReceiveMaximum = connAckPacket.ReceiveMaximum,
|
ReceiveMaximum = connAckPacket.ReceiveMaximum,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
namespace MQTTnet;
|
namespace MQTTnet;
|
||||||
@@ -48,10 +49,25 @@ public sealed class MqttClientDisconnectOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance `WithUserProperty` with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public MqttClientDisconnectOptionsBuilder WithUserProperty(string name, string value)
|
public MqttClientDisconnectOptionsBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
_userProperties ??= [];
|
_userProperties ??= [];
|
||||||
_userProperties.Add(new MqttUserProperty(name, value));
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttClientDisconnectOptionsBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
_userProperties ??= [];
|
||||||
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientDisconnectOptionsBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
_userProperties ??= [];
|
||||||
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public static class MqttApplicationMessageFactory
|
|||||||
Dup = publishPacket.Dup,
|
Dup = publishPacket.Dup,
|
||||||
ResponseTopic = publishPacket.ResponseTopic,
|
ResponseTopic = publishPacket.ResponseTopic,
|
||||||
ContentType = publishPacket.ContentType,
|
ContentType = publishPacket.ContentType,
|
||||||
CorrelationData = publishPacket.CorrelationData.ToArray(),
|
CorrelationData = publishPacket.CorrelationData,
|
||||||
MessageExpiryInterval = publishPacket.MessageExpiryInterval,
|
MessageExpiryInterval = publishPacket.MessageExpiryInterval,
|
||||||
SubscriptionIdentifiers = publishPacket.SubscriptionIdentifiers,
|
SubscriptionIdentifiers = publishPacket.SubscriptionIdentifiers,
|
||||||
TopicAlias = publishPacket.TopicAlias,
|
TopicAlias = publishPacket.TopicAlias,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public sealed class MqttBufferReader
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> ReadRemainingData()
|
public byte[] ReadRemainingData()
|
||||||
{
|
{
|
||||||
var bufferLength = BytesLeft;
|
var bufferLength = BytesLeft;
|
||||||
if (bufferLength == 0)
|
if (bufferLength == 0)
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
using System;
|
||||||
using System.Buffers.Binary;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
@@ -110,47 +109,31 @@ public sealed class MqttBufferWriter
|
|||||||
WriteBinary(propertyWriter._buffer, 0, propertyWriter.Length);
|
WriteBinary(propertyWriter._buffer, 0, propertyWriter.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteBinary(ReadOnlySequence<byte> value)
|
public void WriteBinary(byte[] value)
|
||||||
{
|
{
|
||||||
if (value.IsEmpty)
|
if (value == null || value.Length == 0)
|
||||||
{
|
{
|
||||||
WriteEmptyBinary();
|
EnsureAdditionalCapacity(2);
|
||||||
return;
|
|
||||||
|
_buffer[_position] = 0;
|
||||||
|
_buffer[_position + 1] = 0;
|
||||||
|
|
||||||
|
IncreasePosition(2);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
EnsureAdditionalCapacity(value.Length + 2);
|
|
||||||
|
|
||||||
_buffer[_position] = (byte)(value.Length >> 8);
|
|
||||||
_buffer[_position + 1] = (byte)value.Length;
|
|
||||||
|
|
||||||
Advance(2);
|
|
||||||
|
|
||||||
foreach (var segment in value)
|
|
||||||
{
|
{
|
||||||
MqttMemoryHelper.Copy(segment, 0, _buffer, _position + 2, segment.Length);
|
var valueLength = value.Length;
|
||||||
Advance(segment.Length);
|
|
||||||
|
EnsureAdditionalCapacity(valueLength + 2);
|
||||||
|
|
||||||
|
_buffer[_position] = (byte)(valueLength >> 8);
|
||||||
|
_buffer[_position + 1] = (byte)valueLength;
|
||||||
|
|
||||||
|
MqttMemoryHelper.Copy(value, 0, _buffer, _position + 2, valueLength);
|
||||||
|
IncreasePosition(valueLength + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteBinary(ReadOnlyMemory<byte> value)
|
|
||||||
{
|
|
||||||
if (value.Length == 0)
|
|
||||||
{
|
|
||||||
WriteEmptyBinary();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnsureAdditionalCapacity(value.Length + 2);
|
|
||||||
|
|
||||||
_buffer[_position] = (byte)(value.Length >> 8);
|
|
||||||
_buffer[_position + 1] = (byte)value.Length;
|
|
||||||
|
|
||||||
Advance(2);
|
|
||||||
|
|
||||||
MqttMemoryHelper.Copy(value, 0, _buffer, _position + 2, (int)value.Length);
|
|
||||||
Advance(value.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteBinary(byte[] buffer, int offset, int count)
|
public void WriteBinary(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(buffer);
|
ArgumentNullException.ThrowIfNull(buffer);
|
||||||
@@ -163,7 +146,15 @@ public sealed class MqttBufferWriter
|
|||||||
EnsureAdditionalCapacity(count);
|
EnsureAdditionalCapacity(count);
|
||||||
|
|
||||||
MqttMemoryHelper.Copy(buffer, offset, _buffer, _position, count);
|
MqttMemoryHelper.Copy(buffer, offset, _buffer, _position, count);
|
||||||
Advance(count);
|
IncreasePosition(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteByte(byte @byte)
|
||||||
|
{
|
||||||
|
EnsureAdditionalCapacity(1);
|
||||||
|
|
||||||
|
_buffer[_position] = @byte;
|
||||||
|
IncreasePosition(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteString(string value)
|
public void WriteString(string value)
|
||||||
@@ -175,7 +166,7 @@ public sealed class MqttBufferWriter
|
|||||||
_buffer[_position] = 0;
|
_buffer[_position] = 0;
|
||||||
_buffer[_position + 1] = 0;
|
_buffer[_position + 1] = 0;
|
||||||
|
|
||||||
Advance(2);
|
IncreasePosition(2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -199,52 +190,49 @@ public sealed class MqttBufferWriter
|
|||||||
_buffer[_position] = (byte)(writtenBytes >> 8);
|
_buffer[_position] = (byte)(writtenBytes >> 8);
|
||||||
_buffer[_position + 1] = (byte)writtenBytes;
|
_buffer[_position + 1] = (byte)writtenBytes;
|
||||||
|
|
||||||
Advance(writtenBytes + 2);
|
IncreasePosition(writtenBytes + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteByte(byte @byte)
|
public void WriteString(ReadOnlyMemory<byte> value)
|
||||||
{
|
{
|
||||||
const int size = sizeof(byte);
|
var span = value.Span;
|
||||||
var span = GetSpan(size);
|
var length = span.Length;
|
||||||
|
|
||||||
span[0] = @byte;
|
if (length > EncodedStringMaxLength)
|
||||||
Advance(size);
|
{
|
||||||
|
throw new MqttProtocolViolationException($"The maximum string length is 65535. The current string has a length of {length}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureAdditionalCapacity(length + 2);
|
||||||
|
|
||||||
|
_buffer[_position] = (byte)(length >> 8);
|
||||||
|
_buffer[_position + 1] = (byte)length;
|
||||||
|
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
span.CopyTo(_buffer.AsSpan(_position + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
IncreasePosition(length + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteTwoByteInteger(ushort value)
|
public void WriteTwoByteInteger(ushort value)
|
||||||
{
|
{
|
||||||
const int size = sizeof(ushort);
|
EnsureAdditionalCapacity(2);
|
||||||
var span = GetSpan(size);
|
|
||||||
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(span, value);
|
_buffer[_position] = (byte)(value >> 8);
|
||||||
|
IncreasePosition(1);
|
||||||
Advance(size);
|
_buffer[_position] = (byte)value;
|
||||||
|
IncreasePosition(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
Span<byte> GetSpan(int size)
|
|
||||||
{
|
|
||||||
var freeSpace = _buffer.Length - _position;
|
|
||||||
if (freeSpace < size)
|
|
||||||
{
|
|
||||||
EnsureCapacity(_buffer.Length + size - freeSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _buffer.AsSpan(_position, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void WriteVariableByteInteger(uint value)
|
public void WriteVariableByteInteger(uint value)
|
||||||
{
|
{
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
{
|
{
|
||||||
_buffer[_position] = 0;
|
_buffer[_position] = 0;
|
||||||
Advance(1);
|
IncreasePosition(1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -252,7 +240,7 @@ public sealed class MqttBufferWriter
|
|||||||
if (value <= 127)
|
if (value <= 127)
|
||||||
{
|
{
|
||||||
_buffer[_position] = (byte)value;
|
_buffer[_position] = (byte)value;
|
||||||
Advance(1);
|
IncreasePosition(1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -274,11 +262,11 @@ public sealed class MqttBufferWriter
|
|||||||
size++;
|
size++;
|
||||||
} while (x > 0);
|
} while (x > 0);
|
||||||
|
|
||||||
Advance(size);
|
IncreasePosition(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void EnsureAdditionalCapacity(long additionalCapacity)
|
void EnsureAdditionalCapacity(int additionalCapacity)
|
||||||
{
|
{
|
||||||
var bufferLength = _buffer.Length;
|
var bufferLength = _buffer.Length;
|
||||||
|
|
||||||
@@ -292,7 +280,7 @@ public sealed class MqttBufferWriter
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void EnsureCapacity(long capacity)
|
void EnsureCapacity(int capacity)
|
||||||
{
|
{
|
||||||
var newBufferLength = _buffer.Length;
|
var newBufferLength = _buffer.Length;
|
||||||
|
|
||||||
@@ -311,7 +299,7 @@ public sealed class MqttBufferWriter
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void Advance(int length)
|
void IncreasePosition(int length)
|
||||||
{
|
{
|
||||||
_position += length;
|
_position += length;
|
||||||
|
|
||||||
@@ -322,14 +310,4 @@ public sealed class MqttBufferWriter
|
|||||||
Length = _position;
|
Length = _position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteEmptyBinary()
|
|
||||||
{
|
|
||||||
EnsureAdditionalCapacity(2);
|
|
||||||
|
|
||||||
_buffer[_position] = 0;
|
|
||||||
_buffer[_position + 1] = 0;
|
|
||||||
|
|
||||||
Advance(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
namespace MQTTnet.Formatter;
|
namespace MQTTnet.Formatter;
|
||||||
@@ -41,7 +40,7 @@ public static class MqttConnectPacketFactory
|
|||||||
connectPacket.WillFlag = true;
|
connectPacket.WillFlag = true;
|
||||||
connectPacket.WillTopic = clientOptions.WillTopic;
|
connectPacket.WillTopic = clientOptions.WillTopic;
|
||||||
connectPacket.WillQoS = clientOptions.WillQualityOfServiceLevel;
|
connectPacket.WillQoS = clientOptions.WillQualityOfServiceLevel;
|
||||||
connectPacket.WillMessage = new ReadOnlySequence<byte>(clientOptions.WillPayload);
|
connectPacket.WillMessage = clientOptions.WillPayload;
|
||||||
connectPacket.WillRetain = clientOptions.WillRetain;
|
connectPacket.WillRetain = clientOptions.WillRetain;
|
||||||
connectPacket.WillDelayInterval = clientOptions.WillDelayInterval;
|
connectPacket.WillDelayInterval = clientOptions.WillDelayInterval;
|
||||||
connectPacket.WillContentType = clientOptions.WillContentType;
|
connectPacket.WillContentType = clientOptions.WillContentType;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
packet.WillRetain = willRetain;
|
packet.WillRetain = willRetain;
|
||||||
|
|
||||||
packet.WillTopic = _bufferReader.ReadString();
|
packet.WillTopic = _bufferReader.ReadString();
|
||||||
packet.WillMessage = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
|
packet.WillMessage = _bufferReader.ReadBinaryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usernameFlag)
|
if (usernameFlag)
|
||||||
@@ -271,7 +271,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
|
|
||||||
if (!_bufferReader.EndOfStream)
|
if (!_bufferReader.EndOfStream)
|
||||||
{
|
{
|
||||||
packet.Payload = new ReadOnlySequence<byte>(_bufferReader.ReadRemainingData());
|
packet.PayloadSegment = new ArraySegment<byte>(_bufferReader.ReadRemainingData());
|
||||||
}
|
}
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
@@ -430,12 +430,12 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0 && packet.Username == null)
|
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].");
|
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.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
connectFlags |= 0x40;
|
connectFlags |= 0x40;
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
bufferWriter.WriteString(packet.Username);
|
bufferWriter.WriteString(packet.Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
bufferWriter.WriteBinary(packet.Password);
|
bufferWriter.WriteBinary(packet.Password);
|
||||||
}
|
}
|
||||||
@@ -501,12 +501,12 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0 && packet.Username == null)
|
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].");
|
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.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
connectFlags |= 0x40;
|
connectFlags |= 0x40;
|
||||||
}
|
}
|
||||||
@@ -531,7 +531,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
|
|||||||
bufferWriter.WriteString(packet.Username);
|
bufferWriter.WriteString(packet.Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
bufferWriter.WriteBinary(packet.Password);
|
bufferWriter.WriteBinary(packet.Password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
@@ -315,7 +314,7 @@ public sealed class MqttV5PacketDecoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
packet.WillTopic = _bufferReader.ReadString();
|
packet.WillTopic = _bufferReader.ReadString();
|
||||||
packet.WillMessage = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
|
packet.WillMessage = _bufferReader.ReadBinaryData();
|
||||||
packet.WillUserProperties = willPropertiesReader.CollectedUserProperties;
|
packet.WillUserProperties = willPropertiesReader.CollectedUserProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +521,7 @@ public sealed class MqttV5PacketDecoder
|
|||||||
|
|
||||||
if (!_bufferReader.EndOfStream)
|
if (!_bufferReader.EndOfStream)
|
||||||
{
|
{
|
||||||
packet.Payload = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
|
packet.PayloadSegment = new ArraySegment<byte>(_bufferReader.ReadRemainingData());
|
||||||
}
|
}
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
|
|||||||
@@ -138,12 +138,12 @@ public sealed class MqttV5PacketEncoder(MqttBufferWriter bufferWriter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0 && packet.Username == null)
|
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].");
|
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.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
connectFlags |= 0x40;
|
connectFlags |= 0x40;
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ public sealed class MqttV5PacketEncoder(MqttBufferWriter bufferWriter)
|
|||||||
_bufferWriter.WriteString(packet.Username);
|
_bufferWriter.WriteString(packet.Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.Password.Length > 0)
|
if (packet.Password != null)
|
||||||
{
|
{
|
||||||
_bufferWriter.WriteBinary(packet.Password);
|
_bufferWriter.WriteBinary(packet.Password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
@@ -59,14 +60,14 @@ public struct MqttV5PropertiesReader
|
|||||||
if (CurrentPropertyId == MqttPropertyId.UserProperty)
|
if (CurrentPropertyId == MqttPropertyId.UserProperty)
|
||||||
{
|
{
|
||||||
var name = _body.ReadString();
|
var name = _body.ReadString();
|
||||||
var value = _body.ReadString();
|
var valueBuffer = ReadUserPropertyValueBuffer();
|
||||||
|
|
||||||
if (CollectedUserProperties == null)
|
if (CollectedUserProperties == null)
|
||||||
{
|
{
|
||||||
CollectedUserProperties = new List<MqttUserProperty>();
|
CollectedUserProperties = new List<MqttUserProperty>();
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectedUserProperties.Add(new MqttUserProperty(name, value));
|
CollectedUserProperties.Add(new MqttUserProperty(name, valueBuffer));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +191,11 @@ public struct MqttV5PropertiesReader
|
|||||||
return _body.ReadTwoByteInteger();
|
return _body.ReadTwoByteInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReadOnlyMemory<byte> ReadUserPropertyValueBuffer()
|
||||||
|
{
|
||||||
|
return _body.ReadBinaryData();
|
||||||
|
}
|
||||||
|
|
||||||
public bool ReadWildcardSubscriptionAvailable()
|
public bool ReadWildcardSubscriptionAvailable()
|
||||||
{
|
{
|
||||||
return _body.ReadByte() == 1;
|
return _body.ReadByte() == 1;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public sealed class MqttV5PropertiesWriter
|
|||||||
Write(MqttPropertyId.AssignedClientIdentifier, value);
|
Write(MqttPropertyId.AssignedClientIdentifier, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteAuthenticationData(ReadOnlyMemory<byte> value)
|
public void WriteAuthenticationData(byte[] value)
|
||||||
{
|
{
|
||||||
Write(MqttPropertyId.AuthenticationData, value);
|
Write(MqttPropertyId.AuthenticationData, value);
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ public sealed class MqttV5PropertiesWriter
|
|||||||
Write(MqttPropertyId.ContentType, value);
|
Write(MqttPropertyId.ContentType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteCorrelationData(ReadOnlyMemory<byte> value)
|
public void WriteCorrelationData(byte[] value)
|
||||||
{
|
{
|
||||||
Write(MqttPropertyId.CorrelationData, value);
|
Write(MqttPropertyId.CorrelationData, value);
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ public sealed class MqttV5PropertiesWriter
|
|||||||
{
|
{
|
||||||
_bufferWriter.WriteByte((byte)MqttPropertyId.UserProperty);
|
_bufferWriter.WriteByte((byte)MqttPropertyId.UserProperty);
|
||||||
_bufferWriter.WriteString(property.Name);
|
_bufferWriter.WriteString(property.Name);
|
||||||
_bufferWriter.WriteString(property.Value);
|
_bufferWriter.WriteString(property.ValueBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,9 +315,9 @@ public sealed class MqttV5PropertiesWriter
|
|||||||
_bufferWriter.WriteString(value);
|
_bufferWriter.WriteString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(MqttPropertyId id, ReadOnlyMemory<byte> value)
|
void Write(MqttPropertyId id, byte[] value)
|
||||||
{
|
{
|
||||||
if (value.Length == 0)
|
if (value == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@
|
|||||||
<DebugType>Full</DebugType>
|
<DebugType>Full</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -263,10 +264,33 @@ public sealed class MqttApplicationMessageBuilder
|
|||||||
/// Adds the user property to the message.
|
/// Adds the user property to the message.
|
||||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Use the WithUserProperty accepting a ReadOnlyMemory<byte> for better performance.")]
|
||||||
public MqttApplicationMessageBuilder WithUserProperty(string name, string value)
|
public MqttApplicationMessageBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
_userProperties ??= [];
|
_userProperties ??= [];
|
||||||
_userProperties.Add(new MqttUserProperty(name, value));
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the message using a pre-encoded UTF-8 value buffer.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttApplicationMessageBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
_userProperties ??= [];
|
||||||
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the message using a pre-encoded UTF-8 value buffer.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttApplicationMessageBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
_userProperties ??= [];
|
||||||
|
_userProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -357,6 +358,7 @@ public sealed class MqttClientOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance `WithUserProperty` with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public MqttClientOptionsBuilder WithUserProperty(string name, string value)
|
public MqttClientOptionsBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
if (_options.UserProperties == null)
|
if (_options.UserProperties == null)
|
||||||
@@ -368,6 +370,28 @@ public sealed class MqttClientOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithWebSocketServer(Action<MqttClientWebSocketOptionsBuilder> configure)
|
public MqttClientOptionsBuilder WithWebSocketServer(Action<MqttClientWebSocketOptionsBuilder> configure)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(configure);
|
ArgumentNullException.ThrowIfNull(configure);
|
||||||
@@ -462,10 +486,25 @@ public sealed class MqttClientOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance `WithWillUserProperty` with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public MqttClientOptionsBuilder WithWillUserProperty(string name, string value)
|
public MqttClientOptionsBuilder WithWillUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
_options.WillUserProperties ??= [];
|
_options.WillUserProperties ??= [];
|
||||||
_options.WillUserProperties.Add(new MqttUserProperty(name, value));
|
_options.WillUserProperties.Add(new MqttUserProperty(name, value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithWillUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
_options.WillUserProperties ??= [];
|
||||||
|
_options.WillUserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithWillUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
_options.WillUserProperties ??= [];
|
||||||
|
_options.WillUserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ public class MqttEnhancedAuthenticationEventArgs : EventArgs
|
|||||||
/// Gets the authentication data.
|
/// Gets the authentication data.
|
||||||
/// Hint: MQTT 5 feature only.
|
/// Hint: MQTT 5 feature only.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] AuthenticationData => _initialAuthPacket.AuthenticationData.ToArray();
|
public byte[] AuthenticationData => _initialAuthPacket.AuthenticationData;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authentication method.
|
/// Gets the authentication method.
|
||||||
@@ -67,7 +67,7 @@ public class MqttEnhancedAuthenticationEventArgs : EventArgs
|
|||||||
{
|
{
|
||||||
return new ReceiveMqttEnhancedAuthenticationDataResult
|
return new ReceiveMqttEnhancedAuthenticationDataResult
|
||||||
{
|
{
|
||||||
AuthenticationData = authPacket.AuthenticationData.ToArray(),
|
AuthenticationData = authPacket.AuthenticationData,
|
||||||
AuthenticationMethod = authPacket.AuthenticationMethod,
|
AuthenticationMethod = authPacket.AuthenticationMethod,
|
||||||
ReasonString = authPacket.ReasonString,
|
ReasonString = authPacket.ReasonString,
|
||||||
ReasonCode = authPacket.ReasonCode,
|
ReasonCode = authPacket.ReasonCode,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace MQTTnet.Packets;
|
|||||||
/// <summary>Added in MQTTv5.0.0.</summary>
|
/// <summary>Added in MQTTv5.0.0.</summary>
|
||||||
public sealed class MqttAuthPacket : MqttPacket
|
public sealed class MqttAuthPacket : MqttPacket
|
||||||
{
|
{
|
||||||
public ReadOnlyMemory<byte> AuthenticationData { get; set; }
|
public byte[] AuthenticationData { get; set; }
|
||||||
|
|
||||||
public string AuthenticationMethod { get; set; }
|
public string AuthenticationMethod { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public sealed class MqttConnAckPacket : MqttPacket
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string AssignedClientIdentifier { get; set; }
|
public string AssignedClientIdentifier { get; set; }
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> AuthenticationData { get; set; }
|
public byte[] AuthenticationData { get; set; }
|
||||||
|
|
||||||
public string AuthenticationMethod { get; set; }
|
public string AuthenticationMethod { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,13 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Buffers;
|
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
|
||||||
namespace MQTTnet.Packets;
|
namespace MQTTnet.Packets;
|
||||||
|
|
||||||
public sealed class MqttConnectPacket : MqttPacket
|
public sealed class MqttConnectPacket : MqttPacket
|
||||||
{
|
{
|
||||||
public ReadOnlyMemory<byte> AuthenticationData { get; set; }
|
public byte[] AuthenticationData { get; set; }
|
||||||
|
|
||||||
public string AuthenticationMethod { get; set; }
|
public string AuthenticationMethod { get; set; }
|
||||||
|
|
||||||
@@ -20,13 +19,13 @@ public sealed class MqttConnectPacket : MqttPacket
|
|||||||
|
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> WillCorrelationData { get; set; }
|
public byte[] WillCorrelationData { get; set; }
|
||||||
|
|
||||||
public ushort KeepAlivePeriod { get; set; }
|
public ushort KeepAlivePeriod { get; set; }
|
||||||
|
|
||||||
public uint MaximumPacketSize { get; set; }
|
public uint MaximumPacketSize { get; set; }
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> Password { get; set; }
|
public byte[] Password { get; set; }
|
||||||
|
|
||||||
public ushort ReceiveMaximum { get; set; }
|
public ushort ReceiveMaximum { get; set; }
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ public sealed class MqttConnectPacket : MqttPacket
|
|||||||
|
|
||||||
public bool WillFlag { get; set; }
|
public bool WillFlag { get; set; }
|
||||||
|
|
||||||
public ReadOnlySequence<byte> WillMessage { get; set; }
|
public byte[] WillMessage { get; set; }
|
||||||
|
|
||||||
public uint WillMessageExpiryInterval { get; set; }
|
public uint WillMessageExpiryInterval { get; set; }
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ public sealed class MqttConnectPacket : MqttPacket
|
|||||||
{
|
{
|
||||||
var passwordText = string.Empty;
|
var passwordText = string.Empty;
|
||||||
|
|
||||||
if (Password.Length > 0)
|
if (Password != null)
|
||||||
{
|
{
|
||||||
passwordText = "****";
|
passwordText = "****";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public sealed class MqttPublishPacket : MqttPacketWithIdentifier
|
|||||||
{
|
{
|
||||||
public string ContentType { get; set; }
|
public string ContentType { get; set; }
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> CorrelationData { get; set; }
|
public byte[] CorrelationData { get; set; }
|
||||||
|
|
||||||
public bool Dup { get; set; }
|
public bool Dup { get; set; }
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public sealed class MqttPublishPacket : MqttPacketWithIdentifier
|
|||||||
|
|
||||||
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified;
|
public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified;
|
||||||
|
|
||||||
//public ArraySegment<byte> PayloadSegment { set => Payload = new ReadOnlySequence<byte>(value); }
|
public ArraySegment<byte> PayloadSegment { set => Payload = new ReadOnlySequence<byte>(value); }
|
||||||
|
|
||||||
public ReadOnlySequence<byte> Payload { get; set; }
|
public ReadOnlySequence<byte> Payload { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,37 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MQTTnet.Packets;
|
namespace MQTTnet.Packets;
|
||||||
|
|
||||||
public sealed class MqttUserProperty
|
public sealed class MqttUserProperty
|
||||||
{
|
{
|
||||||
|
readonly ReadOnlyMemory<byte> _valueBuffer;
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance constructor with ArraySegment<byte> or ReadOnlyMemory<byte> for the value.")]
|
||||||
public MqttUserProperty(string name, string value)
|
public MqttUserProperty(string name, string value)
|
||||||
|
: this(name, new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes(value ?? throw new ArgumentNullException(nameof(value)))))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
: this(name, CreateMemory(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
{
|
{
|
||||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
Value = value ?? throw new ArgumentNullException(nameof(value));
|
_valueBuffer = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
public string Value { get; }
|
public ReadOnlyMemory<byte> ValueBuffer => _valueBuffer;
|
||||||
|
|
||||||
|
[Obsolete("Please use more performance property ValueBuffer or the MqttUserPropertyExtensionMethod `ReadValueAsString`")]
|
||||||
|
public string Value => this.ReadValueAsString();
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
@@ -33,16 +51,46 @@ public sealed class MqttUserProperty
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Equals(Name, other.Name, StringComparison.Ordinal) && string.Equals(Value, other.Value, StringComparison.Ordinal);
|
if (!string.Equals(Name, other.Name, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _valueBuffer.Span.SequenceEqual(other._valueBuffer.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return Name.GetHashCode() ^ Value.GetHashCode();
|
var hashCode = new HashCode();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Name))
|
||||||
|
{
|
||||||
|
hashCode.Add(Name, StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hashCode.Add(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashCode.AddBytes(_valueBuffer.Span);
|
||||||
|
|
||||||
|
return hashCode.ToHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Name} = {Value}";
|
return $"{Name} = {this.ReadValueAsString()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
static ReadOnlyMemory<byte> CreateMemory(ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
if (value.Array == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ReadOnlyMemory<byte>(value.Array, value.Offset, value.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MQTTnet.Packets;
|
||||||
|
|
||||||
|
public static class MqttUserPropertyExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the value of the user property as a UTF-8 string.
|
||||||
|
/// </summary>
|
||||||
|
public static string ReadValueAsString(this MqttUserProperty userProperty)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(userProperty);
|
||||||
|
|
||||||
|
var buffer = userProperty.ValueBuffer;
|
||||||
|
if (buffer.IsEmpty)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(buffer.Span);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
@@ -77,6 +78,7 @@ public sealed class MqttClientSubscribeOptionsBuilder
|
|||||||
/// Adds the user property to the subscribe options.
|
/// Adds the user property to the subscribe options.
|
||||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Use the WithUserProperty accepting a ReadOnlyMemory<byte> for better performance.")]
|
||||||
public MqttClientSubscribeOptionsBuilder WithUserProperty(string name, string value)
|
public MqttClientSubscribeOptionsBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
_subscribeOptions.UserProperties ??= [];
|
_subscribeOptions.UserProperties ??= [];
|
||||||
@@ -84,4 +86,28 @@ public sealed class MqttClientSubscribeOptionsBuilder
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the subscribe options.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttClientSubscribeOptionsBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
_subscribeOptions.UserProperties ??= [];
|
||||||
|
_subscribeOptions.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the subscribe options.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttClientSubscribeOptionsBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
_subscribeOptions.UserProperties ??= [];
|
||||||
|
_subscribeOptions.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
namespace MQTTnet;
|
namespace MQTTnet;
|
||||||
@@ -36,11 +37,30 @@ public sealed class MqttClientUnsubscribeOptionsBuilder
|
|||||||
/// Adds the user property to the unsubscribe options.
|
/// Adds the user property to the unsubscribe options.
|
||||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Use the WithUserProperty accepting a ReadOnlyMemory<byte> for better performance.")]
|
||||||
public MqttClientUnsubscribeOptionsBuilder WithUserProperty(string name, string value)
|
public MqttClientUnsubscribeOptionsBuilder WithUserProperty(string name, string value)
|
||||||
{
|
{
|
||||||
return WithUserProperty(new MqttUserProperty(name, value));
|
return WithUserProperty(new MqttUserProperty(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the unsubscribe options.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttClientUnsubscribeOptionsBuilder WithUserProperty(string name, ReadOnlyMemory<byte> value)
|
||||||
|
{
|
||||||
|
return WithUserProperty(new MqttUserProperty(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the user property to the unsubscribe options.
|
||||||
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public MqttClientUnsubscribeOptionsBuilder WithUserProperty(string name, ArraySegment<byte> value)
|
||||||
|
{
|
||||||
|
return WithUserProperty(new MqttUserProperty(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the user property to the unsubscribe options.
|
/// Adds the user property to the unsubscribe options.
|
||||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
* Core: Used new language features across the entire library
|
* Core: Used new language features across the entire library
|
||||||
* Core: Performance improvements
|
* Core: Performance improvements
|
||||||
* Core: Added validations for variable byte integers which do not match the .NET uint perfectly
|
* Core: Added validations for variable byte integers which do not match the .NET uint perfectly
|
||||||
|
* Client: Added support for pre-encoded UTF-8 binary buffers for user properties (#2228, thanks to @koepalex)
|
||||||
* Server: Improved performance of retained messages when no event handler is attached (#2093, thanks to @zhaowgit)
|
* Server: Improved performance of retained messages when no event handler is attached (#2093, thanks to @zhaowgit)
|
||||||
* Server: The event `InterceptingClientEnqueue` is now also called for retained messages (BREAKING CHANGE!)
|
* Server: The event `InterceptingClientEnqueue` is now also called for retained messages (BREAKING CHANGE!)
|
||||||
* Server: The local end point is now also exposed in the channel adapter (#2179)
|
* Server: The local end point is now also exposed in the channel adapter (#2179)
|
||||||
* Marked all projects as AOT compatible
|
* Marked all projects as AOT compatible
|
||||||
* Restored the strong name of the nugets
|
* Restored the strong name of the nugets
|
||||||
* Embedded license file in all nugets (#2197, thanks to @JensNordenbro)
|
* Embedded license file in all nugets (#2197, thanks to @JensNordenbro)
|
||||||
|
* Added support for dotnet10
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"test": {
|
||||||
|
"runner": "Microsoft.Testing.Platform"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user