Compare commits

..
Author SHA1 Message Date
christian b477ddbe60 Start using readonly memory 2025-10-22 11:35:56 +02:00
53 changed files with 229 additions and 623 deletions
+11 -13
View File
@@ -17,27 +17,20 @@ 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 (signed) - name: Build package
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:
@@ -55,19 +48,24 @@ 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 net10.0 --configuration Release --project Source/MQTTnet.Tests/MQTTnet.Tests.csproj run: dotnet test --framework net8.0 --configuration Release 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' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) if: github.repository == 'dotnet/MQTTnet'
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:
@@ -75,7 +73,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.1-beta.25379.1 run: dotnet tool install --tool-path . sign --version 0.9.0-beta.23127.3
- name: Sign nugets - name: Sign nugets
shell: pwsh shell: pwsh
@@ -116,7 +114,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.1.0-rc' etc. # Tag schema is 'v5.0.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
+27 -3
View File
@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks> <TargetFramework>net8.0</TargetFramework>
<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,7 +11,6 @@
<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>
@@ -25,10 +24,35 @@
<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>
-24
View File
@@ -1,24 +0,0 @@
<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>
-1
View File
@@ -13,7 +13,6 @@ 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}"
-20
View File
@@ -6,9 +6,6 @@
// 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
@@ -87,21 +84,4 @@ 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();
}
} }
+1 -2
View File
@@ -7,7 +7,6 @@
// 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;
@@ -68,7 +67,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", Encoding.UTF8.GetBytes("Data"))); args.ResponseUserProperties.Add(new MqttUserProperty("My", "Data"));
// Now the broker will resend the message again. // Now the broker will resend the message again.
return Task.CompletedTask; return Task.CompletedTask;
-2
View File
@@ -59,12 +59,10 @@ 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,7 +40,6 @@ 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)
@@ -51,26 +50,4 @@ 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;
}
} }
@@ -51,7 +51,6 @@ 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);
@@ -65,32 +64,4 @@ 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,14 +202,9 @@ 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,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<DebugType>Full</DebugType>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
@@ -6,7 +6,6 @@ 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;
@@ -144,7 +143,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", Encoding.UTF8.GetBytes("test_value")).Build(); var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithUserProperty("test_name", "test_value").Build();
// Perform a clean disconnect. // Perform a clean disconnect.
await client.DisconnectAsync(disconnectOptions); await client.DisconnectAsync(disconnectOptions);
@@ -155,7 +154,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].ReadValueAsString()); Assert.AreEqual("test_value", eventArgs.UserProperties[0].Value);
} }
sealed class TestClientKerberosAuthenticationHandler : IMqttEnhancedAuthenticationHandler sealed class TestClientKerberosAuthenticationHandler : IMqttEnhancedAuthenticationHandler
@@ -261,7 +260,7 @@ public sealed class MqttClient_Connection_Tests : BaseTestClass
server.ValidatingConnectionAsync += args => server.ValidatingConnectionAsync += args =>
{ {
args.ResponseUserProperties = [new("Property", Encoding.UTF8.GetBytes("Value"))]; args.ResponseUserProperties = [new("Property", "Value")];
args.ReasonCode = MqttConnectReasonCode.QuotaExceeded; args.ReasonCode = MqttConnectReasonCode.QuotaExceeded;
@@ -275,7 +274,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].ReadValueAsString()); Assert.AreEqual("Value", response.UserProperties[0].Value);
} }
[TestMethod] [TestMethod]
@@ -3,7 +3,6 @@
// 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;
@@ -46,7 +45,7 @@ public sealed class MqttPacketSerialization_V3_Tests
SubscriptionIdentifiersAvailable = true, SubscriptionIdentifiersAvailable = true,
TopicAliasMaximum = 963, TopicAliasMaximum = 963,
WildcardSubscriptionAvailable = true, WildcardSubscriptionAvailable = true,
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V311);
@@ -97,7 +96,7 @@ public sealed class MqttPacketSerialization_V3_Tests
SubscriptionIdentifiersAvailable = true, SubscriptionIdentifiersAvailable = true,
TopicAliasMaximum = 963, TopicAliasMaximum = 963,
WildcardSubscriptionAvailable = true, WildcardSubscriptionAvailable = true,
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V310); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V310);
@@ -153,8 +152,8 @@ public sealed class MqttPacketSerialization_V3_Tests
WillResponseTopic = "WillResponseTopic", WillResponseTopic = "WillResponseTopic",
WillMessageExpiryInterval = 542, WillMessageExpiryInterval = 542,
WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData, WillPayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))], UserProperties = [new("Foo", "Bar")],
WillUserProperties = [new("WillFoo", Encoding.UTF8.GetBytes("WillBar"))] WillUserProperties = [new("WillFoo", "WillBar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V311);
@@ -196,7 +195,7 @@ public sealed class MqttPacketSerialization_V3_Tests
ReasonString = "ReasonString", ReasonString = "ReasonString",
ServerReference = "ServerReference", ServerReference = "ServerReference",
SessionExpiryInterval = 234, SessionExpiryInterval = 234,
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V311);
@@ -236,7 +235,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers, ReasonCode = MqttPubAckReasonCode.NoMatchingSubscribers,
ReasonString = "ReasonString", ReasonString = "ReasonString",
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V311);
@@ -255,7 +254,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound, ReasonCode = MqttPubCompReasonCode.PacketIdentifierNotFound,
ReasonString = "ReasonString", ReasonString = "ReasonString",
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V311);
@@ -285,7 +284,7 @@ public sealed class MqttPacketSerialization_V3_Tests
SubscriptionIdentifiers = [123], SubscriptionIdentifiers = [123],
MessageExpiryInterval = 38, MessageExpiryInterval = 38,
PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData, PayloadFormatIndicator = MqttPayloadFormatIndicator.CharacterData,
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V311);
@@ -314,7 +313,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonCode = MqttPubRecReasonCode.UnspecifiedError, ReasonCode = MqttPubRecReasonCode.UnspecifiedError,
ReasonString = "ReasonString", ReasonString = "ReasonString",
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V311);
@@ -334,7 +333,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound, ReasonCode = MqttPubRelReasonCode.PacketIdentifierNotFound,
ReasonString = "ReasonString", ReasonString = "ReasonString",
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V311);
@@ -354,7 +353,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonString = "ReasonString", ReasonString = "ReasonString",
ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1], ReasonCodes = [MqttSubscribeReasonCode.GrantedQoS1],
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V311);
@@ -384,7 +383,7 @@ public sealed class MqttPacketSerialization_V3_Tests
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
} }
], ],
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V311);
@@ -408,7 +407,7 @@ public sealed class MqttPacketSerialization_V3_Tests
PacketIdentifier = 123, PacketIdentifier = 123,
ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError], ReasonCodes = [MqttUnsubscribeReasonCode.ImplementationSpecificError],
ReasonString = "ReasonString", ReasonString = "ReasonString",
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V311);
@@ -426,7 +425,7 @@ public sealed class MqttPacketSerialization_V3_Tests
{ {
PacketIdentifier = 123, PacketIdentifier = 123,
TopicFilters = ["TopicFilter1"], TopicFilters = ["TopicFilter1"],
UserProperties = [new("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V311); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V311);
@@ -3,7 +3,6 @@
// 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;
@@ -33,7 +32,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(authPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(authPacket, MqttProtocolVersion.V500);
@@ -69,7 +68,7 @@ public sealed class MqttPacketSerialization_V5_Tests
SubscriptionIdentifiersAvailable = true, SubscriptionIdentifiersAvailable = true,
TopicAliasMaximum = 963, TopicAliasMaximum = 963,
WildcardSubscriptionAvailable = true, WildcardSubscriptionAvailable = true,
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connAckPacket, MqttProtocolVersion.V500);
@@ -125,8 +124,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", Encoding.UTF8.GetBytes("Bar"))], UserProperties = [new MqttUserProperty("Foo", "Bar")],
WillUserProperties = [new MqttUserProperty("WillFoo", Encoding.UTF8.GetBytes("WillBar"))] WillUserProperties = [new MqttUserProperty("WillFoo", "WillBar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(connectPacket, MqttProtocolVersion.V500);
@@ -168,7 +167,7 @@ public sealed class MqttPacketSerialization_V5_Tests
ReasonString = "ReasonString", ReasonString = "ReasonString",
ServerReference = "ServerReference", ServerReference = "ServerReference",
SessionExpiryInterval = 234, SessionExpiryInterval = 234,
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(disconnectPacket, MqttProtocolVersion.V500);
@@ -208,7 +207,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubAckPacket, MqttProtocolVersion.V500);
@@ -227,7 +226,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V500);
@@ -256,7 +255,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(publishPacket, MqttProtocolVersion.V500);
@@ -285,7 +284,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRecPacket, MqttProtocolVersion.V500);
@@ -304,7 +303,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubRelPacket, MqttProtocolVersion.V500);
@@ -323,7 +322,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subAckPacket, MqttProtocolVersion.V500);
@@ -353,7 +352,7 @@ public sealed class MqttPacketSerialization_V5_Tests
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
} }
], ],
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(subscribePacket, MqttProtocolVersion.V500);
@@ -377,7 +376,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", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubAckPacket, MqttProtocolVersion.V500);
@@ -396,7 +395,7 @@ public sealed class MqttPacketSerialization_V5_Tests
{ {
PacketIdentifier = 123, PacketIdentifier = 123,
TopicFilters = ["TopicFilter1"], TopicFilters = ["TopicFilter1"],
UserProperties = [new MqttUserProperty("Foo", Encoding.UTF8.GetBytes("Bar"))] UserProperties = [new MqttUserProperty("Foo", "Bar")]
}; };
var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V500); var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V500);
+4 -8
View File
@@ -1,17 +1,19 @@
<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="MSTest" Version="4.0.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="MSTest" Version="4.0.1" />
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup> </ItemGroup>
@@ -23,10 +25,4 @@
<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>
+8 -9
View File
@@ -4,7 +4,6 @@
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;
@@ -65,8 +64,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", Encoding.UTF8.GetBytes("1")) .WithUserProperty("a", "1")
.WithUserProperty("b", Encoding.UTF8.GetBytes("2")) .WithUserProperty("b", "2")
.WithPayloadFormatIndicator(MqttPayloadFormatIndicator.CharacterData) .WithPayloadFormatIndicator(MqttPayloadFormatIndicator.CharacterData)
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
.Build()); .Build());
@@ -99,8 +98,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", Encoding.UTF8.GetBytes("1")) .WithUserProperty("x", "1")
.WithUserProperty("y", Encoding.UTF8.GetBytes("2")) .WithUserProperty("y", "2")
.WithResponseTopic("response") .WithResponseTopic("response")
.WithContentType("text") .WithContentType("text")
.WithMessageExpiryInterval(50) .WithMessageExpiryInterval(50)
@@ -215,8 +214,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", Encoding.UTF8.GetBytes("1")) .WithUserProperty("x", "1")
.WithUserProperty("y", Encoding.UTF8.GetBytes("2")) .WithUserProperty("y", "2")
.WithResponseTopic("response") .WithResponseTopic("response")
.WithContentType("text") .WithContentType("text")
.WithMessageExpiryInterval(50) .WithMessageExpiryInterval(50)
@@ -251,8 +250,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", Encoding.UTF8.GetBytes("1")) .WithUserProperty("x", "1")
.WithUserProperty("y", Encoding.UTF8.GetBytes("2")) .WithUserProperty("y", "2")
.WithResponseTopic("response") .WithResponseTopic("response")
.WithContentType("text") .WithContentType("text")
.WithMessageExpiryInterval(50) .WithMessageExpiryInterval(50)
@@ -2,12 +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.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;
@@ -64,64 +59,4 @@ 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,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.Text;
using MQTTnet.Formatter; using MQTTnet.Formatter;
namespace MQTTnet.Tests; namespace MQTTnet.Tests;
@@ -28,7 +27,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", Encoding.UTF8.GetBytes("Property")).Build(), new MqttApplicationMessageBuilder().WithTopic("A").WithUserProperty("User", "Property").Build(),
MqttProtocolVersion.V500); MqttProtocolVersion.V500);
} }
@@ -36,7 +35,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", Encoding.UTF8.GetBytes("Property")).Build(), new MqttApplicationMessageBuilder().WithTopic("B").WithUserProperty("User", "Property").Build(),
MqttProtocolVersion.V311)); MqttProtocolVersion.V311));
} }
} }
@@ -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.Text;
using MQTTnet.Formatter; using MQTTnet.Formatter;
namespace MQTTnet.Tests; namespace MQTTnet.Tests;
@@ -14,27 +13,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", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build(); new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithUserProperty("User", "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", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build()); new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithWillUserProperty("User", "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", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build(); new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithWillUserProperty("User", "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", Encoding.UTF8.GetBytes("Property")).WithTcpServer("FAKE").Build()); new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V311).WithUserProperty("User", "Property").WithTcpServer("FAKE").Build());
} }
[TestMethod] [TestMethod]
+2 -3
View File
@@ -20,8 +20,7 @@ public class MqttTcpChannel_Tests
try try
{ {
serverSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); serverSocket.Bind(new IPEndPoint(IPAddress.Any, 50001));
var serverPort = ((IPEndPoint)serverSocket.LocalEndPoint).Port;
serverSocket.Listen(0); serverSocket.Listen(0);
#pragma warning disable 4014 #pragma warning disable 4014
@@ -38,7 +37,7 @@ public class MqttTcpChannel_Tests
}, },
ct.Token); ct.Token);
var remoteEndPoint = new DnsEndPoint("localhost", serverPort); var remoteEndPoint = new DnsEndPoint("localhost", 50001);
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", Encoding.UTF8.GetBytes("B")) .WithUserProperty("A", "B")
.WithResponseTopic("Response") .WithResponseTopic("Response")
.WithCorrelationData(Encoding.UTF8.GetBytes("Correlation")) .WithCorrelationData(Encoding.UTF8.GetBytes("Correlation"))
.Build(); .Build();
@@ -2,7 +2,6 @@ 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;
@@ -27,7 +26,6 @@ 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();
@@ -49,7 +47,6 @@ 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();
@@ -73,7 +70,6 @@ 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();
@@ -95,7 +91,6 @@ 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();
@@ -127,12 +122,10 @@ 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;
} }
@@ -140,11 +133,10 @@ 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()
{ {
@@ -153,15 +145,10 @@ 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];
@@ -227,7 +214,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", _serverPort) .WithTcpServer("localhost")
.WithCleanSession() .WithCleanSession()
.WithProtocolVersion(MqttProtocolVersion.V500); .WithProtocolVersion(MqttProtocolVersion.V500);
@@ -253,7 +240,6 @@ 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;
@@ -273,8 +259,6 @@ 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();
@@ -295,7 +279,6 @@ 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();
@@ -305,17 +288,6 @@ 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,7 +3,6 @@
// 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;
@@ -99,7 +98,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", Encoding.UTF8.GetBytes("1")).Build(); var subscribeOptions = testEnvironment.ClientFactory.CreateSubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "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,5 +1,4 @@
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;
@@ -521,11 +520,10 @@ 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)
{ {
bytes = bytes.AsEnumerable().Reverse().ToArray(); return bytes.Reverse().ToArray();
} }
return bytes; return bytes;
-2
View File
@@ -31,12 +31,10 @@ 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,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.Text;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
using MQTTnet.Formatter; using MQTTnet.Formatter;
using MQTTnet.Internal; using MQTTnet.Internal;
@@ -46,7 +45,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", Encoding.UTF8.GetBytes("1")).Build(); var unsubscribeOptions = testEnvironment.ClientFactory.CreateUnsubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "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,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.Text;
using MQTTnet.Formatter; using MQTTnet.Formatter;
using MQTTnet.Internal; using MQTTnet.Internal;
using MQTTnet.Packets; using MQTTnet.Packets;
@@ -27,10 +26,10 @@ public class Feature_Tests
var message = new MqttApplicationMessageBuilder() var message = new MqttApplicationMessageBuilder()
.WithTopic("A") .WithTopic("A")
.WithUserProperty("x", Encoding.UTF8.GetBytes("1")) .WithUserProperty("x", "1")
.WithUserProperty("y", Encoding.UTF8.GetBytes("2")) .WithUserProperty("y", "2")
.WithUserProperty("z", Encoding.UTF8.GetBytes("3")) .WithUserProperty("z", "3")
.WithUserProperty("z", Encoding.UTF8.GetBytes("4")); // z is here two times to test list of items .WithUserProperty("z", "4"); // z is here two times to test list of items
await receiver.SubscribeAsync(new MqttClientSubscribeOptions await receiver.SubscribeAsync(new MqttClientSubscribeOptions
{ {
@@ -14,17 +14,6 @@ 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.
@@ -32,7 +21,5 @@ 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, AuthenticationData = connAckPacket.AuthenticationData.ToArray(),
MaximumPacketSize = connAckPacket.MaximumPacketSize, MaximumPacketSize = connAckPacket.MaximumPacketSize,
ReasonString = connAckPacket.ReasonString, ReasonString = connAckPacket.ReasonString,
ReceiveMaximum = connAckPacket.ReceiveMaximum, ReceiveMaximum = connAckPacket.ReceiveMaximum,
@@ -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;
using MQTTnet.Packets; using MQTTnet.Packets;
namespace MQTTnet; namespace MQTTnet;
@@ -49,25 +48,10 @@ 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, CorrelationData = publishPacket.CorrelationData.ToArray(),
MessageExpiryInterval = publishPacket.MessageExpiryInterval, MessageExpiryInterval = publishPacket.MessageExpiryInterval,
SubscriptionIdentifiers = publishPacket.SubscriptionIdentifiers, SubscriptionIdentifiers = publishPacket.SubscriptionIdentifiers,
TopicAlias = publishPacket.TopicAlias, TopicAlias = publishPacket.TopicAlias,
+1 -1
View File
@@ -58,7 +58,7 @@ public sealed class MqttBufferReader
return value; return value;
} }
public byte[] ReadRemainingData() public ReadOnlyMemory<byte> ReadRemainingData()
{ {
var bufferLength = BytesLeft; var bufferLength = BytesLeft;
if (bufferLength == 0) if (bufferLength == 0)
+82 -60
View File
@@ -2,7 +2,8 @@
// 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.Binary;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
@@ -109,31 +110,47 @@ public sealed class MqttBufferWriter
WriteBinary(propertyWriter._buffer, 0, propertyWriter.Length); WriteBinary(propertyWriter._buffer, 0, propertyWriter.Length);
} }
public void WriteBinary(byte[] value) public void WriteBinary(ReadOnlySequence<byte> value)
{ {
if (value == null || value.Length == 0) if (value.IsEmpty)
{ {
EnsureAdditionalCapacity(2); WriteEmptyBinary();
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)
{ {
var valueLength = value.Length; MqttMemoryHelper.Copy(segment, 0, _buffer, _position + 2, segment.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);
@@ -146,15 +163,7 @@ public sealed class MqttBufferWriter
EnsureAdditionalCapacity(count); EnsureAdditionalCapacity(count);
MqttMemoryHelper.Copy(buffer, offset, _buffer, _position, count); MqttMemoryHelper.Copy(buffer, offset, _buffer, _position, count);
IncreasePosition(count); Advance(count);
}
public void WriteByte(byte @byte)
{
EnsureAdditionalCapacity(1);
_buffer[_position] = @byte;
IncreasePosition(1);
} }
public void WriteString(string value) public void WriteString(string value)
@@ -166,7 +175,7 @@ public sealed class MqttBufferWriter
_buffer[_position] = 0; _buffer[_position] = 0;
_buffer[_position + 1] = 0; _buffer[_position + 1] = 0;
IncreasePosition(2); Advance(2);
} }
else else
{ {
@@ -190,49 +199,52 @@ public sealed class MqttBufferWriter
_buffer[_position] = (byte)(writtenBytes >> 8); _buffer[_position] = (byte)(writtenBytes >> 8);
_buffer[_position + 1] = (byte)writtenBytes; _buffer[_position + 1] = (byte)writtenBytes;
IncreasePosition(writtenBytes + 2); Advance(writtenBytes + 2);
} }
} }
public void WriteString(ReadOnlyMemory<byte> value) public void WriteByte(byte @byte)
{ {
var span = value.Span; const int size = sizeof(byte);
var length = span.Length; var span = GetSpan(size);
if (length > EncodedStringMaxLength) span[0] = @byte;
{ 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)
{ {
EnsureAdditionalCapacity(2); const int size = sizeof(ushort);
var span = GetSpan(size);
_buffer[_position] = (byte)(value >> 8); BinaryPrimitives.WriteUInt16BigEndian(span, value);
IncreasePosition(1);
_buffer[_position] = (byte)value; Advance(size);
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;
IncreasePosition(1); Advance(1);
return; return;
} }
@@ -240,7 +252,7 @@ public sealed class MqttBufferWriter
if (value <= 127) if (value <= 127)
{ {
_buffer[_position] = (byte)value; _buffer[_position] = (byte)value;
IncreasePosition(1); Advance(1);
return; return;
} }
@@ -262,11 +274,11 @@ public sealed class MqttBufferWriter
size++; size++;
} while (x > 0); } while (x > 0);
IncreasePosition(size); Advance(size);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void EnsureAdditionalCapacity(int additionalCapacity) void EnsureAdditionalCapacity(long additionalCapacity)
{ {
var bufferLength = _buffer.Length; var bufferLength = _buffer.Length;
@@ -280,7 +292,7 @@ public sealed class MqttBufferWriter
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void EnsureCapacity(int capacity) void EnsureCapacity(long capacity)
{ {
var newBufferLength = _buffer.Length; var newBufferLength = _buffer.Length;
@@ -299,7 +311,7 @@ public sealed class MqttBufferWriter
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void IncreasePosition(int length) void Advance(int length)
{ {
_position += length; _position += length;
@@ -310,4 +322,14 @@ public sealed class MqttBufferWriter
Length = _position; Length = _position;
} }
} }
void WriteEmptyBinary()
{
EnsureAdditionalCapacity(2);
_buffer[_position] = 0;
_buffer[_position + 1] = 0;
Advance(2);
}
} }
@@ -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.Buffers;
using MQTTnet.Packets; using MQTTnet.Packets;
namespace MQTTnet.Formatter; namespace MQTTnet.Formatter;
@@ -40,7 +41,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 = clientOptions.WillPayload; connectPacket.WillMessage = new ReadOnlySequence<byte>(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 = _bufferReader.ReadBinaryData(); packet.WillMessage = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
} }
if (usernameFlag) if (usernameFlag)
@@ -271,7 +271,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
if (!_bufferReader.EndOfStream) if (!_bufferReader.EndOfStream)
{ {
packet.PayloadSegment = new ArraySegment<byte>(_bufferReader.ReadRemainingData()); packet.Payload = new ReadOnlySequence<byte>(_bufferReader.ReadRemainingData());
} }
return packet; return packet;
@@ -430,12 +430,12 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
} }
} }
if (packet.Password != null && packet.Username == null) if (packet.Password.Length > 0 && 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 != null) if (packet.Password.Length > 0)
{ {
connectFlags |= 0x40; connectFlags |= 0x40;
} }
@@ -460,7 +460,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
bufferWriter.WriteString(packet.Username); bufferWriter.WriteString(packet.Username);
} }
if (packet.Password != null) if (packet.Password.Length > 0)
{ {
bufferWriter.WriteBinary(packet.Password); bufferWriter.WriteBinary(packet.Password);
} }
@@ -501,12 +501,12 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
} }
} }
if (packet.Password != null && packet.Username == null) if (packet.Password.Length > 0 && 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 != null) if (packet.Password.Length > 0)
{ {
connectFlags |= 0x40; connectFlags |= 0x40;
} }
@@ -531,7 +531,7 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
bufferWriter.WriteString(packet.Username); bufferWriter.WriteString(packet.Username);
} }
if (packet.Password != null) if (packet.Password.Length > 0)
{ {
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.Buffers;
using MQTTnet.Adapter; using MQTTnet.Adapter;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
using MQTTnet.Packets; using MQTTnet.Packets;
@@ -314,7 +315,7 @@ public sealed class MqttV5PacketDecoder
} }
packet.WillTopic = _bufferReader.ReadString(); packet.WillTopic = _bufferReader.ReadString();
packet.WillMessage = _bufferReader.ReadBinaryData(); packet.WillMessage = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
packet.WillUserProperties = willPropertiesReader.CollectedUserProperties; packet.WillUserProperties = willPropertiesReader.CollectedUserProperties;
} }
@@ -521,7 +522,7 @@ public sealed class MqttV5PacketDecoder
if (!_bufferReader.EndOfStream) if (!_bufferReader.EndOfStream)
{ {
packet.PayloadSegment = new ArraySegment<byte>(_bufferReader.ReadRemainingData()); packet.Payload = new ReadOnlySequence<byte>(_bufferReader.ReadBinaryData());
} }
return packet; return packet;
@@ -138,12 +138,12 @@ public sealed class MqttV5PacketEncoder(MqttBufferWriter bufferWriter)
} }
} }
if (packet.Password != null && packet.Username == null) if (packet.Password.Length > 0 && 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 != null) if (packet.Password.Length > 0)
{ {
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 != null) if (packet.Password.Length > 0)
{ {
_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;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
using MQTTnet.Packets; using MQTTnet.Packets;
using MQTTnet.Protocol; using MQTTnet.Protocol;
@@ -60,14 +59,14 @@ public struct MqttV5PropertiesReader
if (CurrentPropertyId == MqttPropertyId.UserProperty) if (CurrentPropertyId == MqttPropertyId.UserProperty)
{ {
var name = _body.ReadString(); var name = _body.ReadString();
var valueBuffer = ReadUserPropertyValueBuffer(); var value = _body.ReadString();
if (CollectedUserProperties == null) if (CollectedUserProperties == null)
{ {
CollectedUserProperties = new List<MqttUserProperty>(); CollectedUserProperties = new List<MqttUserProperty>();
} }
CollectedUserProperties.Add(new MqttUserProperty(name, valueBuffer)); CollectedUserProperties.Add(new MqttUserProperty(name, value));
continue; continue;
} }
@@ -191,11 +190,6 @@ 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(byte[] value) public void WriteAuthenticationData(ReadOnlyMemory<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(byte[] value) public void WriteCorrelationData(ReadOnlyMemory<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.ValueBuffer); _bufferWriter.WriteString(property.Value);
} }
} }
@@ -315,9 +315,9 @@ public sealed class MqttV5PropertiesWriter
_bufferWriter.WriteString(value); _bufferWriter.WriteString(value);
} }
void Write(MqttPropertyId id, byte[] value) void Write(MqttPropertyId id, ReadOnlyMemory<byte> value)
{ {
if (value == null) if (value.Length == 0)
{ {
return; return;
} }
+1 -1
View File
@@ -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,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;
using System.Buffers; using System.Buffers;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -264,33 +263,10 @@ 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,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;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@@ -358,7 +357,6 @@ 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)
@@ -370,28 +368,6 @@ 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);
@@ -486,25 +462,10 @@ 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; public byte[] AuthenticationData => _initialAuthPacket.AuthenticationData.ToArray();
/// <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, AuthenticationData = authPacket.AuthenticationData.ToArray(),
AuthenticationMethod = authPacket.AuthenticationMethod, AuthenticationMethod = authPacket.AuthenticationMethod,
ReasonString = authPacket.ReasonString, ReasonString = authPacket.ReasonString,
ReasonCode = authPacket.ReasonCode, ReasonCode = authPacket.ReasonCode,
+1 -1
View File
@@ -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 byte[] AuthenticationData { get; set; } public ReadOnlyMemory<byte> AuthenticationData { get; set; }
public string AuthenticationMethod { get; set; } public string AuthenticationMethod { get; set; }
+1 -1
View File
@@ -13,7 +13,7 @@ public sealed class MqttConnAckPacket : MqttPacket
/// </summary> /// </summary>
public string AssignedClientIdentifier { get; set; } public string AssignedClientIdentifier { get; set; }
public byte[] AuthenticationData { get; set; } public ReadOnlyMemory<byte> AuthenticationData { get; set; }
public string AuthenticationMethod { get; set; } public string AuthenticationMethod { get; set; }
+6 -5
View File
@@ -2,13 +2,14 @@
// 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 byte[] AuthenticationData { get; set; } public ReadOnlyMemory<byte> AuthenticationData { get; set; }
public string AuthenticationMethod { get; set; } public string AuthenticationMethod { get; set; }
@@ -19,13 +20,13 @@ public sealed class MqttConnectPacket : MqttPacket
public string ClientId { get; set; } public string ClientId { get; set; }
public byte[] WillCorrelationData { get; set; } public ReadOnlyMemory<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 byte[] Password { get; set; } public ReadOnlyMemory<byte> Password { get; set; }
public ushort ReceiveMaximum { get; set; } public ushort ReceiveMaximum { get; set; }
@@ -49,7 +50,7 @@ public sealed class MqttConnectPacket : MqttPacket
public bool WillFlag { get; set; } public bool WillFlag { get; set; }
public byte[] WillMessage { get; set; } public ReadOnlySequence<byte> WillMessage { get; set; }
public uint WillMessageExpiryInterval { get; set; } public uint WillMessageExpiryInterval { get; set; }
@@ -69,7 +70,7 @@ public sealed class MqttConnectPacket : MqttPacket
{ {
var passwordText = string.Empty; var passwordText = string.Empty;
if (Password != null) if (Password.Length > 0)
{ {
passwordText = "****"; passwordText = "****";
} }
+2 -2
View File
@@ -11,7 +11,7 @@ public sealed class MqttPublishPacket : MqttPacketWithIdentifier
{ {
public string ContentType { get; set; } public string ContentType { get; set; }
public byte[] CorrelationData { get; set; } public ReadOnlyMemory<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; }
+5 -53
View File
@@ -2,37 +2,19 @@
// 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));
_valueBuffer = value; Value = value ?? throw new ArgumentNullException(nameof(value));
} }
public string Name { get; } public string Name { get; }
public ReadOnlyMemory<byte> ValueBuffer => _valueBuffer; public string Value { get; }
[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)
{ {
@@ -51,46 +33,16 @@ public sealed class MqttUserProperty
return true; return true;
} }
if (!string.Equals(Name, other.Name, StringComparison.Ordinal)) return string.Equals(Name, other.Name, StringComparison.Ordinal) && string.Equals(Value, other.Value, StringComparison.Ordinal);
{
return false;
}
return _valueBuffer.Span.SequenceEqual(other._valueBuffer.Span);
} }
public override int GetHashCode() public override int GetHashCode()
{ {
var hashCode = new HashCode(); return Name.GetHashCode() ^ Value.GetHashCode();
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} = {this.ReadValueAsString()}"; return $"{Name} = {Value}";
}
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);
} }
} }
@@ -1,27 +0,0 @@
// 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,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;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
using MQTTnet.Packets; using MQTTnet.Packets;
using MQTTnet.Protocol; using MQTTnet.Protocol;
@@ -78,7 +77,6 @@ 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 ??= [];
@@ -86,28 +84,4 @@ 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,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;
using MQTTnet.Packets; using MQTTnet.Packets;
namespace MQTTnet; namespace MQTTnet;
@@ -37,30 +36,11 @@ 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>
-2
View File
@@ -1,11 +1,9 @@
* 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
-5
View File
@@ -1,5 +0,0 @@
{
"test": {
"runner": "Microsoft.Testing.Platform"
}
}