mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-15 00:15:15 +08:00
Merge from develop.
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
||||
<dependencies>
|
||||
<dependency id="MQTTnet" version="2.8.5-rc3" />
|
||||
<dependency id="MQTTnet" version="2.8.5" />
|
||||
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="2.1.3" />
|
||||
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.1.1" />
|
||||
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="2.1.1" />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
||||
<dependencies>
|
||||
<dependency id="MQTTnet" version="2.8.5-rc3" />
|
||||
<dependency id="MQTTnet" version="2.8.5" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
||||
<dependencies>
|
||||
<dependency id="MQTTnet" version="2.8.5-rc3" />
|
||||
<dependency id="MQTTnet" version="2.8.5" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
|
||||
@@ -12,12 +12,17 @@
|
||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
|
||||
<releaseNotes> * [Core] Updated nuget packages due to security issues.
|
||||
* [Client] Fixed wrong behavior of publish method when client is disconnecting (thanks to @PaulFake).
|
||||
* [Client] Added readonly property for accessing options.
|
||||
* [ManagedClient] Added max pending messages count option.
|
||||
* [ManagedClient] Add pending messages overflow strategy option.
|
||||
* [ManagedClient] Fixed an issue which deletes the wrong message from the internal queue (thanks to @PaulFake).
|
||||
* [ManagedClient] Added readonly property for accessing options.
|
||||
* [Server] Added new method which exposes all retained messages.
|
||||
* [Server] Removed (wrong) setter from the server options interface.
|
||||
* [Server] fixed cpu spike in case a client disconnectes (issue 421).
|
||||
* [Server] fixed concurrent sends with Aspnetcore.Connections.Abstractions based transport.
|
||||
* [Server] Fixed cpu spike in case a client disconnects (issue 421).
|
||||
* [Server] Fixed concurrent sends with Aspnetcore.Connections.Abstractions based transport.
|
||||
* [Server] Fixed wrong retain flag when distributing application messages (thanks to @trev0115).
|
||||
* [Server] Fixed issue which closes a connection when reconnecting with the same client ID (thanks to @fogzot).
|
||||
</releaseNotes>
|
||||
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2010
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1-B9D6-40BF-81EC-86004D7765B4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Build\build.ps1 = Build\build.ps1
|
||||
Build\MQTTnet.AspNetCore.nuspec = Build\MQTTnet.AspNetCore.nuspec
|
||||
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
|
||||
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
|
||||
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
|
||||
Build\upload.ps1 = Build\upload.ps1
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.bettercodehub.yml = .bettercodehub.yml
|
||||
appveyor.yml = appveyor.yml
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.TestApp.NetCore", "Tests\MQTTnet.TestApp.NetCore\MQTTnet.TestApp.NetCore.csproj", "{3D283AAD-AAA8-4339-8394-52F80B6304DB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.TestApp.AspNetCore2", "Tests\MQTTnet.TestApp.AspNetCore2\MQTTnet.TestApp.AspNetCore2.csproj", "{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore", "Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj", "{F10C4060-F7EE-4A83-919F-FF723E72F94A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{12816BCC-AF9E-44A9-9AE5-C246AF2A0587}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.Rpc", "Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj", "{C444E9C8-95FA-430E-9126-274129DE16CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Benchmarks", "Tests\MQTTnet.Benchmarks\MQTTnet.Benchmarks.csproj", "{998D04DD-7CB0-45F5-A393-E2495C16399E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.ManagedClient", "Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj", "{C400533A-8EBA-4F0B-BF4D-295C3708604B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore.Tests", "Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj", "{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.Build.0 = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||
{F10C4060-F7EE-4A83-919F-FF723E72F94A} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
||||
{C444E9C8-95FA-430E-9126-274129DE16CD} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
||||
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -86,12 +86,13 @@ This project also listed at Open Collective (https://opencollective.com/mqttnet)
|
||||
|
||||
This library is used in the following projects:
|
||||
|
||||
* Azure Functions MQTT Bindings, [CaseOnline.Azure.WebJobs.Extensions.Mqtt](https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt/)
|
||||
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
|
||||
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
|
||||
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
|
||||
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
|
||||
|
||||
If you use this library and want to see your project here please let me know.
|
||||
If you use this library and want to see your project here please create a pull request.
|
||||
|
||||
## MIT License
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
bool IsStarted { get; }
|
||||
bool IsConnected { get; }
|
||||
int PendingApplicationMessagesCount { get; }
|
||||
IManagedMqttClientOptions Options { get; }
|
||||
|
||||
event EventHandler<MqttClientConnectedEventArgs> Connected;
|
||||
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard1.3;netstandard2.0;net452;net461</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core'">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||
<Product />
|
||||
<Company />
|
||||
|
||||
@@ -27,8 +27,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
private CancellationTokenSource _publishingCancellationToken;
|
||||
|
||||
private ManagedMqttClientStorageManager _storageManager;
|
||||
private IManagedMqttClientOptions _options;
|
||||
|
||||
|
||||
private bool _subscriptionsNotPushed;
|
||||
|
||||
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
|
||||
@@ -47,6 +46,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
public bool IsConnected => _mqttClient.IsConnected;
|
||||
public bool IsStarted => _connectionCancellationToken != null;
|
||||
public int PendingApplicationMessagesCount => _messageQueue.Count;
|
||||
public IManagedMqttClientOptions Options { get; private set; }
|
||||
|
||||
public event EventHandler<MqttClientConnectedEventArgs> Connected;
|
||||
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
|
||||
@@ -70,11 +70,11 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
if (_connectionCancellationToken != null) throw new InvalidOperationException("The managed client is already started.");
|
||||
|
||||
_options = options;
|
||||
Options = options;
|
||||
|
||||
if (_options.Storage != null)
|
||||
if (Options.Storage != null)
|
||||
{
|
||||
_storageManager = new ManagedMqttClientStorageManager(_options.Storage);
|
||||
_storageManager = new ManagedMqttClientStorageManager(Options.Storage);
|
||||
var messages = await _storageManager.LoadQueuedMessagesAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var message in messages)
|
||||
@@ -116,16 +116,16 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
ManagedMqttApplicationMessage removedMessage = null;
|
||||
lock (_messageQueue)
|
||||
{
|
||||
if (_messageQueue.Count >= _options.MaxPendingMessages)
|
||||
if (_messageQueue.Count >= Options.MaxPendingMessages)
|
||||
{
|
||||
if (_options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
|
||||
if (Options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
|
||||
{
|
||||
_logger.Verbose("Skipping publish of new application message because internal queue is full.");
|
||||
ApplicationMessageSkipped?.Invoke(this, new ApplicationMessageSkippedEventArgs(applicationMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
|
||||
if (Options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
|
||||
{
|
||||
removedMessage = _messageQueue.RemoveFirst();
|
||||
_logger.Verbose("Removed oldest application message from internal queue because it is full.");
|
||||
@@ -219,7 +219,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
if (connectionState == ReconnectionResult.NotConnected)
|
||||
{
|
||||
StopPublishing();
|
||||
await Task.Delay(_options.AutoReconnectDelay, cancellationToken).ConfigureAwait(false);
|
||||
await Task.Delay(Options.AutoReconnectDelay, cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
if (connectionState == ReconnectionResult.StillConnected)
|
||||
{
|
||||
await Task.Delay(_options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
|
||||
await Task.Delay(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -254,7 +254,15 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested && _mqttClient.IsConnected)
|
||||
{
|
||||
var message = _messageQueue.Dequeue();
|
||||
//Peek at the message without dequeueing in order to prevent the
|
||||
//possibility of the queue growing beyond the configured cap.
|
||||
//Previously, messages could be re-enqueued if there was an
|
||||
//exception, and this re-enqueueing did not honor the cap.
|
||||
//Furthermore, because re-enqueueing would shuffle the order
|
||||
//of the messages, the DropOldestQueuedMessage strategy would
|
||||
//be unable to know which message is actually the oldest and would
|
||||
//instead drop the first item in the queue.
|
||||
var message = _messageQueue.PeekAndWait();
|
||||
if (message == null)
|
||||
{
|
||||
continue;
|
||||
@@ -284,6 +292,16 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
try
|
||||
{
|
||||
_mqttClient.PublishAsync(message.ApplicationMessage).GetAwaiter().GetResult();
|
||||
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
|
||||
{
|
||||
//While publishing this message, this.PublishAsync could have booted this
|
||||
//message off the queue to make room for another (when using a cap
|
||||
//with the DropOldestQueuedMessage strategy). If the first item
|
||||
//in the queue is equal to this message, then it's safe to remove
|
||||
//it from the queue. If not, that means this.PublishAsync has already
|
||||
//removed it, in which case we don't want to do anything.
|
||||
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
||||
}
|
||||
_storageManager?.RemoveAsync(message).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (MqttCommunicationException exception)
|
||||
@@ -292,9 +310,19 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
_logger.Warning(exception, $"Publishing application ({message.Id}) message failed.");
|
||||
|
||||
if (message.ApplicationMessage.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
||||
if (message.ApplicationMessage.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
_messageQueue.Enqueue(message);
|
||||
//If QoS 0, we don't want this message to stay on the queue.
|
||||
//If QoS 1 or 2, it's possible that, when using a cap, this message
|
||||
//has been booted off the queue by this.PublishAsync, in which case this
|
||||
//thread will not continue to try to publish it. While this does
|
||||
//contradict the expected behavior of QoS 1 and 2, that's also true
|
||||
//for the usage of a message queue cap, so it's still consistent
|
||||
//with prior behavior in that way.
|
||||
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
|
||||
{
|
||||
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
@@ -360,7 +388,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
|
||||
try
|
||||
{
|
||||
await _mqttClient.ConnectAsync(_options.ClientOptions).ConfigureAwait(false);
|
||||
await _mqttClient.ConnectAsync(Options.ClientOptions).ConfigureAwait(false);
|
||||
return ReconnectionResult.Reconnected;
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard1.3;netstandard2.0;net452;net461</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core'">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||
<Product />
|
||||
<Company />
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace MQTTnet.Client
|
||||
public interface IMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||
{
|
||||
bool IsConnected { get; }
|
||||
IMqttClientOptions Options { get; }
|
||||
|
||||
event EventHandler<MqttClientConnectedEventArgs> Connected;
|
||||
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace MQTTnet.Client
|
||||
private readonly IMqttClientAdapterFactory _adapterFactory;
|
||||
private readonly IMqttNetChildLogger _logger;
|
||||
|
||||
private IMqttClientOptions _options;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
internal Task _packetReceiverTask;
|
||||
internal Task _keepAliveMessageSenderTask;
|
||||
@@ -46,6 +45,7 @@ namespace MQTTnet.Client
|
||||
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
|
||||
|
||||
public bool IsConnected { get; private set; }
|
||||
public IMqttClientOptions Options { get; private set; }
|
||||
|
||||
public async Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options)
|
||||
{
|
||||
@@ -56,16 +56,17 @@ namespace MQTTnet.Client
|
||||
|
||||
try
|
||||
{
|
||||
_options = options;
|
||||
Options = options;
|
||||
|
||||
_packetIdentifierProvider.Reset();
|
||||
_packetDispatcher.Reset();
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_disconnectGate = 0;
|
||||
_adapter = _adapterFactory.CreateClientAdapter(options, _logger);
|
||||
|
||||
_logger.Verbose($"Trying to connect with server ({_options.ChannelOptions}).");
|
||||
await _adapter.ConnectAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
||||
_logger.Verbose($"Trying to connect with server ({Options.ChannelOptions}).");
|
||||
await _adapter.ConnectAsync(Options.CommunicationTimeout, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
_logger.Verbose("Connection with server established.");
|
||||
|
||||
StartReceivingPackets(_cancellationTokenSource.Token);
|
||||
@@ -75,7 +76,7 @@ namespace MQTTnet.Client
|
||||
|
||||
_sendTracker.Restart();
|
||||
|
||||
if (_options.KeepAlivePeriod != TimeSpan.Zero)
|
||||
if (Options.KeepAlivePeriod != TimeSpan.Zero)
|
||||
{
|
||||
StartSendingKeepAliveMessages(_cancellationTokenSource.Token);
|
||||
}
|
||||
@@ -141,7 +142,7 @@ namespace MQTTnet.Client
|
||||
return subscribePacket.TopicFilters.Select((t, i) => new MqttSubscribeResult(t, response.SubscribeReturnCodes[i])).ToList();
|
||||
}
|
||||
|
||||
public async Task UnsubscribeAsync(IEnumerable<string> topicFilters)
|
||||
public Task UnsubscribeAsync(IEnumerable<string> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
@@ -153,7 +154,7 @@ namespace MQTTnet.Client
|
||||
TopicFilters = topicFilters.ToList()
|
||||
};
|
||||
|
||||
await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
return SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, _cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
public Task PublishAsync(MqttApplicationMessage applicationMessage)
|
||||
@@ -201,11 +202,11 @@ namespace MQTTnet.Client
|
||||
{
|
||||
var connectPacket = new MqttConnectPacket
|
||||
{
|
||||
ClientId = _options.ClientId,
|
||||
Username = _options.Credentials?.Username,
|
||||
Password = _options.Credentials?.Password,
|
||||
CleanSession = _options.CleanSession,
|
||||
KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds,
|
||||
ClientId = Options.ClientId,
|
||||
Username = Options.Credentials?.Username,
|
||||
Password = Options.Credentials?.Password,
|
||||
CleanSession = Options.CleanSession,
|
||||
KeepAlivePeriod = (ushort)Options.KeepAlivePeriod.TotalSeconds,
|
||||
WillMessage = willApplicationMessage
|
||||
};
|
||||
|
||||
@@ -241,14 +242,14 @@ namespace MQTTnet.Client
|
||||
|
||||
try
|
||||
{
|
||||
await WaitForTaskAsync(_packetReceiverTask, sender).ConfigureAwait(false);
|
||||
await WaitForTaskAsync(_keepAliveMessageSenderTask, sender).ConfigureAwait(false);
|
||||
|
||||
if (_adapter != null)
|
||||
{
|
||||
await _adapter.DisconnectAsync(_options.CommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
|
||||
await _adapter.DisconnectAsync(Options.CommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await WaitForTaskAsync(_packetReceiverTask, sender).ConfigureAwait(false);
|
||||
await WaitForTaskAsync(_keepAliveMessageSenderTask, sender).ConfigureAwait(false);
|
||||
|
||||
_logger.Verbose("Disconnected from adapter.");
|
||||
}
|
||||
catch (Exception adapterException)
|
||||
@@ -310,7 +311,7 @@ namespace MQTTnet.Client
|
||||
try
|
||||
{
|
||||
await _adapter.SendPacketAsync(requestPacket, cancellationToken).ConfigureAwait(false);
|
||||
var respone = await Internal.TaskExtensions.TimeoutAfterAsync(ct => packetAwaiter.Task, _options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||
var respone = await Internal.TaskExtensions.TimeoutAfterAsync(ct => packetAwaiter.Task, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return (TResponsePacket)respone;
|
||||
}
|
||||
@@ -327,16 +328,16 @@ namespace MQTTnet.Client
|
||||
|
||||
private async Task SendKeepAliveMessagesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Verbose("Start sending keep alive packets.");
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Verbose("Start sending keep alive packets.");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var keepAliveSendInterval = TimeSpan.FromSeconds(_options.KeepAlivePeriod.TotalSeconds * 0.75);
|
||||
if (_options.KeepAliveSendInterval.HasValue)
|
||||
var keepAliveSendInterval = TimeSpan.FromSeconds(Options.KeepAlivePeriod.TotalSeconds * 0.75);
|
||||
if (Options.KeepAliveSendInterval.HasValue)
|
||||
{
|
||||
keepAliveSendInterval = _options.KeepAliveSendInterval.Value;
|
||||
keepAliveSendInterval = Options.KeepAliveSendInterval.Value;
|
||||
}
|
||||
|
||||
var waitTime = keepAliveSendInterval - _sendTracker.Elapsed;
|
||||
@@ -381,10 +382,10 @@ namespace MQTTnet.Client
|
||||
|
||||
private async Task ReceivePacketsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Verbose("Start receiving packets.");
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Verbose("Start receiving packets.");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken)
|
||||
@@ -507,7 +508,7 @@ namespace MQTTnet.Client
|
||||
() => ReceivePacketsAsync(cancellationToken),
|
||||
cancellationToken,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
TaskScheduler.Default).Unwrap();
|
||||
}
|
||||
|
||||
private void StartSendingKeepAliveMessages(CancellationToken cancellationToken)
|
||||
@@ -516,7 +517,7 @@ namespace MQTTnet.Client
|
||||
() => SendKeepAliveMessagesAsync(cancellationToken),
|
||||
cancellationToken,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
TaskScheduler.Default).Unwrap();
|
||||
}
|
||||
|
||||
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket)
|
||||
@@ -525,7 +526,7 @@ namespace MQTTnet.Client
|
||||
{
|
||||
// TODO: Move conversion to formatter.
|
||||
var applicationMessage = publishPacket.ToApplicationMessage();
|
||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(_options.ClientId, applicationMessage));
|
||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(Options.ClientId, applicationMessage));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
@@ -17,7 +16,7 @@ namespace MQTTnet.Implementations
|
||||
{
|
||||
private readonly IMqttClientOptions _clientOptions;
|
||||
private readonly MqttClientTcpOptions _options;
|
||||
|
||||
|
||||
private Socket _socket;
|
||||
private Stream _stream;
|
||||
|
||||
@@ -87,8 +86,9 @@ namespace MQTTnet.Implementations
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Cleanup(ref _stream, (s) => s.Dispose());
|
||||
Cleanup(ref _socket, (s) => {
|
||||
Cleanup(ref _stream, s => s.Dispose());
|
||||
Cleanup(ref _socket, s =>
|
||||
{
|
||||
if (s.Connected)
|
||||
{
|
||||
s.Shutdown(SocketShutdown.Both);
|
||||
@@ -102,7 +102,7 @@ namespace MQTTnet.Implementations
|
||||
// Try the instance callback.
|
||||
if (_options.TlsOptions.CertificateValidationCallback != null)
|
||||
{
|
||||
return _options.TlsOptions.CertificateValidationCallback(x509Certificate, chain, sslPolicyErrors,_clientOptions);
|
||||
return _options.TlsOptions.CertificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _clientOptions);
|
||||
}
|
||||
|
||||
// Try static callback.
|
||||
|
||||
@@ -55,6 +55,40 @@ namespace MQTTnet.Internal
|
||||
_gate.WaitOne();
|
||||
}
|
||||
}
|
||||
|
||||
public TItem PeekAndWait()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (_items.Count > 0)
|
||||
{
|
||||
return _items.First.Value;
|
||||
}
|
||||
|
||||
if (_items.Count == 0)
|
||||
{
|
||||
_gate.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
_gate.WaitOne();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveFirst(Predicate<TItem> match)
|
||||
{
|
||||
if (match == null) throw new ArgumentNullException(nameof(match));
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (_items.Count > 0 && match(_items.First.Value))
|
||||
{
|
||||
_items.RemoveFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TItem RemoveFirst()
|
||||
{
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace MQTTnet.Server
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(() => RunAsync(keepAlivePeriod, cancellationToken), cancellationToken);
|
||||
|
||||
Task.Run(() => RunAsync(keepAlivePeriod, cancellationToken), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
@@ -50,6 +50,12 @@ namespace MQTTnet.Server
|
||||
_isPaused = false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_lastPacketReceivedTracker.Restart();
|
||||
_lastNonKeepAlivePacketReceivedTracker.Restart();
|
||||
}
|
||||
|
||||
public void PacketReceived(MqttBasePacket packet)
|
||||
{
|
||||
_lastPacketReceivedTracker.Restart();
|
||||
|
||||
@@ -9,6 +9,7 @@ using MQTTnet.Exceptions;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Serializer;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
@@ -17,6 +18,7 @@ namespace MQTTnet.Server
|
||||
private readonly MqttPacketIdentifierProvider _packetIdentifierProvider = new MqttPacketIdentifierProvider();
|
||||
|
||||
private readonly MqttRetainedMessagesManager _retainedMessagesManager;
|
||||
private readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
private readonly MqttClientKeepAliveMonitor _keepAliveMonitor;
|
||||
private readonly MqttClientPendingPacketsQueue _pendingPacketsQueue;
|
||||
private readonly MqttClientSubscriptionsManager _subscriptionsManager;
|
||||
@@ -28,29 +30,33 @@ namespace MQTTnet.Server
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private MqttApplicationMessage _willMessage;
|
||||
private bool _wasCleanDisconnect;
|
||||
private IMqttChannelAdapter _adapter;
|
||||
private Task _workerTask;
|
||||
private IDisposable _cleanupHandle;
|
||||
|
||||
private string _adapterEndpoint;
|
||||
private MqttProtocolVersion? _adapterProtocolVersion;
|
||||
|
||||
public MqttClientSession(
|
||||
string clientId,
|
||||
IMqttServerOptions options,
|
||||
MqttClientSessionsManager sessionsManager,
|
||||
MqttRetainedMessagesManager retainedMessagesManager,
|
||||
MqttServerEventDispatcher eventDispatcher,
|
||||
IMqttNetChildLogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_sessionsManager = sessionsManager;
|
||||
_sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
|
||||
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
||||
_eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher));
|
||||
|
||||
ClientId = clientId;
|
||||
|
||||
_logger = logger.CreateChildLogger(nameof(MqttClientSession));
|
||||
|
||||
_keepAliveMonitor = new MqttClientKeepAliveMonitor(this, _logger);
|
||||
_subscriptionsManager = new MqttClientSubscriptionsManager(clientId, _options, sessionsManager.Server);
|
||||
_subscriptionsManager = new MqttClientSubscriptionsManager(clientId, _options, eventDispatcher);
|
||||
_pendingPacketsQueue = new MqttClientPendingPacketsQueue(_options, this, _logger);
|
||||
}
|
||||
|
||||
@@ -59,9 +65,9 @@ namespace MQTTnet.Server
|
||||
public void FillStatus(MqttClientSessionStatus status)
|
||||
{
|
||||
status.ClientId = ClientId;
|
||||
status.IsConnected = _adapter != null;
|
||||
status.Endpoint = _adapter?.Endpoint;
|
||||
status.ProtocolVersion = _adapter?.PacketFormatterAdapter?.ProtocolVersion;
|
||||
status.IsConnected = _cancellationTokenSource != null;
|
||||
status.Endpoint = _adapterEndpoint;
|
||||
status.ProtocolVersion = _adapterProtocolVersion;
|
||||
status.PendingApplicationMessagesCount = _pendingPacketsQueue.Count;
|
||||
status.LastPacketReceived = _keepAliveMonitor.LastPacketReceived;
|
||||
status.LastNonKeepAlivePacketReceived = _keepAliveMonitor.LastNonKeepAlivePacketReceived;
|
||||
@@ -73,24 +79,154 @@ namespace MQTTnet.Server
|
||||
return _workerTask;
|
||||
}
|
||||
|
||||
private async Task RunInternalAsync(MqttApplicationMessage willMessage, int keepAlivePeriod, IMqttChannelAdapter adapter)
|
||||
public void Stop(MqttClientDisconnectType type)
|
||||
{
|
||||
Stop(type, false);
|
||||
}
|
||||
|
||||
public void EnqueueApplicationMessage(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
|
||||
{
|
||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
||||
|
||||
var checkSubscriptionsResult = _subscriptionsManager.CheckSubscriptions(publishPacket.Topic, publishPacket.QualityOfServiceLevel);
|
||||
if (!checkSubscriptionsResult.IsSubscribed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
publishPacket = new MqttPublishPacket
|
||||
{
|
||||
Topic = publishPacket.Topic,
|
||||
Payload = publishPacket.Payload,
|
||||
QualityOfServiceLevel = checkSubscriptionsResult.QualityOfServiceLevel,
|
||||
Retain = publishPacket.Retain,
|
||||
Dup = false
|
||||
};
|
||||
|
||||
if (publishPacket.QualityOfServiceLevel > 0)
|
||||
{
|
||||
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
|
||||
}
|
||||
|
||||
if (_options.ClientMessageQueueInterceptor != null)
|
||||
{
|
||||
var context = new MqttClientMessageQueueInterceptorContext(
|
||||
senderClientSession?.ClientId,
|
||||
ClientId,
|
||||
publishPacket.ToApplicationMessage());
|
||||
|
||||
_options.ClientMessageQueueInterceptor?.Invoke(context);
|
||||
|
||||
if (!context.AcceptEnqueue || context.ApplicationMessage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
publishPacket.Topic = context.ApplicationMessage.Topic;
|
||||
publishPacket.Payload = context.ApplicationMessage.Payload;
|
||||
publishPacket.QualityOfServiceLevel = context.ApplicationMessage.QualityOfServiceLevel;
|
||||
}
|
||||
|
||||
_pendingPacketsQueue.Enqueue(publishPacket);
|
||||
}
|
||||
|
||||
public Task SubscribeAsync(IList<TopicFilter> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
_subscriptionsManager.Subscribe(new MqttSubscribePacket
|
||||
{
|
||||
TopicFilters = topicFilters
|
||||
});
|
||||
|
||||
EnqueueSubscribedRetainedMessages(topicFilters);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task UnsubscribeAsync(IList<string> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
_subscriptionsManager.Unsubscribe(new MqttUnsubscribePacket
|
||||
{
|
||||
TopicFilters = topicFilters
|
||||
});
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void ClearPendingApplicationMessages()
|
||||
{
|
||||
_pendingPacketsQueue.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_pendingPacketsQueue?.Dispose();
|
||||
|
||||
_cancellationTokenSource?.Cancel ();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
|
||||
private void Stop(MqttClientDisconnectType type, bool isInsideSession)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cts = _cancellationTokenSource;
|
||||
if (cts == null || cts.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_cancellationTokenSource?.Cancel(false);
|
||||
|
||||
_wasCleanDisconnect = type == MqttClientDisconnectType.Clean;
|
||||
|
||||
if (_willMessage != null && !_wasCleanDisconnect)
|
||||
{
|
||||
_sessionsManager.EnqueueApplicationMessage(this, _willMessage.ToPublishPacket());
|
||||
}
|
||||
|
||||
_willMessage = null;
|
||||
|
||||
if (!isInsideSession)
|
||||
{
|
||||
_workerTask?.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_logger.Info("Client '{0}': Disconnected (clean={1}).", ClientId, _wasCleanDisconnect);
|
||||
_eventDispatcher.OnClientDisconnected(ClientId, _wasCleanDisconnect);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunInternalAsync(MqttConnectPacket connectPacket, IMqttChannelAdapter adapter)
|
||||
{
|
||||
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
|
||||
|
||||
try
|
||||
{
|
||||
_adapter = adapter;
|
||||
if (_cancellationTokenSource != null)
|
||||
{
|
||||
Stop(MqttClientDisconnectType.Clean, true);
|
||||
}
|
||||
|
||||
adapter.ReadingPacketStarted += OnAdapterReadingPacketStarted;
|
||||
adapter.ReadingPacketCompleted += OnAdapterReadingPacketCompleted;
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
//woraround for https://github.com/dotnet/corefx/issues/24430
|
||||
//workaround for https://github.com/dotnet/corefx/issues/24430
|
||||
#pragma warning disable 4014
|
||||
_cleanupHandle = _cancellationTokenSource.Token.Register(() => CleanupAsync());
|
||||
_cleanupHandle = _cancellationTokenSource.Token.Register(async () =>
|
||||
{
|
||||
await TryDisconnectAdapterAsync(adapter).ConfigureAwait(false);
|
||||
TryDisposeAdapter(adapter);
|
||||
});
|
||||
#pragma warning restore 4014
|
||||
//endworkaround
|
||||
//end workaround
|
||||
|
||||
_wasCleanDisconnect = false;
|
||||
_willMessage = willMessage;
|
||||
@@ -98,6 +234,9 @@ namespace MQTTnet.Server
|
||||
_pendingPacketsQueue.Start(adapter, _cancellationTokenSource.Token);
|
||||
_keepAliveMonitor.Start(keepAlivePeriod, _cancellationTokenSource.Token);
|
||||
|
||||
_adapterEndpoint = adapter.Endpoint;
|
||||
_adapterProtocolVersion = adapter.PacketSerializer.ProtocolVersion;
|
||||
|
||||
while (!_cancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
@@ -133,34 +272,35 @@ namespace MQTTnet.Server
|
||||
}
|
||||
finally
|
||||
{
|
||||
await CleanupAsync().ConfigureAwait(false);
|
||||
_adapterEndpoint = null;
|
||||
_adapterProtocolVersion = null;
|
||||
|
||||
// Uncomment as soon as the workaround above is no longer needed.
|
||||
//await TryDisconnectAdapterAsync(adapter).ConfigureAwait(false);
|
||||
//TryDisposeAdapter(adapter);
|
||||
|
||||
_cleanupHandle?.Dispose();
|
||||
_cleanupHandle = null;
|
||||
|
||||
_adapter = null;
|
||||
_cancellationTokenSource?.Cancel(false);
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CleanupAsync()
|
||||
private void TryDisposeAdapter(IMqttChannelAdapter adapter)
|
||||
{
|
||||
var adapter = _adapter;
|
||||
if (adapter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (adapter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_adapter = null;
|
||||
|
||||
adapter.ReadingPacketStarted -= OnAdapterReadingPacketStarted;
|
||||
adapter.ReadingPacketCompleted -= OnAdapterReadingPacketCompleted;
|
||||
|
||||
await adapter.DisconnectAsync(_options.DefaultCommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
|
||||
adapter.Dispose();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -231,65 +371,21 @@ namespace MQTTnet.Server
|
||||
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
|
||||
}
|
||||
|
||||
if (_options.ClientMessageQueueInterceptor != null)
|
||||
private async Task TryDisconnectAdapterAsync(IMqttChannelAdapter adapter)
|
||||
{
|
||||
if (adapter == null)
|
||||
{
|
||||
var context = new MqttClientMessageQueueInterceptorContext(
|
||||
senderClientSession?.ClientId,
|
||||
ClientId,
|
||||
publishPacket.ToApplicationMessage());
|
||||
|
||||
_options.ClientMessageQueueInterceptor?.Invoke(context);
|
||||
|
||||
if (!context.AcceptEnqueue || context.ApplicationMessage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
publishPacket.Topic = context.ApplicationMessage.Topic;
|
||||
publishPacket.Payload = context.ApplicationMessage.Payload;
|
||||
publishPacket.QualityOfServiceLevel = context.ApplicationMessage.QualityOfServiceLevel;
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingPacketsQueue.Enqueue(publishPacket);
|
||||
}
|
||||
|
||||
public Task SubscribeAsync(IList<TopicFilter> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
_subscriptionsManager.Subscribe(new MqttSubscribePacket
|
||||
try
|
||||
{
|
||||
TopicFilters = topicFilters
|
||||
});
|
||||
|
||||
EnqueueSubscribedRetainedMessages(topicFilters);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task UnsubscribeAsync(IList<string> topicFilters)
|
||||
{
|
||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||
|
||||
_subscriptionsManager.Unsubscribe(new MqttUnsubscribePacket
|
||||
await adapter.DisconnectAsync(_options.DefaultCommunicationTimeout, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
TopicFilters = topicFilters
|
||||
});
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void ClearPendingApplicationMessages()
|
||||
{
|
||||
_pendingPacketsQueue.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_pendingPacketsQueue?.Dispose();
|
||||
|
||||
_cancellationTokenSource?.Cancel ();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
_logger.Error(exception, "Error while disconnecting channel adapter.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessReceivedPacket(IMqttChannelAdapter adapter, MqttBasePacket packet, CancellationToken cancellationToken)
|
||||
@@ -366,7 +462,12 @@ namespace MQTTnet.Server
|
||||
var retainedMessages = _retainedMessagesManager.GetSubscribedMessages(topicFilters);
|
||||
foreach (var applicationMessage in retainedMessages)
|
||||
{
|
||||
EnqueueApplicationMessage(null, applicationMessage);
|
||||
var publishPacket = applicationMessage.ToPublishPacket();
|
||||
|
||||
// Set the retain flag to true according to [MQTT-3.3.1-8].
|
||||
publishPacket.Retain = true;
|
||||
|
||||
EnqueueApplicationMessage(null, publishPacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,25 +23,29 @@ namespace MQTTnet.Server
|
||||
private readonly Dictionary<string, MqttClientSession> _sessions = new Dictionary<string, MqttClientSession>();
|
||||
|
||||
private readonly CancellationToken _cancellationToken;
|
||||
private readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
|
||||
private readonly MqttRetainedMessagesManager _retainedMessagesManager;
|
||||
private readonly IMqttServerOptions _options;
|
||||
private readonly IMqttNetChildLogger _logger;
|
||||
|
||||
public MqttClientSessionsManager(IMqttServerOptions options, MqttServer server, MqttRetainedMessagesManager retainedMessagesManager, CancellationToken cancellationToken, IMqttNetChildLogger logger)
|
||||
public MqttClientSessionsManager(
|
||||
IMqttServerOptions options,
|
||||
MqttRetainedMessagesManager retainedMessagesManager,
|
||||
CancellationToken cancellationToken,
|
||||
MqttServerEventDispatcher eventDispatcher,
|
||||
IMqttNetChildLogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_cancellationToken = cancellationToken;
|
||||
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.CreateChildLogger(nameof(MqttClientSessionsManager));
|
||||
|
||||
_cancellationToken = cancellationToken;
|
||||
_eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher));
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
Server = server ?? throw new ArgumentNullException(nameof(server));
|
||||
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
||||
}
|
||||
|
||||
public MqttServer Server { get; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Task.Factory.StartNew(() => TryProcessQueuedApplicationMessages(_cancellationToken), _cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
@@ -62,7 +66,7 @@ namespace MQTTnet.Server
|
||||
|
||||
public Task StartSession(IMqttChannelAdapter clientAdapter)
|
||||
{
|
||||
return Task.Run(() => RunSession(clientAdapter, _cancellationToken), _cancellationToken);
|
||||
return Task.Run(() => RunSessionAsync(clientAdapter, _cancellationToken), _cancellationToken);
|
||||
}
|
||||
|
||||
public IList<IMqttClientSessionStatus> GetClientStatus()
|
||||
@@ -177,7 +181,7 @@ namespace MQTTnet.Server
|
||||
applicationMessage = interceptorContext.ApplicationMessage;
|
||||
}
|
||||
|
||||
Server.OnApplicationMessageReceived(sender?.ClientId, applicationMessage);
|
||||
_eventDispatcher.OnApplicationMessageReceived(sender?.ClientId, applicationMessage);
|
||||
|
||||
if (applicationMessage.Retain)
|
||||
{
|
||||
@@ -186,7 +190,12 @@ namespace MQTTnet.Server
|
||||
|
||||
foreach (var clientSession in GetSessions())
|
||||
{
|
||||
clientSession.EnqueueApplicationMessage(enqueuedApplicationMessage.Sender, applicationMessage);
|
||||
var publishPacket = applicationMessage.ToPublishPacket();
|
||||
|
||||
// Set the retain flag to true according to [MQTT-3.3.1-9].
|
||||
publishPacket.Retain = false;
|
||||
|
||||
clientSession.EnqueueApplicationMessage(enqueuedApplicationMessage.Sender, publishPacket);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -206,7 +215,7 @@ namespace MQTTnet.Server
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunSession(IMqttChannelAdapter clientAdapter, CancellationToken cancellationToken)
|
||||
private async Task RunSessionAsync(IMqttChannelAdapter clientAdapter, CancellationToken cancellationToken)
|
||||
{
|
||||
var clientId = string.Empty;
|
||||
|
||||
@@ -239,7 +248,6 @@ namespace MQTTnet.Server
|
||||
}
|
||||
|
||||
var result = PrepareClientSession(connectPacket);
|
||||
var clientSession = result.Session;
|
||||
|
||||
await clientAdapter.SendPacketAsync(
|
||||
new MqttConnAckPacket
|
||||
@@ -249,9 +257,10 @@ namespace MQTTnet.Server
|
||||
},
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
Server.OnClientConnected(clientId);
|
||||
_logger.Info("Client '{0}': Connected.", clientId);
|
||||
_eventDispatcher.OnClientConnected(clientId);
|
||||
|
||||
await clientSession.RunAsync(connectPacket.WillMessage, connectPacket.KeepAlivePeriod, clientAdapter).ConfigureAwait(false);
|
||||
await result.Session.RunAsync(connectPacket, clientAdapter).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -315,7 +324,7 @@ namespace MQTTnet.Server
|
||||
{
|
||||
isExistingSession = false;
|
||||
|
||||
clientSession = new MqttClientSession(connectPacket.ClientId, _options, this, _retainedMessagesManager, _logger);
|
||||
clientSession = new MqttClientSession(connectPacket.ClientId, _options, this, _retainedMessagesManager, _eventDispatcher, _logger);
|
||||
_sessions[connectPacket.ClientId] = clientSession;
|
||||
|
||||
_logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId);
|
||||
|
||||
@@ -10,14 +10,14 @@ namespace MQTTnet.Server
|
||||
{
|
||||
private readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
||||
private readonly IMqttServerOptions _options;
|
||||
private readonly MqttServer _server;
|
||||
private readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
private readonly string _clientId;
|
||||
|
||||
public MqttClientSubscriptionsManager(string clientId, IMqttServerOptions options, MqttServer server)
|
||||
public MqttClientSubscriptionsManager(string clientId, IMqttServerOptions options, MqttServerEventDispatcher eventDispatcher)
|
||||
{
|
||||
_clientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_server = server;
|
||||
_eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher));
|
||||
}
|
||||
|
||||
public MqttClientSubscribeResult Subscribe(MqttSubscribePacket subscribePacket)
|
||||
@@ -58,7 +58,7 @@ namespace MQTTnet.Server
|
||||
_subscriptions[topicFilter.Topic] = topicFilter.QualityOfServiceLevel;
|
||||
}
|
||||
|
||||
_server.OnClientSubscribedTopic(_clientId, topicFilter);
|
||||
_eventDispatcher.OnClientSubscribedTopic(_clientId, topicFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace MQTTnet.Server
|
||||
{
|
||||
_subscriptions.Remove(topicFilter);
|
||||
|
||||
_server.OnClientUnsubscribedTopic(_clientId, topicFilter);
|
||||
_eventDispatcher.OnClientUnsubscribedTopic(_clientId, topicFilter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace MQTTnet.Server
|
||||
{
|
||||
public class MqttServer : IMqttServer
|
||||
{
|
||||
private readonly MqttServerEventDispatcher _eventDispatcher = new MqttServerEventDispatcher();
|
||||
private readonly ICollection<IMqttServerAdapter> _adapters;
|
||||
private readonly IMqttNetChildLogger _logger;
|
||||
|
||||
@@ -21,10 +22,16 @@ namespace MQTTnet.Server
|
||||
public MqttServer(IEnumerable<IMqttServerAdapter> adapters, IMqttNetChildLogger logger)
|
||||
{
|
||||
if (adapters == null) throw new ArgumentNullException(nameof(adapters));
|
||||
_adapters = adapters.ToList();
|
||||
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.CreateChildLogger(nameof(MqttServer));
|
||||
|
||||
_adapters = adapters.ToList();
|
||||
_eventDispatcher.ClientConnected += (s, e) => ClientConnected?.Invoke(s, e);
|
||||
_eventDispatcher.ClientDisconnected += (s, e) => ClientDisconnected?.Invoke(s, e);
|
||||
_eventDispatcher.ClientSubscribedTopic += (s, e) => ClientSubscribedTopic?.Invoke(s, e);
|
||||
_eventDispatcher.ClientUnsubscribedTopic += (s, e) => ClientUnsubscribedTopic?.Invoke(s, e);
|
||||
_eventDispatcher.ApplicationMessageReceived += (s, e) => ApplicationMessageReceived?.Invoke(s, e);
|
||||
}
|
||||
|
||||
public event EventHandler Started;
|
||||
@@ -92,7 +99,7 @@ namespace MQTTnet.Server
|
||||
_retainedMessagesManager = new MqttRetainedMessagesManager(Options, _logger);
|
||||
await _retainedMessagesManager.LoadMessagesAsync().ConfigureAwait(false);
|
||||
|
||||
_clientSessionsManager = new MqttClientSessionsManager(Options, this, _retainedMessagesManager, _cancellationTokenSource.Token, _logger);
|
||||
_clientSessionsManager = new MqttClientSessionsManager(Options, _retainedMessagesManager, _cancellationTokenSource.Token, _eventDispatcher, _logger);
|
||||
_clientSessionsManager.Start();
|
||||
|
||||
foreach (var adapter in _adapters)
|
||||
@@ -144,33 +151,6 @@ namespace MQTTnet.Server
|
||||
return _retainedMessagesManager?.ClearMessagesAsync();
|
||||
}
|
||||
|
||||
internal void OnClientConnected(string clientId)
|
||||
{
|
||||
_logger.Info("Client '{0}': Connected.", clientId);
|
||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientId));
|
||||
}
|
||||
|
||||
internal void OnClientDisconnected(string clientId, bool wasCleanDisconnect)
|
||||
{
|
||||
_logger.Info("Client '{0}': Disconnected (clean={1}).", clientId, wasCleanDisconnect);
|
||||
ClientDisconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(clientId, wasCleanDisconnect));
|
||||
}
|
||||
|
||||
internal void OnClientSubscribedTopic(string clientId, TopicFilter topicFilter)
|
||||
{
|
||||
ClientSubscribedTopic?.Invoke(this, new MqttClientSubscribedTopicEventArgs(clientId, topicFilter));
|
||||
}
|
||||
|
||||
internal void OnClientUnsubscribedTopic(string clientId, string topicFilter)
|
||||
{
|
||||
ClientUnsubscribedTopic?.Invoke(this, new MqttClientUnsubscribedTopicEventArgs(clientId, topicFilter));
|
||||
}
|
||||
|
||||
internal void OnApplicationMessageReceived(string clientId, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(clientId, applicationMessage));
|
||||
}
|
||||
|
||||
private void OnClientAccepted(object sender, MqttServerAdapterClientAcceptedEventArgs eventArgs)
|
||||
{
|
||||
eventArgs.SessionTask = _clientSessionsManager.StartSession(eventArgs.Client);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public class MqttServerEventDispatcher
|
||||
{
|
||||
public event EventHandler<MqttClientSubscribedTopicEventArgs> ClientSubscribedTopic;
|
||||
|
||||
public event EventHandler<MqttClientUnsubscribedTopicEventArgs> ClientUnsubscribedTopic;
|
||||
|
||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
||||
|
||||
public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
|
||||
|
||||
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
|
||||
|
||||
public void OnClientSubscribedTopic(string clientId, TopicFilter topicFilter)
|
||||
{
|
||||
ClientSubscribedTopic?.Invoke(this, new MqttClientSubscribedTopicEventArgs(clientId, topicFilter));
|
||||
}
|
||||
|
||||
public void OnClientUnsubscribedTopic(string clientId, string topicFilter)
|
||||
{
|
||||
ClientUnsubscribedTopic?.Invoke(this, new MqttClientUnsubscribedTopicEventArgs(clientId, topicFilter));
|
||||
}
|
||||
|
||||
public void OnClientDisconnected(string clientId, bool wasCleanDisconnect)
|
||||
{
|
||||
ClientDisconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(clientId, wasCleanDisconnect));
|
||||
}
|
||||
|
||||
public void OnApplicationMessageReceived(string senderClientId, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(senderClientId, applicationMessage));
|
||||
}
|
||||
|
||||
public void OnClientConnected(string clientId)
|
||||
{
|
||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<DebugType>Full</DebugType>
|
||||
<TargetFramework>net461</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework Condition=" '$(OS)' == 'Windows_NT' ">net461</TargetFramework>
|
||||
<TargetFramework Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.1</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -8,6 +10,7 @@ using MQTTnet.Client;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Core.Tests
|
||||
{
|
||||
@@ -15,7 +18,7 @@ namespace MQTTnet.Core.Tests
|
||||
public class MqttClientTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task ClientDisconnectException()
|
||||
public async Task Client_Disconnect_Exception()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var client = factory.CreateMqttClient();
|
||||
@@ -39,9 +42,95 @@ namespace MQTTnet.Core.Tests
|
||||
Assert.IsInstanceOfType(ex.InnerException, typeof(SocketException));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Client_Publish()
|
||||
{
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
|
||||
try
|
||||
{
|
||||
var receivedMessages = new List<MqttApplicationMessage>();
|
||||
|
||||
await server.StartAsync(new MqttServerOptions());
|
||||
|
||||
var client1 = new MqttFactory().CreateMqttClient();
|
||||
client1.ApplicationMessageReceived += (_, e) =>
|
||||
{
|
||||
lock (receivedMessages)
|
||||
{
|
||||
receivedMessages.Add(e.ApplicationMessage);
|
||||
}
|
||||
};
|
||||
|
||||
await client1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build());
|
||||
await client1.SubscribeAsync("a");
|
||||
|
||||
var client2 = new MqttFactory().CreateMqttClient();
|
||||
await client2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build());
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithRetainFlag().Build();
|
||||
await client2.PublishAsync(message);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(1, receivedMessages.Count);
|
||||
Assert.IsFalse(receivedMessages.First().Retain); // Must be false even if set above!
|
||||
}
|
||||
finally
|
||||
{
|
||||
await server.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Publish_Special_Content()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var server = factory.CreateMqttServer();
|
||||
var serverOptions = new MqttServerOptionsBuilder().Build();
|
||||
|
||||
var receivedMessages = new List<MqttApplicationMessage>();
|
||||
|
||||
var client = factory.CreateMqttClient();
|
||||
|
||||
try
|
||||
{
|
||||
await server.StartAsync(serverOptions);
|
||||
|
||||
client.Connected += async (s, e) =>
|
||||
{
|
||||
await client.SubscribeAsync("RCU/P1/H0001/R0003");
|
||||
|
||||
var msg = new MqttApplicationMessageBuilder()
|
||||
.WithPayload("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|")
|
||||
.WithTopic("RCU/P1/H0001/R0003");
|
||||
|
||||
await client.PublishAsync(msg.Build());
|
||||
};
|
||||
|
||||
client.ApplicationMessageReceived += (s, e) =>
|
||||
{
|
||||
lock (receivedMessages)
|
||||
{
|
||||
receivedMessages.Add(e.ApplicationMessage);
|
||||
}
|
||||
};
|
||||
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(1, receivedMessages.Count);
|
||||
Assert.AreEqual("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|", receivedMessages.First().ConvertPayloadToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
await server.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
[TestMethod]
|
||||
public async Task ClientCleanupOnAuthentificationFails()
|
||||
public async Task Client_Cleanup_On_Authentification_Fails()
|
||||
{
|
||||
var channel = new TestMqttCommunicationAdapter();
|
||||
var channel2 = new TestMqttCommunicationAdapter();
|
||||
@@ -50,7 +139,10 @@ namespace MQTTnet.Core.Tests
|
||||
|
||||
Task.Run(async () => {
|
||||
var connect = await channel2.ReceivePacketAsync(TimeSpan.Zero, CancellationToken.None);
|
||||
await channel2.SendPacketAsync(new MqttConnAckPacket { ConnectReturnCode = Protocol.MqttConnectReturnCode.ConnectionRefusedNotAuthorized }, CancellationToken.None);
|
||||
await channel2.SendPacketAsync(new MqttConnAckPacket
|
||||
{
|
||||
ConnectReturnCode = Protocol.MqttConnectReturnCode.ConnectionRefusedNotAuthorized
|
||||
}, CancellationToken.None);
|
||||
});
|
||||
|
||||
var fake = new TestMqttCommunicationAdapterFactory(channel);
|
||||
|
||||
@@ -4,6 +4,7 @@ using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -227,6 +228,39 @@ namespace MQTTnet.Core.Tests
|
||||
|
||||
Assert.AreEqual(2000, receivedMessagesCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_SessionTakeover()
|
||||
{
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
try
|
||||
{
|
||||
await server.StartAsync(new MqttServerOptions());
|
||||
|
||||
var client1 = new MqttFactory().CreateMqttClient();
|
||||
var client2 = new MqttFactory().CreateMqttClient();
|
||||
|
||||
var options = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost")
|
||||
.WithCleanSession(false)
|
||||
.WithClientId("a").Build();
|
||||
|
||||
await client1.ConnectAsync(options);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
await client2.ConnectAsync(options);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsFalse(client1.IsConnected);
|
||||
Assert.IsTrue(client2.IsConnected);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await server.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task Publish(IMqttClient c1, MqttApplicationMessage message)
|
||||
{
|
||||
@@ -267,11 +301,6 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public async Task MqttServer_HandleCleanDisconnect()
|
||||
{
|
||||
MqttNetGlobalLogger.LogMessagePublished += (_, e) =>
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[{e.TraceMessage.Timestamp:s}] {e.TraceMessage.Source} {e.TraceMessage.Message}");
|
||||
};
|
||||
|
||||
var serverAdapter = new MqttTcpServerAdapter(new MqttNetLogger().CreateChildLogger());
|
||||
var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
|
||||
|
||||
@@ -304,6 +333,51 @@ namespace MQTTnet.Core.Tests
|
||||
Assert.AreEqual(clientConnectedCalled, clientDisconnectedCalled);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_Client_Disconnect_Without_Errors()
|
||||
{
|
||||
var errors = 0;
|
||||
|
||||
MqttNetGlobalLogger.LogMessagePublished += (_, e) =>
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[{e.TraceMessage.Timestamp:s}] {e.TraceMessage.Source} {e.TraceMessage.Message}");
|
||||
|
||||
if (e.TraceMessage.Level == MqttNetLogLevel.Error)
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
};
|
||||
|
||||
bool clientWasConnected;
|
||||
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
try
|
||||
{
|
||||
var options = new MqttServerOptionsBuilder().Build();
|
||||
await server.StartAsync(options);
|
||||
|
||||
var client = new MqttFactory().CreateMqttClient();
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost")
|
||||
.Build();
|
||||
|
||||
await client.ConnectAsync(clientOptions);
|
||||
|
||||
clientWasConnected = true;
|
||||
|
||||
await client.DisconnectAsync();
|
||||
|
||||
await Task.Delay(500);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await server.StopAsync();
|
||||
}
|
||||
|
||||
Assert.IsTrue(clientWasConnected);
|
||||
Assert.AreEqual(0, errors);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_LotsOfRetainedMessages()
|
||||
{
|
||||
@@ -389,6 +463,8 @@ namespace MQTTnet.Core.Tests
|
||||
}
|
||||
|
||||
await c2.DisconnectAsync();
|
||||
|
||||
await s.StopAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -427,7 +503,7 @@ namespace MQTTnet.Core.Tests
|
||||
var serverAdapter = new TestMqttServerAdapter();
|
||||
var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
|
||||
|
||||
var receivedMessagesCount = 0;
|
||||
var receivedMessages = new List<MqttApplicationMessage>();
|
||||
try
|
||||
{
|
||||
await s.StartAsync(new MqttServerOptions());
|
||||
@@ -437,7 +513,14 @@ namespace MQTTnet.Core.Tests
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
var c2 = await serverAdapter.ConnectTestClient("c2");
|
||||
c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
|
||||
c2.ApplicationMessageReceived += (_, e) =>
|
||||
{
|
||||
lock (receivedMessages)
|
||||
{
|
||||
receivedMessages.Add(e.ApplicationMessage);
|
||||
}
|
||||
};
|
||||
|
||||
await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
|
||||
|
||||
await Task.Delay(500);
|
||||
@@ -447,7 +530,8 @@ namespace MQTTnet.Core.Tests
|
||||
await s.StopAsync();
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
Assert.AreEqual(1, receivedMessages.Count);
|
||||
Assert.IsTrue(receivedMessages.First().Retain);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -655,26 +739,29 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public async Task MqttServer_SameClientIdConnectDisconnectEventOrder()
|
||||
{
|
||||
var serverAdapter = new MqttTcpServerAdapter(new MqttNetLogger().CreateChildLogger());
|
||||
var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
|
||||
var s = new MqttFactory().CreateMqttServer();
|
||||
|
||||
var connectedClient = false;
|
||||
var connecteCalledBeforeConnectedClients = false;
|
||||
var events = new List<string>();
|
||||
|
||||
s.ClientConnected += (_, __) =>
|
||||
{
|
||||
connecteCalledBeforeConnectedClients |= connectedClient;
|
||||
connectedClient = true;
|
||||
lock (events)
|
||||
{
|
||||
events.Add("c");
|
||||
}
|
||||
};
|
||||
|
||||
s.ClientDisconnected += (_, __) =>
|
||||
{
|
||||
connectedClient = false;
|
||||
lock (events)
|
||||
{
|
||||
events.Add("d");
|
||||
}
|
||||
};
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost")
|
||||
.WithClientId(Guid.NewGuid().ToString())
|
||||
.WithClientId("same_id")
|
||||
.Build();
|
||||
|
||||
await s.StartAsync(new MqttServerOptions());
|
||||
@@ -684,20 +771,24 @@ namespace MQTTnet.Core.Tests
|
||||
|
||||
await c1.ConnectAsync(clientOptions);
|
||||
|
||||
await Task.Delay(100);
|
||||
await Task.Delay(250);
|
||||
|
||||
await c2.ConnectAsync(clientOptions);
|
||||
|
||||
await Task.Delay(100);
|
||||
await Task.Delay(250);
|
||||
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
await Task.Delay(250);
|
||||
|
||||
await c2.DisconnectAsync();
|
||||
|
||||
await Task.Delay(250);
|
||||
|
||||
await s.StopAsync();
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.IsFalse(connecteCalledBeforeConnectedClients, "ClientConnected was called before ClientDisconnect was called");
|
||||
var flow = string.Join(string.Empty, events);
|
||||
Assert.AreEqual("cdcd", flow);
|
||||
}
|
||||
|
||||
|
||||
@@ -725,6 +816,8 @@ namespace MQTTnet.Core.Tests
|
||||
await server.StartAsync(new MqttServerOptions());
|
||||
var client3 = new MqttFactory().CreateMqttClient();
|
||||
await client3.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
|
||||
await server.StopAsync();
|
||||
}
|
||||
|
||||
private class TestStorage : IMqttServerStorage
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
@@ -13,7 +11,7 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public void MqttSubscriptionsManager_SubscribeSingleSuccess()
|
||||
{
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServer(new IMqttServerAdapter[0], new MqttNetLogger().CreateChildLogger("")));
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServerEventDispatcher());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new TopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
@@ -28,7 +26,7 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public void MqttSubscriptionsManager_SubscribeDifferentQoSSuccess()
|
||||
{
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServer(new IMqttServerAdapter[0], new MqttNetLogger().CreateChildLogger("")));
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServerEventDispatcher());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new TopicFilter("A/B/C", MqttQualityOfServiceLevel.AtMostOnce));
|
||||
@@ -43,7 +41,7 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public void MqttSubscriptionsManager_SubscribeTwoTimesSuccess()
|
||||
{
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServer(new IMqttServerAdapter[0], new MqttNetLogger().CreateChildLogger("")));
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServerEventDispatcher());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new TopicFilter("#", MqttQualityOfServiceLevel.AtMostOnce));
|
||||
@@ -59,7 +57,7 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public void MqttSubscriptionsManager_SubscribeSingleNoSuccess()
|
||||
{
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServer(new IMqttServerAdapter[0], new MqttNetLogger().CreateChildLogger("")));
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServerEventDispatcher());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new TopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
@@ -72,7 +70,7 @@ namespace MQTTnet.Core.Tests
|
||||
[TestMethod]
|
||||
public void MqttSubscriptionsManager_SubscribeAndUnsubscribeSingle()
|
||||
{
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServer(new IMqttServerAdapter[0], new MqttNetLogger().CreateChildLogger("")));
|
||||
var sm = new MqttClientSubscriptionsManager("", new MqttServerOptions(), new MqttServerEventDispatcher());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new TopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<DebugType>Full</DebugType>
|
||||
<TargetFrameworks>netcoreapp2.1;net452;net461</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netcoreapp2.1|AnyCPU'">
|
||||
|
||||
@@ -61,13 +61,7 @@ namespace MQTTnet.TestApp.NetCore
|
||||
|
||||
public class RandomPassword : IMqttClientCredentials
|
||||
{
|
||||
public string Password
|
||||
{
|
||||
get
|
||||
{
|
||||
return Guid.NewGuid().ToString(); // The random password.
|
||||
}
|
||||
}
|
||||
public string Password => Guid.NewGuid().ToString();
|
||||
|
||||
public string Username => "the_static_user";
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ image: Visual Studio 2017
|
||||
configuration: Release
|
||||
before_build:
|
||||
- cmd: >-
|
||||
msbuild /t:restore
|
||||
msbuild /t:restore MQTTnet.sln
|
||||
|
||||
cd Tests/MQTTnet.TestApp.AspNetCore2/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user