mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-18 02:13:00 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a26b641284 | ||
|
|
7be3685850 | ||
|
|
1a6be47144 | ||
|
|
5d73de2a86 | ||
|
|
2eaebe0e6a | ||
|
|
d7b552fce2 | ||
|
|
bea6d75251 | ||
|
|
f7db00c08e | ||
|
|
f259bbcc9b | ||
|
|
252772007b | ||
|
|
21a9974e5d | ||
|
|
d63143bdc9 | ||
|
|
aad9eac361 | ||
|
|
e8a683b936 | ||
|
|
e475e36ce7 | ||
|
|
611c230da2 | ||
|
|
18839de083 | ||
|
|
194664bc9c | ||
|
|
10a33fd153 | ||
|
|
868aa7d89a | ||
|
|
1f8792cf87 | ||
|
|
7bb99c8b37 | ||
|
|
7f5504b01b | ||
|
|
fd789417e7 | ||
|
|
f1f9924bce | ||
|
|
b0c603082b | ||
|
|
f3f10e9f65 | ||
|
|
beb228cc05 | ||
|
|
7a7f0640ba | ||
|
|
55d009ce6b | ||
|
|
e23ac4f703 | ||
|
|
fc367ddb64 | ||
|
|
cf217034fa | ||
|
|
6b6627f823 | ||
|
|
4f51a238b3 | ||
|
|
733c587e45 | ||
|
|
3260920828 | ||
|
|
4e6aeb91a4 | ||
|
|
5056843611 | ||
|
|
a65c015a58 | ||
|
|
e63f26789f | ||
|
|
9a598892a7 | ||
|
|
857ab005be | ||
|
|
33e4ec1943 | ||
|
|
6a564a0c72 | ||
|
|
3a4dce5080 | ||
|
|
4e6118d324 | ||
|
|
269bfa09ac | ||
|
|
59dd6b98a3 | ||
|
|
9f37306f20 | ||
|
|
85b000c6b7 | ||
|
|
5a919ce5d2 | ||
|
|
57ab8e5abc | ||
|
|
8f6d48be81 | ||
|
|
38cfa15cc3 | ||
|
|
6adf7096ec | ||
|
|
df149eb0b3 | ||
|
|
63c9329190 | ||
|
|
246a10649a | ||
|
|
0a76ac15c6 | ||
|
|
d801af5616 | ||
|
|
257211fc7a | ||
|
|
a407fc381b | ||
|
|
4fa275bf2b | ||
|
|
7cf12dc751 | ||
|
|
40aefd0ad3 | ||
|
|
c20142671f | ||
|
|
75dfe68a94 | ||
|
|
92518fc4ec | ||
|
|
16180e83ba | ||
|
|
c779b394f1 | ||
|
|
e60a732b61 | ||
|
|
7ea9415c63 | ||
|
|
13c399bc9a | ||
|
|
4565c3990a | ||
|
|
2bd2648b48 | ||
|
|
1b56155f1c | ||
|
|
626930cfae | ||
|
|
6cf9cb0af2 | ||
|
|
60941c04e5 | ||
|
|
ba68b1274b | ||
|
|
dbe12b9c48 | ||
|
|
52b79a140b | ||
|
|
c270225e9e | ||
|
|
3f5d4e9825 | ||
|
|
e80d19ba9b | ||
|
|
48837529a2 | ||
|
|
43e3ad4c00 | ||
|
|
08c9ecb011 | ||
|
|
763f0e7934 | ||
|
|
9d381c2cf9 | ||
|
|
17ceb20169 | ||
|
|
683bb43486 | ||
|
|
d25b51740b | ||
|
|
a58ab607ad | ||
|
|
0a7d450f3b | ||
|
|
999fa7a468 | ||
|
|
f0a1f9ca93 | ||
|
|
89e9cb224f | ||
|
|
fe48c9c837 | ||
|
|
2a421d1d42 | ||
|
|
48d0344a40 | ||
|
|
db5ed594f7 | ||
|
|
f85bc9b956 | ||
|
|
eec46dd9bc | ||
|
|
9c9e2293c8 | ||
|
|
856861e1b1 | ||
|
|
4b481b4833 | ||
|
|
c05f11a495 | ||
|
|
e798c91ff3 | ||
|
|
5df4fc3d5d | ||
|
|
c6236c0865 | ||
|
|
85c0cb3bcc | ||
|
|
9810e52bcb | ||
|
|
948a5eaae3 | ||
|
|
31df8247fa | ||
|
|
229418100c | ||
|
|
93d8679bbc | ||
|
|
6cec126862 | ||
|
|
9749f790ea | ||
|
|
fbbc638c75 | ||
|
|
bf679adb6b | ||
|
|
cf7e59a774 | ||
|
|
e9724c0202 | ||
|
|
7931af7487 | ||
|
|
bb5f023b74 | ||
|
|
c2ac4fffaf | ||
|
|
4b78710705 | ||
|
|
2e69f8be78 | ||
|
|
2d6c44e45b | ||
|
|
fc3965f5a3 | ||
|
|
1d553c5ece | ||
|
|
07ad9fc557 | ||
|
|
f001d7aecc | ||
|
|
d49a4384c0 | ||
|
|
4e6658e014 | ||
|
|
2b2b30912c | ||
|
|
79d95c8516 | ||
|
|
88e8691ce0 | ||
|
|
28641892f5 | ||
|
|
c10145f743 |
@@ -0,0 +1,5 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
|
||||||
|
# CA1031: Do not catch general exception types
|
||||||
|
dotnet_diagnostic.CA1031.severity = none
|
||||||
@@ -3,24 +3,26 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.AspNetCore</id>
|
<id>MQTTnet.AspNetCore</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<icon>images\Logo_128x128.png</icon>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is a support library to integrate MQTTnet into AspNetCore.</description>
|
<description>This is a support library to integrate MQTTnet into AspNetCore.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</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>
|
<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 Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<group targetFramework="netstandard2.0">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="3.1.3" />
|
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.0" />
|
||||||
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.1.0" />
|
</group>
|
||||||
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.2.1" />
|
|
||||||
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="3.1.3" />
|
<group targetFramework="netcoreapp3.1">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
</group>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
@@ -33,5 +35,8 @@
|
|||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\"/>
|
||||||
|
|
||||||
|
<!-- .NET Core App 3.1 -->
|
||||||
|
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.*" target="lib\netcoreapp3.1\"/>
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
||||||
|
|||||||
@@ -3,17 +3,17 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.ManagedClient</id>
|
<id>MQTTnet.Extensions.ManagedClient</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<icon>images\Logo_128x128.png</icon>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description>
|
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</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>
|
<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 Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -3,17 +3,17 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.Rpc</id>
|
<id>MQTTnet.Extensions.Rpc</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<icon>images\Logo_128x128.png</icon>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
|
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</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>
|
<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 Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -3,19 +3,34 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.WebSocket4Net</id>
|
<id>MQTTnet.Extensions.WebSocket4Net</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<icon>images\Logo_128x128.png</icon>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description>
|
<description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</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>
|
<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 Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<group targetFramework="netstandard1.3">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="WebSocket4Net" version="0.15.2" />
|
||||||
|
</group>
|
||||||
|
<group targetFramework="netstandard2.0">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="WebSocket4Net" version="0.15.2" />
|
||||||
|
</group>
|
||||||
|
<group targetFramework="netstandard2.1">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="WebSocket4Net" version="0.15.2" />
|
||||||
|
</group>
|
||||||
|
<group targetFramework="uap10.0">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="WebSocket4Net" version="0.15.2" />
|
||||||
|
</group>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<package >
|
|
||||||
<metadata>
|
|
||||||
<id>MQTTnet.NETStandard</id>
|
|
||||||
<version>0.0.0</version>
|
|
||||||
<authors>Christian Kratky</authors>
|
|
||||||
<owners>Christian Kratky</owners>
|
|
||||||
<license type="file">LICENSE</license>
|
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
|
||||||
<icon>images\Logo_128x128.png</icon>
|
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
|
||||||
<description>This package contains the .NET Standard version of MQTTnet only.</description>
|
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</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>
|
|
||||||
<group targetFramework="netstandard1.3">
|
|
||||||
<dependency id="NETStandard.Library" version="1.3.0" />
|
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
|
||||||
</group>
|
|
||||||
<group targetFramework="netstandard2.0">
|
|
||||||
<dependency id="NETStandard.Library" version="2.0.0" />
|
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
|
||||||
</group>
|
|
||||||
</dependencies>
|
|
||||||
</metadata>
|
|
||||||
|
|
||||||
<files>
|
|
||||||
<!-- License -->
|
|
||||||
<file src="..\LICENSE" />
|
|
||||||
|
|
||||||
<!-- Images -->
|
|
||||||
<file src="..\Images\Logo_128x128.png" target="images\" />
|
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
|
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
+28
-23
@@ -3,38 +3,25 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet</id>
|
<id>MQTTnet</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<icon>images\Logo_128x128.png</icon>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
|
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
|
||||||
<releaseNotes>
|
<releaseNotes>
|
||||||
* [All] Due to a merge issue not all changes are included in 3.0.8. All these changes are now included in this version.
|
* [Client] Fixed wrong value for "ClientWasConnected" in "MqttClientDisconnectedEventArgs" #976 (thanks to @dbeinder).
|
||||||
* [Core] Updated all nuget references.
|
* [Client] Added direct support for Amazon AWS connections (requires .NET Core 3.1) (thanks to @henning-krause).
|
||||||
* [Core] Added MqttApplicationMessage.GetUserProperty() convenience method (thanks to @PMExtra).
|
* [Client] handle disconnect package and propagate disconnect reason code (thanks to @JanEggers)
|
||||||
* [LowLevelMqttClient] Added low level MQTT client in order to provide more flexibility when using the MQTT protocol. This client requires detailed knowledge about the MQTT protocol.
|
* [ManagedClient] Exposed the internal MQTT client.
|
||||||
* [Client] Improve connection stability (thanks to @jltjohanlindqvist).
|
* [Server] Added client message queue interceptor for QoS level (thanks to @msallin).
|
||||||
* [Client] Support WithConnectionUri to configure client (thanks to @PMExtra).
|
* [Server] improved behavior when multiple connections fight over a session (thanks to @JanEggers)
|
||||||
* [Client] Support PublishAsync with QoS 1 and QoS 2 from within an ApplicationMessageReceivedHandler (#648, #587, thanks to @PSanetra).
|
* [Server] Exposed _ClientDisconnectedInterceptor_ (thanks to @SeppPenner).
|
||||||
* [Client] Fixed MqttCommunicationTimedOutExceptions, caused by a long running ApplicationMessageReceivedHandler, which blocked MQTT packets from being processed (#829, thanks to @PSanetra).
|
|
||||||
* [ManagedClient] Added builder class for MqttClientUnsubscribeOptions (thanks to @dominikviererbe).
|
|
||||||
* [ManagedClient] Added support for persisted sessions (thansk to @PMExtra).
|
|
||||||
* [ManagedClient] Fixed a memory leak (thanks to @zawodskoj).
|
|
||||||
* [ManagedClient] Improved internal subscription management (#569, thanks to @cstichlberger).
|
|
||||||
* [ManagedClient] Refactored log messages (thanks to @cstichlberger).
|
|
||||||
* [Server] Added support for assigned client IDs (MQTTv5 only) (thanks to @bcrosnier).
|
|
||||||
* [Server] Added interceptor for unsubscriptions.
|
|
||||||
* [Server] Removed exceptions when user properties are set with MQTT protocol version 3.1
|
|
||||||
* [Server] Added custom session items to the client status.
|
|
||||||
* [Server] Added option to check whether the server is already started properly or not.
|
|
||||||
* [MQTTnet.AspNetCore] improved compatibility with AspNetCore 3.1
|
|
||||||
* [MQTTnet.Server] Added interceptor for unsubscriptions.
|
|
||||||
</releaseNotes>
|
</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</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>
|
<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 Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<group targetFramework="netstandard1.3">
|
<group targetFramework="netstandard1.3">
|
||||||
<dependency id="NETStandard.Library" version="1.3.0" />
|
<dependency id="NETStandard.Library" version="1.3.0" />
|
||||||
@@ -48,6 +35,18 @@
|
|||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
||||||
</group>
|
</group>
|
||||||
|
<group targetFramework="netstandard2.1">
|
||||||
|
<dependency id="NETStandard.Library" version="2.0.0" />
|
||||||
|
<dependency id="System.Net.Security" version="4.3.2" />
|
||||||
|
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
||||||
|
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
||||||
|
</group>
|
||||||
|
<group targetFramework="netcoreapp3.1">
|
||||||
|
<dependency id="NETStandard.Library" version="2.0.0" />
|
||||||
|
<dependency id="System.Net.Security" version="4.3.2" />
|
||||||
|
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
||||||
|
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
||||||
|
</group>
|
||||||
<group targetFramework="uap10.0">
|
<group targetFramework="uap10.0">
|
||||||
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.10" />
|
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.10" />
|
||||||
</group>
|
</group>
|
||||||
@@ -67,6 +66,12 @@
|
|||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
|
||||||
|
|
||||||
|
<!-- .NET Standard 2.1 -->
|
||||||
|
<file src="..\Source\MQTTnet\bin\Release\netstandard2.1\MQTTnet.*" target="lib\netstandard2.1\"/>
|
||||||
|
|
||||||
|
<!-- .NET Standard 3.1 -->
|
||||||
|
<file src="..\Source\MQTTnet\bin\Release\netcoreapp3.1\MQTTnet.*" target="lib\netcoreapp3.1\"/>
|
||||||
|
|
||||||
<!-- Universal Windows -->
|
<!-- Universal Windows -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\"/>
|
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\"/>
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -28,16 +28,20 @@ vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\M
|
|||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the ASP.NET Core 2.0 extension
|
# Build the ASP.NET Core 2.0 extension
|
||||||
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the RPC extension
|
# Build the RPC extension
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the Managed Client extension
|
# Build the Managed Client extension
|
||||||
@@ -45,6 +49,7 @@ vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\M
|
|||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the WebSocket4Net extension
|
# Build the WebSocket4Net extension
|
||||||
@@ -52,6 +57,7 @@ vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\M
|
|||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Create NuGet packages.
|
# Create NuGet packages.
|
||||||
@@ -69,7 +75,6 @@ Copy-Item MQTTnet.Extensions.WebSocket4Net.nuspec -Destination MQTTnet.Extension
|
|||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path .\NuGet
|
New-Item -ItemType Directory -Force -Path .\NuGet
|
||||||
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.NETStandard.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
|
||||||
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
MQTTnet Copyright (c) 2016-2019 Christian Kratky
|
Copyright (c) 2016-2019 Christian Kratky
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+61
-1
@@ -20,7 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1
|
|||||||
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
|
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
|
||||||
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
|
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
|
||||||
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec
|
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec
|
||||||
Build\MQTTnet.NETStandard.nuspec = Build\MQTTnet.NETStandard.nuspec
|
|
||||||
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
|
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
|
||||||
Build\upload.ps1 = Build\upload.ps1
|
Build\upload.ps1 = Build\upload.ps1
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
@@ -28,6 +27,7 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.bettercodehub.yml = .bettercodehub.yml
|
.bettercodehub.yml = .bettercodehub.yml
|
||||||
|
.editorconfig = .editorconfig
|
||||||
appveyor.yml = appveyor.yml
|
appveyor.yml = appveyor.yml
|
||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
@@ -55,6 +55,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocke
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{A56E3128-1639-4F31-873A-325E14BB6295}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{A56E3128-1639-4F31-873A-325E14BB6295}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Server", "Tests\MQTTnet.Test.BlazorApp\Server\MQTTnet.Test.BlazorApp.Server.csproj", "{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Client", "Tests\MQTTnet.Test.BlazorApp\Client\MQTTnet.Test.BlazorApp.Client.csproj", "{D260D63D-7902-4C55-9665-84C5CACBBB24}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Shared", "Tests\MQTTnet.Test.BlazorApp\Shared\MQTTnet.Test.BlazorApp.Shared.csproj", "{DDB069BA-6E1A-48C7-B374-5D903B553CAD}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -266,6 +274,54 @@ Global
|
|||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -283,6 +339,10 @@ Global
|
|||||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {A56E3128-1639-4F31-873A-325E14BB6295}
|
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {A56E3128-1639-4F31-873A-325E14BB6295}
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
||||||
|
{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
|
|||||||
* Uniform API across all supported versions of the MQTT protocol
|
* Uniform API across all supported versions of the MQTT protocol
|
||||||
* Interfaces included for mocking and testing
|
* Interfaces included for mocking and testing
|
||||||
* Access to internal trace messages
|
* Access to internal trace messages
|
||||||
* Unit tested (~210 tests)
|
* Unit tested (~250 tests)
|
||||||
* No external dependencies
|
* No external dependencies
|
||||||
|
|
||||||
\* Tested on local machine (Intel i7 8700K) with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetCore_.
|
\* Tested on local machine (Intel i7 8700K) with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetCore_.
|
||||||
@@ -34,7 +34,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
|
|||||||
### Client
|
### Client
|
||||||
|
|
||||||
* Communication via TCP (+TLS) or WS (WebSocket) supported
|
* Communication via TCP (+TLS) or WS (WebSocket) supported
|
||||||
* Included core _MqttClient_ with low level functionality
|
* Included core _LowLevelMqttClient_ with low level functionality
|
||||||
* Also included _ManagedMqttClient_ which maintains the connection and subscriptions automatically. Also application messages are queued and re-scheduled for higher QoS levels automatically.
|
* Also included _ManagedMqttClient_ which maintains the connection and subscriptions automatically. Also application messages are queued and re-scheduled for higher QoS levels automatically.
|
||||||
* Rx support (via another project)
|
* Rx support (via another project)
|
||||||
* Compatible with Microsoft Azure IoT Hub
|
* Compatible with Microsoft Azure IoT Hub
|
||||||
@@ -72,6 +72,7 @@ _MQTTnet Server_ is a standalone cross platform MQTT server (like mosquitto) bas
|
|||||||
* Universal Windows Platform (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU, Windows 10 IoT Core)
|
* Universal Windows Platform (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU, Windows 10 IoT Core)
|
||||||
* Xamarin.Android 7.5+
|
* Xamarin.Android 7.5+
|
||||||
* Xamarin.iOS 10.14+
|
* Xamarin.iOS 10.14+
|
||||||
|
* Blazor WebAssembly 3.2.0
|
||||||
|
|
||||||
## Supported MQTT versions
|
## Supported MQTT versions
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ If you use this library and want to see your project here please create a pull r
|
|||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
MQTTnet Copyright (c) 2016-2019 Christian Kratky
|
MQTTnet Copyright (c) 2016-2020 Christian Kratky
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.AspNetCore.Client.Tcp;
|
using MQTTnet.AspNetCore.Client.Tcp;
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Diagnostics;
|
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -10,7 +9,7 @@ namespace MQTTnet.AspNetCore.Client
|
|||||||
{
|
{
|
||||||
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
|
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetLogger logger)
|
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace MQTTnet.AspNetCore.Client.Tcp
|
|||||||
#if NETCOREAPP3_1
|
#if NETCOREAPP3_1
|
||||||
public override ValueTask DisposeAsync()
|
public override ValueTask DisposeAsync()
|
||||||
#else
|
#else
|
||||||
public new Task DisposeAsync()
|
public Task DisposeAsync()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
IsConnected = false;
|
IsConnected = false;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ApplicationBuilderExtensions
|
public static class ApplicationBuilderExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ConnectionBuilderExtensions
|
public static class ConnectionBuilderExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Connections;
|
using Microsoft.AspNetCore.Http.Connections;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
#if NETCOREAPP3_1
|
||||||
|
using System;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ConnectionRouteBuilderExtensions
|
public static class ConnectionRouteBuilderExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using MQTTnet.Exceptions;
|
|||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ReaderExtensions
|
public static class ReaderExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,23 +8,25 @@
|
|||||||
<PackageId />
|
<PackageId />
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
|
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
|
||||||
<PackageReference Include="System.IO.Pipelines" Version="4.7.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.3" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.3" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -10,11 +10,19 @@ using System.IO.Pipelines;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.AspNetCore.Extensions;
|
||||||
|
using MQTTnet.Internal;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore
|
||||||
{
|
{
|
||||||
public class MqttConnectionContext : IMqttChannelAdapter
|
public sealed class MqttConnectionContext : IMqttChannelAdapter
|
||||||
{
|
{
|
||||||
|
readonly AsyncLock _writerLock = new AsyncLock();
|
||||||
|
readonly SpanBasedMqttPacketBodyReader _reader;
|
||||||
|
|
||||||
|
PipeReader _input;
|
||||||
|
PipeWriter _output;
|
||||||
|
|
||||||
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
|
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
|
||||||
{
|
{
|
||||||
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
|
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
|
||||||
@@ -25,18 +33,20 @@ namespace MQTTnet.AspNetCore
|
|||||||
_input = Connection.Transport.Input;
|
_input = Connection.Transport.Input;
|
||||||
_output = Connection.Transport.Output;
|
_output = Connection.Transport.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
_reader = new SpanBasedMqttPacketBodyReader();
|
_reader = new SpanBasedMqttPacketBodyReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PipeReader _input;
|
|
||||||
private PipeWriter _output;
|
|
||||||
private readonly SpanBasedMqttPacketBodyReader _reader;
|
|
||||||
|
|
||||||
public string Endpoint
|
public string Endpoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
if (Connection?.RemoteEndPoint != null)
|
||||||
|
{
|
||||||
|
return Connection.RemoteEndPoint.ToString();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
var connection = Http?.HttpContext?.Connection;
|
var connection = Http?.HttpContext?.Connection;
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
{
|
{
|
||||||
@@ -51,9 +61,8 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
|
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
|
||||||
|
|
||||||
private IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
|
|
||||||
|
|
||||||
public ConnectionContext Connection { get; }
|
public ConnectionContext Connection { get; }
|
||||||
|
|
||||||
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
|
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
|
||||||
|
|
||||||
public long BytesSent { get; set; }
|
public long BytesSent { get; set; }
|
||||||
@@ -62,7 +71,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
public Action ReadingPacketStartedCallback { get; set; }
|
public Action ReadingPacketStartedCallback { get; set; }
|
||||||
public Action ReadingPacketCompletedCallback { get; set; }
|
public Action ReadingPacketCompletedCallback { get; set; }
|
||||||
|
|
||||||
private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
|
IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
|
||||||
|
|
||||||
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -136,6 +145,13 @@ namespace MQTTnet.AspNetCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// completing the cannels makes sure that there is no more data read after a protocol error
|
||||||
|
_input?.Complete(e);
|
||||||
|
_output?.Complete(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ReadingPacketCompletedCallback?.Invoke();
|
ReadingPacketCompletedCallback?.Invoke();
|
||||||
@@ -154,10 +170,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var formatter = PacketFormatterAdapter;
|
var formatter = PacketFormatterAdapter;
|
||||||
|
using (await _writerLock.WaitAsync(cancellationToken).ConfigureAwait(false))
|
||||||
|
|
||||||
await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var buffer = formatter.Encode(packet);
|
var buffer = formatter.Encode(packet);
|
||||||
var msg = buffer.AsMemory();
|
var msg = buffer.AsMemory();
|
||||||
@@ -169,10 +182,6 @@ namespace MQTTnet.AspNetCore
|
|||||||
}
|
}
|
||||||
PacketFormatterAdapter.FreeBuffer();
|
PacketFormatterAdapter.FreeBuffer();
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
_writerSemaphore.Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
private readonly IMqttServerOptions _options;
|
private readonly IMqttServerOptions _options;
|
||||||
|
|
||||||
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||||
: base(adapters, logger.CreateChildLogger(nameof(MqttHostedServer)))
|
: base(adapters, logger)
|
||||||
{
|
{
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,29 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore
|
||||||
{
|
{
|
||||||
public static class MqttSubProtocolSelector
|
public static class MqttSubProtocolSelector
|
||||||
{
|
{
|
||||||
|
public static string SelectSubProtocol(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new ArgumentNullException(nameof(request));
|
||||||
|
|
||||||
|
string subProtocol = null;
|
||||||
|
if (request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
||||||
|
{
|
||||||
|
subProtocol = SelectSubProtocol(requestedSubProtocolValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
public static string SelectSubProtocol(IList<string> requestedSubProtocolValues)
|
public static string SelectSubProtocol(IList<string> requestedSubProtocolValues)
|
||||||
{
|
{
|
||||||
|
if (requestedSubProtocolValues == null) throw new ArgumentNullException(nameof(requestedSubProtocolValues));
|
||||||
|
|
||||||
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
|
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
|
||||||
return requestedSubProtocolValues
|
return requestedSubProtocolValues
|
||||||
.OrderByDescending(p => p.Length)
|
.OrderByDescending(p => p.Length)
|
||||||
|
|||||||
@@ -10,15 +10,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore
|
||||||
{
|
{
|
||||||
public class MqttWebSocketServerAdapter : IMqttServerAdapter
|
public sealed class MqttWebSocketServerAdapter : IMqttServerAdapter
|
||||||
{
|
{
|
||||||
private readonly IMqttNetLogger _logger;
|
readonly IMqttNetLogger _rootLogger;
|
||||||
|
|
||||||
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
|
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||||
@@ -51,7 +49,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
var formatter = new MqttPacketFormatterAdapter(writer);
|
var formatter = new MqttPacketFormatterAdapter(writer);
|
||||||
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
|
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
|
||||||
|
|
||||||
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter))))
|
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _rootLogger))
|
||||||
{
|
{
|
||||||
await clientHandler(channelAdapter).ConfigureAwait(false);
|
await clientHandler(channelAdapter).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
|
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
|
||||||
{
|
{
|
||||||
private ReadOnlyMemory<byte> _buffer;
|
ReadOnlyMemory<byte> _buffer;
|
||||||
|
|
||||||
private int _offset;
|
int _offset;
|
||||||
|
|
||||||
public void SetBuffer(ReadOnlyMemory<byte> buffer)
|
public void SetBuffer(ReadOnlyMemory<byte> buffer)
|
||||||
{
|
{
|
||||||
@@ -38,16 +38,6 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
return ReadSegmentWithLengthPrefix().ToArray();
|
return ReadSegmentWithLengthPrefix().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
|
|
||||||
{
|
|
||||||
var span = _buffer.Span;
|
|
||||||
var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
|
|
||||||
|
|
||||||
var result = span.Slice(_offset+2, length);
|
|
||||||
_offset += 2 + length;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe string ReadStringWithLengthPrefix()
|
public unsafe string ReadStringWithLengthPrefix()
|
||||||
{
|
{
|
||||||
@@ -121,5 +111,19 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
_offset = position;
|
_offset = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
|
||||||
|
{
|
||||||
|
var span = _buffer.Span;
|
||||||
|
var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
|
||||||
|
|
||||||
|
if (Length < _offset + length)
|
||||||
|
{
|
||||||
|
throw new MqttProtocolViolationException($"Expected at least {_offset + 2 + length} bytes but there are only {Length} bytes");
|
||||||
|
}
|
||||||
|
var result = span.Slice(_offset + 2, length);
|
||||||
|
_offset += 2 + length;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,15 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
public class SpanBasedMqttPacketWriter : IMqttPacketWriter
|
public class SpanBasedMqttPacketWriter : IMqttPacketWriter
|
||||||
{
|
{
|
||||||
private readonly ArrayPool<byte> _pool;
|
readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create();
|
||||||
|
|
||||||
public SpanBasedMqttPacketWriter()
|
public SpanBasedMqttPacketWriter()
|
||||||
{
|
{
|
||||||
_pool = ArrayPool<byte>.Create();
|
Reset(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] _buffer;
|
byte[] _buffer;
|
||||||
private int _position;
|
int _position;
|
||||||
|
|
||||||
public int Length { get; set; }
|
public int Length { get; set; }
|
||||||
|
|
||||||
@@ -112,7 +111,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
Commit(payload.Length);
|
Commit(payload.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Commit(int count)
|
void Commit(int count)
|
||||||
{
|
{
|
||||||
if (_position == Length)
|
if (_position == Length)
|
||||||
{
|
{
|
||||||
@@ -122,7 +121,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
_position += count;
|
_position += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GrowIfNeeded(int requiredAdditional)
|
void GrowIfNeeded(int requiredAdditional)
|
||||||
{
|
{
|
||||||
var requiredTotal = _position + requiredAdditional;
|
var requiredTotal = _position + requiredAdditional;
|
||||||
if (_buffer.Length >= requiredTotal)
|
if (_buffer.Length >= requiredTotal)
|
||||||
|
|||||||
@@ -1,31 +1,49 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.Client;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||||
{
|
{
|
||||||
bool IsStarted { get; }
|
/// <summary>
|
||||||
bool IsConnected { get; }
|
/// Gets the internally used MQTT client.
|
||||||
int PendingApplicationMessagesCount { get; }
|
/// This property should be used with caution because manipulating the internal client might break the managed client.
|
||||||
IManagedMqttClientOptions Options { get; }
|
/// </summary>
|
||||||
|
IMqttClient InternalClient { get; }
|
||||||
|
|
||||||
|
bool IsStarted { get; }
|
||||||
|
|
||||||
|
bool IsConnected { get; }
|
||||||
|
|
||||||
|
int PendingApplicationMessagesCount { get; }
|
||||||
|
|
||||||
|
IManagedMqttClientOptions Options { get; }
|
||||||
|
|
||||||
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
||||||
|
|
||||||
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
||||||
|
|
||||||
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
||||||
|
|
||||||
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
|
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
|
||||||
|
|
||||||
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
|
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
|
||||||
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
|
|
||||||
|
|
||||||
Task StartAsync(IManagedMqttClientOptions options);
|
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
|
||||||
Task StopAsync();
|
|
||||||
|
|
||||||
Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
Task StartAsync(IManagedMqttClientOptions options);
|
||||||
|
|
||||||
|
Task StopAsync();
|
||||||
|
|
||||||
|
Task PingAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters);
|
||||||
|
|
||||||
Task UnsubscribeAsync(IEnumerable<string> topics);
|
Task UnsubscribeAsync(IEnumerable<string> topics);
|
||||||
|
|
||||||
Task PublishAsync(ManagedMqttApplicationMessage applicationMessages);
|
Task PublishAsync(ManagedMqttApplicationMessage applicationMessages);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
IMqttClientOptions ClientOptions { get; }
|
IMqttClientOptions ClientOptions { get; }
|
||||||
|
|
||||||
|
bool AutoReconnect { get; }
|
||||||
|
|
||||||
TimeSpan AutoReconnectDelay { get; }
|
TimeSpan AutoReconnectDelay { get; }
|
||||||
|
|
||||||
TimeSpan ConnectionCheckInterval { get; }
|
TimeSpan ConnectionCheckInterval { get; }
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +26,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
public class ManagedMqttClient : Disposable, IManagedMqttClient
|
public class ManagedMqttClient : Disposable, IManagedMqttClient
|
||||||
{
|
{
|
||||||
private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
|
readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The subscriptions are managed in 2 separate buckets:
|
/// The subscriptions are managed in 2 separate buckets:
|
||||||
@@ -27,33 +27,39 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
/// any thread and are therefore mutex'ed. <see cref="_reconnectSubscriptions"/> get sent to the broker
|
/// any thread and are therefore mutex'ed. <see cref="_reconnectSubscriptions"/> get sent to the broker
|
||||||
/// at reconnect and are solely owned by <see cref="MaintainConnectionAsync"/>.
|
/// at reconnect and are solely owned by <see cref="MaintainConnectionAsync"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
||||||
private readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
||||||
private readonly HashSet<string> _unsubscriptions = new HashSet<string>();
|
readonly HashSet<string> _unsubscriptions = new HashSet<string>();
|
||||||
private readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0);
|
readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0);
|
||||||
|
|
||||||
private readonly IMqttClient _mqttClient;
|
readonly IMqttClient _mqttClient;
|
||||||
private readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
|
|
||||||
private readonly AsyncLock _messageQueueLock = new AsyncLock();
|
readonly AsyncLock _messageQueueLock = new AsyncLock();
|
||||||
|
|
||||||
private CancellationTokenSource _connectionCancellationToken;
|
CancellationTokenSource _connectionCancellationToken;
|
||||||
private CancellationTokenSource _publishingCancellationToken;
|
CancellationTokenSource _publishingCancellationToken;
|
||||||
private Task _maintainConnectionTask;
|
Task _maintainConnectionTask;
|
||||||
|
|
||||||
private ManagedMqttClientStorageManager _storageManager;
|
ManagedMqttClientStorageManager _storageManager;
|
||||||
|
|
||||||
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
|
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
||||||
|
InternalClient = mqttClient;
|
||||||
|
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
_logger = logger.CreateChildLogger(nameof(ManagedMqttClient));
|
_logger = logger.CreateScopedLogger(nameof(ManagedMqttClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsConnected => _mqttClient.IsConnected;
|
public bool IsConnected => _mqttClient.IsConnected;
|
||||||
|
|
||||||
public bool IsStarted => _connectionCancellationToken != null;
|
public bool IsStarted => _connectionCancellationToken != null;
|
||||||
|
|
||||||
|
public IMqttClient InternalClient { get; }
|
||||||
|
|
||||||
public int PendingApplicationMessagesCount => _messageQueue.Count;
|
public int PendingApplicationMessagesCount => _messageQueue.Count;
|
||||||
|
|
||||||
public IManagedMqttClientOptions Options { get; private set; }
|
public IManagedMqttClientOptions Options { get; private set; }
|
||||||
|
|
||||||
public IMqttClientConnectedHandler ConnectedHandler
|
public IMqttClientConnectedHandler ConnectedHandler
|
||||||
@@ -88,8 +94,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
if (options.ClientOptions == null) throw new ArgumentException("The client options are not set.", nameof(options));
|
if (options.ClientOptions == null) throw new ArgumentException("The client options are not set.", nameof(options));
|
||||||
|
|
||||||
|
|
||||||
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
|
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
|
||||||
|
|
||||||
Options = options;
|
Options = options;
|
||||||
@@ -105,11 +110,16 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_connectionCancellationToken = new CancellationTokenSource();
|
if (Options.AutoReconnect)
|
||||||
|
{
|
||||||
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
_maintainConnectionTask.Forget(_logger);
|
var cancellationToken = cancellationTokenSource.Token;
|
||||||
|
_connectionCancellationToken = cancellationTokenSource;
|
||||||
|
|
||||||
|
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(cancellationToken), cancellationToken);
|
||||||
|
_maintainConnectionTask.Forget(_logger);
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Info("Started");
|
_logger.Info("Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +139,11 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task PingAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _mqttClient.PingAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
@@ -199,7 +214,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
|
public Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
@@ -255,10 +270,11 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
_mqttClient.Dispose();
|
_mqttClient.Dispose();
|
||||||
_subscriptionsQueuedSignal.Dispose();
|
_subscriptionsQueuedSignal.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
|
async Task MaintainConnectionAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -298,7 +314,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
|
async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -341,7 +357,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
|
async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -379,7 +395,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
|
async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
|
||||||
{
|
{
|
||||||
Exception transmitException = null;
|
Exception transmitException = null;
|
||||||
try
|
try
|
||||||
@@ -444,17 +460,17 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PublishSubscriptionsAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
async Task PublishSubscriptionsAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var endTime = DateTime.UtcNow + timeout;
|
var endTime = DateTime.UtcNow + timeout;
|
||||||
while (await _subscriptionsQueuedSignal.WaitAsync(GetRemainingTime(endTime), cancellationToken).ConfigureAwait(false))
|
while (await _subscriptionsQueuedSignal.WaitAsync(GetRemainingTime(endTime), cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
List<TopicFilter> subscriptions;
|
List<MqttTopicFilter> subscriptions;
|
||||||
HashSet<string> unsubscriptions;
|
HashSet<string> unsubscriptions;
|
||||||
|
|
||||||
lock (_subscriptions)
|
lock (_subscriptions)
|
||||||
{
|
{
|
||||||
subscriptions = _subscriptions.Select(i => new TopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
|
subscriptions = _subscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
|
||||||
_subscriptions.Clear();
|
_subscriptions.Clear();
|
||||||
unsubscriptions = new HashSet<string>(_unsubscriptions);
|
unsubscriptions = new HashSet<string>(_unsubscriptions);
|
||||||
_unsubscriptions.Clear();
|
_unsubscriptions.Clear();
|
||||||
@@ -496,7 +512,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PublishReconnectSubscriptionsAsync()
|
async Task PublishReconnectSubscriptionsAsync()
|
||||||
{
|
{
|
||||||
_logger.Info("Publishing subscriptions at reconnect");
|
_logger.Info("Publishing subscriptions at reconnect");
|
||||||
|
|
||||||
@@ -504,7 +520,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
if (_reconnectSubscriptions.Any())
|
if (_reconnectSubscriptions.Any())
|
||||||
{
|
{
|
||||||
var subscriptions = _reconnectSubscriptions.Select(i => new TopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value });
|
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value });
|
||||||
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
|
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,7 +530,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleSubscriptionExceptionAsync(Exception exception)
|
async Task HandleSubscriptionExceptionAsync(Exception exception)
|
||||||
{
|
{
|
||||||
_logger.Warning(exception, "Synchronizing subscriptions failed.");
|
_logger.Warning(exception, "Synchronizing subscriptions failed.");
|
||||||
|
|
||||||
@@ -525,7 +541,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ReconnectionResult> ReconnectIfRequiredAsync()
|
async Task<ReconnectionResult> ReconnectIfRequiredAsync()
|
||||||
{
|
{
|
||||||
if (_mqttClient.IsConnected)
|
if (_mqttClient.IsConnected)
|
||||||
{
|
{
|
||||||
@@ -549,34 +565,47 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartPublishing()
|
void StartPublishing()
|
||||||
{
|
{
|
||||||
if (_publishingCancellationToken != null)
|
if (_publishingCancellationToken != null)
|
||||||
{
|
{
|
||||||
StopPublishing();
|
StopPublishing();
|
||||||
}
|
}
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
_publishingCancellationToken = cts;
|
var cancellationToken = cancellationTokenSource.Token;
|
||||||
|
_publishingCancellationToken = cancellationTokenSource;
|
||||||
|
|
||||||
Task.Run(() => PublishQueuedMessagesAsync(cts.Token), cts.Token).Forget(_logger);
|
Task.Run(() => PublishQueuedMessagesAsync(cancellationToken), cancellationToken).Forget(_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopPublishing()
|
void StopPublishing()
|
||||||
{
|
{
|
||||||
_publishingCancellationToken?.Cancel(false);
|
try
|
||||||
_publishingCancellationToken?.Dispose();
|
{
|
||||||
_publishingCancellationToken = null;
|
_publishingCancellationToken?.Cancel(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_publishingCancellationToken?.Dispose();
|
||||||
|
_publishingCancellationToken = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopMaintainingConnection()
|
void StopMaintainingConnection()
|
||||||
{
|
{
|
||||||
_connectionCancellationToken?.Cancel(false);
|
try
|
||||||
_connectionCancellationToken?.Dispose();
|
{
|
||||||
_connectionCancellationToken = null;
|
_connectionCancellationToken?.Cancel(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connectionCancellationToken?.Dispose();
|
||||||
|
_connectionCancellationToken = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeSpan GetRemainingTime(DateTime endTime)
|
static TimeSpan GetRemainingTime(DateTime endTime)
|
||||||
{
|
{
|
||||||
var remainingTime = endTime - DateTime.UtcNow;
|
var remainingTime = endTime - DateTime.UtcNow;
|
||||||
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime;
|
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
using MQTTnet.Client.Publishing;
|
using MQTTnet.Client.Publishing;
|
||||||
using MQTTnet.Client.Receiving;
|
using MQTTnet.Client.Receiving;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
@@ -76,39 +76,42 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
if (handler == null)
|
if (handler == null)
|
||||||
{
|
{
|
||||||
return client.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
if (handler == null)
|
if (handler == null)
|
||||||
{
|
{
|
||||||
return client.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, IMqttApplicationMessageReceivedHandler handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, IMqttApplicationMessageReceivedHandler handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
client.ApplicationMessageReceivedHandler = handler;
|
receiver.ApplicationMessageReceivedHandler = handler;
|
||||||
return client;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task SubscribeAsync(this IManagedMqttClient client, params TopicFilter[] topicFilters)
|
public static Task SubscribeAsync(this IManagedMqttClient client, params MqttTopicFilter[] topicFilters)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
|
|
||||||
@@ -120,7 +123,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task SubscribeAsync(this IManagedMqttClient client, string topic)
|
public static Task SubscribeAsync(this IManagedMqttClient client, string topic)
|
||||||
@@ -128,7 +131,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task UnsubscribeAsync(this IManagedMqttClient client, params string[] topicFilters)
|
public static Task UnsubscribeAsync(this IManagedMqttClient client, params string[] topicFilters)
|
||||||
@@ -138,92 +141,92 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return client.UnsubscribeAsync(topicFilters);
|
return client.UnsubscribeAsync(topicFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task PublishAsync(this IManagedMqttClient client, IEnumerable<MqttApplicationMessage> applicationMessages)
|
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, IEnumerable<MqttApplicationMessage> applicationMessages)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||||
|
|
||||||
foreach (var applicationMessage in applicationMessages)
|
foreach (var applicationMessage in applicationMessages)
|
||||||
{
|
{
|
||||||
await client.PublishAsync(applicationMessage).ConfigureAwait(false);
|
await publisher.PublishAsync(applicationMessage).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, MqttApplicationMessage applicationMessage)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||||
|
|
||||||
return client.PublishAsync(applicationMessage, CancellationToken.None);
|
return publisher.PublishAsync(applicationMessage, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task PublishAsync(this IManagedMqttClient client, params MqttApplicationMessage[] applicationMessages)
|
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, params MqttApplicationMessage[] applicationMessages)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||||
|
|
||||||
foreach (var applicationMessage in applicationMessages)
|
foreach (var applicationMessage in applicationMessages)
|
||||||
{
|
{
|
||||||
await client.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
await publisher.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic));
|
.WithTopic(topic));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload));
|
.WithPayload(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload)
|
.WithPayload(payload)
|
||||||
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload)
|
.WithPayload(payload)
|
||||||
.WithQualityOfServiceLevel(qualityOfServiceLevel)
|
.WithQualityOfServiceLevel(qualityOfServiceLevel)
|
||||||
.WithRetainFlag(retain));
|
.WithRetainFlag(retain));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
|
|
||||||
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
||||||
return client.PublishAsync(message, cancellationToken);
|
return publisher.PublishAsync(message, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
|
|
||||||
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
||||||
return client.PublishAsync(message, CancellationToken.None);
|
return publisher.PublishAsync(message, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
@@ -9,6 +8,8 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
public IMqttClientOptions ClientOptions { get; set; }
|
public IMqttClientOptions ClientOptions { get; set; }
|
||||||
|
|
||||||
|
public bool AutoReconnect { get; set; } = true;
|
||||||
|
|
||||||
public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5);
|
public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
public TimeSpan ConnectionCheckInterval { get; set; } = TimeSpan.FromSeconds(1);
|
public TimeSpan ConnectionCheckInterval { get; set; } = TimeSpan.FromSeconds(1);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
@@ -7,8 +6,8 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
public class ManagedMqttClientOptionsBuilder
|
public class ManagedMqttClientOptionsBuilder
|
||||||
{
|
{
|
||||||
private readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
|
readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
|
||||||
private MqttClientOptionsBuilder _clientOptionsBuilder;
|
MqttClientOptionsBuilder _clientOptionsBuilder;
|
||||||
|
|
||||||
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
|
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
|
||||||
{
|
{
|
||||||
@@ -70,6 +69,18 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ManagedMqttClientOptionsBuilder WithAutoReconnect()
|
||||||
|
{
|
||||||
|
_options.AutoReconnect = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagedMqttClientOptionsBuilder WithoutAutoReconnect()
|
||||||
|
{
|
||||||
|
_options.AutoReconnect = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ManagedMqttClientOptions Build()
|
public ManagedMqttClientOptions Build()
|
||||||
{
|
{
|
||||||
if (_clientOptionsBuilder != null)
|
if (_clientOptionsBuilder != null)
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +26,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
|
using System;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.Rpc.Options
|
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
|
||||||
{
|
{
|
||||||
public class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
|
public class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +26,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
{
|
{
|
||||||
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
|
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
|
||||||
|
|
||||||
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory());
|
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory(mqttFactory.DefaultLogger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,21 +9,27 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
{
|
{
|
||||||
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
|
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetLogger logger)
|
readonly IMqttNetLogger _logger;
|
||||||
|
|
||||||
|
public WebSocket4NetMqttClientAdapterFactory(IMqttNetLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
switch (options.ChannelOptions)
|
switch (options.ChannelOptions)
|
||||||
{
|
{
|
||||||
case MqttClientTcpOptions _:
|
case MqttClientTcpOptions _:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
case MqttClientWebSocketOptions webSocketOptions:
|
case MqttClientWebSocketOptions webSocketOptions:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options, webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options, webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Controllers
|
namespace MQTTnet.Server.Controllers
|
||||||
@@ -12,7 +13,8 @@ namespace MQTTnet.Server.Controllers
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public ActionResult<string> GetVersion()
|
public ActionResult<string> GetVersion()
|
||||||
{
|
{
|
||||||
return Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||||
|
return fileVersion.ProductVersion.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MQTTnet.Server.Logging
|
namespace MQTTnet.Server.Logging
|
||||||
{
|
{
|
||||||
public class MqttNetLoggerWrapper : IMqttNetLogger
|
public sealed class MqttNetLoggerWrapper : IMqttNetLogger
|
||||||
{
|
{
|
||||||
readonly ILogger<MqttServer> _logger;
|
readonly ILogger<MqttServer> _logger;
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@ namespace MQTTnet.Server.Logging
|
|||||||
|
|
||||||
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
||||||
|
|
||||||
public IMqttNetLogger CreateChildLogger(string source)
|
public IMqttNetScopedLogger CreateScopedLogger(string source)
|
||||||
{
|
{
|
||||||
return new MqttNetLogger(source);
|
return new MqttNetScopedLogger(this, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
|
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
|
||||||
|
|||||||
@@ -8,19 +8,22 @@
|
|||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
<Company />
|
<Company />
|
||||||
<Product>MQTTnet</Product>
|
<Product>MQTTnet</Product>
|
||||||
<Description />
|
<Description>Standalone MQTT server with Python scripting backend.</Description>
|
||||||
<Authors />
|
<Authors>The authors of MQTTnet.Server.</Authors>
|
||||||
<PackageId />
|
<PackageId />
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<DelaySign>false</DelaySign>
|
<DelaySign>false</DelaySign>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Version>1.0.0</Version>
|
<Version>3.0.11</Version>
|
||||||
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
|
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject></StartupObject>
|
<StartupObject>MQTTnet.Server.Program</StartupObject>
|
||||||
<UserSecretsId>c564f0de-28b4-45bf-b726-4d665d705653</UserSecretsId>
|
<UserSecretsId>c564f0de-28b4-45bf-b726-4d665d705653</UserSecretsId>
|
||||||
|
<Copyright>(c) Christian Kratky 2016-2020</Copyright>
|
||||||
|
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@@ -29,13 +32,6 @@
|
|||||||
<NoWarn>1701;1702</NoWarn>
|
<NoWarn>1701;1702</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="wwwroot\**" />
|
|
||||||
<Content Remove="wwwroot\**" />
|
|
||||||
<EmbeddedResource Remove="wwwroot\**" />
|
|
||||||
<None Remove="wwwroot\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Update="appsettings.json">
|
<Content Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
@@ -43,12 +39,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IronPython" Version="2.7.10-candidate1" />
|
<PackageReference Include="IronPython" Version="2.7.10" />
|
||||||
<PackageReference Include="IronPython.StdLib" Version="2.7.10-candidate1" />
|
<PackageReference Include="IronPython.StdLib" Version="2.7.10" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.5" />
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.3.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.3.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -72,11 +68,19 @@
|
|||||||
<None Update="Web\authorization_handler.py">
|
<None Update="Web\authorization_handler.py">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Web\wwwroot\Hello.txt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Web\wwwroot\mqtt_Test.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Web\wwwroot\pahoJS_Test.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\PublishProfiles\" />
|
<Folder Include="Properties\PublishProfiles\" />
|
||||||
<Folder Include="Web\wwwroot\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using MQTTnet.Server.Web;
|
using MQTTnet.Server.Web;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
@@ -20,8 +22,8 @@ namespace MQTTnet.Server
|
|||||||
webBuilder.ConfigureKestrel(serverOptions =>
|
webBuilder.ConfigureKestrel(serverOptions =>
|
||||||
{
|
{
|
||||||
})
|
})
|
||||||
|
.UseWebRoot(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot"))
|
||||||
.UseStartup<Startup>();
|
.UseStartup<Startup>();
|
||||||
|
|
||||||
}).Build().Run();
|
}).Build().Run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -58,8 +60,11 @@ namespace MQTTnet.Server
|
|||||||
Console.WriteLine(@"https://github.com/chkr1011/MQTTnet");
|
Console.WriteLine(@"https://github.com/chkr1011/MQTTnet");
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||||
|
|
||||||
Console.WriteLine($@"
|
Console.WriteLine($@"
|
||||||
Version: {Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}
|
Version: {fileVersion.ProductVersion}
|
||||||
License: MIT (read LICENSE file)
|
License: MIT (read LICENSE file)
|
||||||
Sponsoring: https://opencollective.com/mqttnet
|
Sponsoring: https://opencollective.com/mqttnet
|
||||||
Support: https://github.com/chkr1011/MQTTnet/issues
|
Support: https://github.com/chkr1011/MQTTnet/issues
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.Scripting.Utils;
|
using Microsoft.Scripting.Utils;
|
||||||
|
using MQTTnet.AspNetCore;
|
||||||
using MQTTnet.Server.Configuration;
|
using MQTTnet.Server.Configuration;
|
||||||
using MQTTnet.Server.Logging;
|
using MQTTnet.Server.Logging;
|
||||||
using MQTTnet.Server.Mqtt;
|
using MQTTnet.Server.Mqtt;
|
||||||
@@ -40,6 +41,9 @@ namespace MQTTnet.Server.Web
|
|||||||
DataSharingService dataSharingService,
|
DataSharingService dataSharingService,
|
||||||
MqttSettingsModel mqttSettings)
|
MqttSettingsModel mqttSettings)
|
||||||
{
|
{
|
||||||
|
application.UseDefaultFiles();
|
||||||
|
application.UseStaticFiles();
|
||||||
|
|
||||||
application.UseHsts();
|
application.UseHsts();
|
||||||
application.UseRouting();
|
application.UseRouting();
|
||||||
application.UseCors(x => x
|
application.UseCors(x => x
|
||||||
@@ -49,9 +53,7 @@ namespace MQTTnet.Server.Web
|
|||||||
|
|
||||||
application.UseAuthentication();
|
application.UseAuthentication();
|
||||||
application.UseAuthorization();
|
application.UseAuthorization();
|
||||||
|
|
||||||
application.UseStaticFiles();
|
|
||||||
|
|
||||||
application.UseEndpoints(endpoints =>
|
application.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
@@ -81,7 +83,6 @@ namespace MQTTnet.Server.Web
|
|||||||
{
|
{
|
||||||
services.AddCors();
|
services.AddCors();
|
||||||
|
|
||||||
|
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddMvc()
|
||||||
@@ -197,7 +198,13 @@ namespace MQTTnet.Server.Web
|
|||||||
{
|
{
|
||||||
if (context.WebSockets.IsWebSocketRequest)
|
if (context.WebSockets.IsWebSocketRequest)
|
||||||
{
|
{
|
||||||
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false))
|
string subProtocol = null;
|
||||||
|
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
||||||
|
{
|
||||||
|
subProtocol = MqttSubProtocolSelector.SelectSubProtocol(requestedSubProtocolValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await mqttServerService.RunWebSocketConnectionAsync(webSocket, context).ConfigureAwait(false);
|
await mqttServerService.RunWebSocketConnectionAsync(webSocket, context).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
World
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>MQTT JS Example</title>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mqtt@4.0.1/dist/mqtt.min.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var client = mqtt.connect('ws://localhost:80/mqtt')
|
||||||
|
|
||||||
|
client.on('connect', function () {
|
||||||
|
client.subscribe('mqtt_subscription', function (err) {
|
||||||
|
console.log("Subscribed");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('message', function (topic, message) {
|
||||||
|
console.log(topic);
|
||||||
|
console.log(message.toString())
|
||||||
|
})
|
||||||
|
|
||||||
|
function buttonClick() {
|
||||||
|
client.publish("MQTT_JS_TOPIC", "payload");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<button onclick="buttonClick()">Publish</button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>paho JS Example</title>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var mqttClient = new Paho.MQTT.Client("localhost", 80, "/mqtt", "pahoJS_client");
|
||||||
|
mqttClient.onConnectionLost = onConnectionLost;
|
||||||
|
mqttClient.onMessageArrived = onMessageArrived;
|
||||||
|
mqttClient.connect({ onSuccess: onConnect });
|
||||||
|
|
||||||
|
function onConnect() {
|
||||||
|
console.log("MQTT client connected");
|
||||||
|
mqttClient.subscribe("pahoJS_subscription");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConnectionLost(responseObject) {
|
||||||
|
if (responseObject.errorCode !== 0) {
|
||||||
|
console.log("onConnectionLost:" + responseObject.errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessageArrived(message) {
|
||||||
|
console.log("onMessageArrived:" + message.payloadString);
|
||||||
|
}
|
||||||
|
function buttonClick() {
|
||||||
|
message = new Paho.MQTT.Message("Hello");
|
||||||
|
message.destinationName = "pahoJS_topic";
|
||||||
|
mqttClient.send(message);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<button onclick="buttonClick()">Publish</button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Diagnostics;
|
|
||||||
|
|
||||||
namespace MQTTnet.Adapter
|
namespace MQTTnet.Adapter
|
||||||
{
|
{
|
||||||
public interface IMqttClientAdapterFactory
|
public interface IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetLogger logger);
|
IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ namespace MQTTnet.Adapter
|
|||||||
public sealed class MqttChannelAdapter : Disposable, IMqttChannelAdapter
|
public sealed class MqttChannelAdapter : Disposable, IMqttChannelAdapter
|
||||||
{
|
{
|
||||||
const uint ErrorOperationAborted = 0x800703E3;
|
const uint ErrorOperationAborted = 0x800703E3;
|
||||||
const int ReadBufferSize = 4096; // TODO: Move buffer size to config
|
const int ReadBufferSize = 4096;
|
||||||
|
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
readonly IMqttChannel _channel;
|
readonly IMqttChannel _channel;
|
||||||
readonly MqttPacketReader _packetReader;
|
readonly MqttPacketReader _packetReader;
|
||||||
|
|
||||||
readonly byte[] _fixedHeaderBuffer = new byte[2];
|
readonly byte[] _fixedHeaderBuffer = new byte[2];
|
||||||
|
|
||||||
SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
|
readonly AsyncLock _syncRoot = new AsyncLock();
|
||||||
|
|
||||||
long _bytesReceived;
|
long _bytesReceived;
|
||||||
long _bytesSent;
|
long _bytesSent;
|
||||||
@@ -39,7 +39,7 @@ namespace MQTTnet.Adapter
|
|||||||
|
|
||||||
_packetReader = new MqttPacketReader(_channel);
|
_packetReader = new MqttPacketReader(_channel);
|
||||||
|
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttChannelAdapter));
|
_logger = logger.CreateScopedLogger(nameof(MqttChannelAdapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Endpoint => _channel.Endpoint;
|
public string Endpoint => _channel.Endpoint;
|
||||||
@@ -58,6 +58,7 @@ namespace MQTTnet.Adapter
|
|||||||
|
|
||||||
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -84,6 +85,7 @@ namespace MQTTnet.Adapter
|
|||||||
|
|
||||||
public async Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -111,44 +113,58 @@ namespace MQTTnet.Adapter
|
|||||||
|
|
||||||
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
ThrowIfDisposed();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var packetData = PacketFormatterAdapter.Encode(packet);
|
using (await _syncRoot.WaitAsync(cancellationToken).ConfigureAwait(false))
|
||||||
|
|
||||||
if (timeout == TimeSpan.Zero)
|
|
||||||
{
|
{
|
||||||
await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false);
|
// Check for cancellation here again because "WaitAsync" might take some time.
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var packetData = PacketFormatterAdapter.Encode(packet);
|
||||||
|
|
||||||
|
if (timeout == TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await MqttTaskTimeout.WaitAsync(
|
||||||
|
t => _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, t), timeout, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Interlocked.Add(ref _bytesReceived, packetData.Count);
|
||||||
|
|
||||||
|
_logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
if (IsWrappedException(exception))
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
WrapException(exception);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
PacketFormatterAdapter.FreeBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
await MqttTaskTimeout.WaitAsync(
|
|
||||||
t => _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, t), timeout, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Interlocked.Add(ref _bytesReceived, packetData.Count);
|
|
||||||
|
|
||||||
PacketFormatterAdapter.FreeBuffer();
|
|
||||||
|
|
||||||
_logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet);
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
if (IsWrappedException(exception))
|
throw new OperationCanceledException();
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
WrapException(exception);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_writerSemaphore?.Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -188,6 +204,9 @@ namespace MQTTnet.Adapter
|
|||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
if (IsWrappedException(exception))
|
if (IsWrappedException(exception))
|
||||||
@@ -211,10 +230,8 @@ namespace MQTTnet.Adapter
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
_channel?.Dispose();
|
_channel.Dispose();
|
||||||
|
_syncRoot.Dispose();
|
||||||
_writerSemaphore?.Dispose();
|
|
||||||
_writerSemaphore = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MQTTnet.Certificates
|
||||||
|
{
|
||||||
|
public class BlobCertificateProvider : ICertificateProvider
|
||||||
|
{
|
||||||
|
public BlobCertificateProvider(byte[] blob)
|
||||||
|
{
|
||||||
|
Blob = blob ?? throw new ArgumentNullException(nameof(blob));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Blob { get; }
|
||||||
|
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public X509Certificate2 GetCertificate()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Password))
|
||||||
|
{
|
||||||
|
// Use a different overload when no password is specified. Otherwise the constructor will fail.
|
||||||
|
return new X509Certificate2(Blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new X509Certificate2(Blob, Password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MQTTnet.Certificates
|
||||||
|
{
|
||||||
|
public interface ICertificateProvider
|
||||||
|
{
|
||||||
|
X509Certificate2 GetCertificate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#if !WINDOWS_UWP
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MQTTnet.Certificates
|
||||||
|
{
|
||||||
|
public class X509CertificateProvider : ICertificateProvider
|
||||||
|
{
|
||||||
|
readonly X509Certificate2 _certificate;
|
||||||
|
|
||||||
|
public X509CertificateProvider(X509Certificate2 certificate)
|
||||||
|
{
|
||||||
|
_certificate = certificate ?? throw new ArgumentNullException(nameof(certificate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509Certificate2 GetCertificate()
|
||||||
|
{
|
||||||
|
return _certificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -3,6 +3,34 @@
|
|||||||
public enum MqttClientDisconnectReason
|
public enum MqttClientDisconnectReason
|
||||||
{
|
{
|
||||||
NormalDisconnection = 0,
|
NormalDisconnection = 0,
|
||||||
|
DisconnectWithWillMessage = 4,
|
||||||
|
UnspecifiedError = 128,
|
||||||
|
MalformedPacket = 129,
|
||||||
|
ProtocolError = 130,
|
||||||
|
ImplementationSpecificError = 131,
|
||||||
|
NotAuthorized = 135,
|
||||||
|
ServerBusy = 137,
|
||||||
|
ServerShuttingDown = 139,
|
||||||
|
BadAuthenticationMethod = 140,
|
||||||
|
KeepaliveTimeout = 141,
|
||||||
|
SessionTakenOver = 142,
|
||||||
|
TopicFilterInvalid = 143,
|
||||||
|
TopicNameInvalid = 144,
|
||||||
|
ReceiveMaximumExceeded = 147,
|
||||||
|
TopicAliasInvalid = 148,
|
||||||
|
PacketTooLarge = 149,
|
||||||
|
MessageRateTooHigh = 150,
|
||||||
|
QuotaExceeded = 151,
|
||||||
|
AdministrativeAction = 152,
|
||||||
|
PayloadFormatInvalid = 153,
|
||||||
|
RetainNotSupported = 154,
|
||||||
|
QosNotSupported = 155,
|
||||||
|
UseAnotherServer = 156,
|
||||||
|
ServerMoved = 157,
|
||||||
|
SharedSubscriptionsNotSupported = 158,
|
||||||
|
ConnectionRateExceeded = 159,
|
||||||
|
MaximumConnectTime = 160,
|
||||||
|
SubscriptionIdentifiersNotSupported = 161,
|
||||||
|
WildcardSubscriptionsNotSupported = 162
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ namespace MQTTnet.Client.Disconnecting
|
|||||||
{
|
{
|
||||||
public class MqttClientDisconnectedEventArgs : EventArgs
|
public class MqttClientDisconnectedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public MqttClientDisconnectedEventArgs(bool clientWasConnected, Exception exception, MqttClientAuthenticateResult authenticateResult)
|
public MqttClientDisconnectedEventArgs(bool clientWasConnected, Exception exception, MqttClientAuthenticateResult authenticateResult, MqttClientDisconnectReason reasonCode)
|
||||||
{
|
{
|
||||||
ClientWasConnected = clientWasConnected;
|
ClientWasConnected = clientWasConnected;
|
||||||
Exception = exception;
|
Exception = exception;
|
||||||
AuthenticateResult = authenticateResult;
|
AuthenticateResult = authenticateResult;
|
||||||
|
ReasonCode = reasonCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ClientWasConnected { get; }
|
public bool ClientWasConnected { get; }
|
||||||
@@ -17,5 +18,7 @@ namespace MQTTnet.Client.Disconnecting
|
|||||||
public Exception Exception { get; }
|
public Exception Exception { get; }
|
||||||
|
|
||||||
public MqttClientAuthenticateResult AuthenticateResult { get; }
|
public MqttClientAuthenticateResult AuthenticateResult { get; }
|
||||||
|
|
||||||
|
public MqttClientDisconnectReason ReasonCode { get; set; } = MqttClientDisconnectReason.NormalDisconnection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Client.Subscribing;
|
using MQTTnet.Client.Subscribing;
|
||||||
using MQTTnet.Client.Unsubscribing;
|
using MQTTnet.Client.Unsubscribing;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
namespace MQTTnet.Client
|
||||||
{
|
{
|
||||||
@@ -16,11 +16,12 @@ namespace MQTTnet.Client
|
|||||||
IMqttClientOptions Options { get; }
|
IMqttClientOptions Options { get; }
|
||||||
|
|
||||||
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
||||||
|
|
||||||
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
||||||
|
|
||||||
Task<MqttClientAuthenticateResult> ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken);
|
Task<MqttClientAuthenticateResult> ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken);
|
||||||
Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken);
|
Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken);
|
||||||
|
Task PingAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken);
|
Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken);
|
||||||
Task<MqttClientSubscribeResult> SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken);
|
Task<MqttClientSubscribeResult> SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using MQTTnet.Adapter;
|
using System;
|
||||||
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
|
using MQTTnet.LowLevelClient;
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
namespace MQTTnet.Client
|
||||||
{
|
{
|
||||||
@@ -7,6 +9,14 @@ namespace MQTTnet.Client
|
|||||||
{
|
{
|
||||||
IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory);
|
IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory);
|
||||||
|
|
||||||
|
ILowLevelMqttClient CreateLowLevelMqttClient();
|
||||||
|
|
||||||
|
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger);
|
||||||
|
|
||||||
|
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttClientAdapterFactory clientAdapterFactory);
|
||||||
|
|
||||||
|
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory clientAdapterFactory);
|
||||||
|
|
||||||
IMqttClient CreateMqttClient();
|
IMqttClient CreateMqttClient();
|
||||||
|
|
||||||
IMqttClient CreateMqttClient(IMqttNetLogger logger);
|
IMqttClient CreateMqttClient(IMqttNetLogger logger);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace MQTTnet.Client
|
|||||||
readonly object _disconnectLock = new object();
|
readonly object _disconnectLock = new object();
|
||||||
|
|
||||||
readonly IMqttClientAdapterFactory _adapterFactory;
|
readonly IMqttClientAdapterFactory _adapterFactory;
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
|
|
||||||
CancellationTokenSource _backgroundCancellationTokenSource;
|
CancellationTokenSource _backgroundCancellationTokenSource;
|
||||||
Task _packetReceiverTask;
|
Task _packetReceiverTask;
|
||||||
@@ -40,14 +40,15 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
IMqttChannelAdapter _adapter;
|
IMqttChannelAdapter _adapter;
|
||||||
bool _cleanDisconnectInitiated;
|
bool _cleanDisconnectInitiated;
|
||||||
long _disconnectGate;
|
long _isDisconnectPending;
|
||||||
|
bool _isConnected;
|
||||||
|
|
||||||
public MqttClient(IMqttClientAdapterFactory channelFactory, IMqttNetLogger logger)
|
public MqttClient(IMqttClientAdapterFactory channelFactory, IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_adapterFactory = channelFactory ?? throw new ArgumentNullException(nameof(channelFactory));
|
_adapterFactory = channelFactory ?? throw new ArgumentNullException(nameof(channelFactory));
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttClient));
|
_logger = logger.CreateScopedLogger(nameof(MqttClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
public IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
||||||
@@ -56,7 +57,7 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler { get; set; }
|
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler { get; set; }
|
||||||
|
|
||||||
public bool IsConnected { get; private set; }
|
public bool IsConnected => _isConnected && Interlocked.Read(ref _isDisconnectPending) == 0;
|
||||||
|
|
||||||
public IMqttClientOptions Options { get; private set; }
|
public IMqttClientOptions Options { get; private set; }
|
||||||
|
|
||||||
@@ -81,8 +82,8 @@ namespace MQTTnet.Client
|
|||||||
_backgroundCancellationTokenSource = new CancellationTokenSource();
|
_backgroundCancellationTokenSource = new CancellationTokenSource();
|
||||||
var backgroundCancellationToken = _backgroundCancellationTokenSource.Token;
|
var backgroundCancellationToken = _backgroundCancellationTokenSource.Token;
|
||||||
|
|
||||||
_disconnectGate = 0;
|
_isDisconnectPending = 0;
|
||||||
var adapter = _adapterFactory.CreateClientAdapter(options, _logger);
|
var adapter = _adapterFactory.CreateClientAdapter(options);
|
||||||
_adapter = adapter;
|
_adapter = adapter;
|
||||||
|
|
||||||
using (var combined = CancellationTokenSource.CreateLinkedTokenSource(backgroundCancellationToken, cancellationToken))
|
using (var combined = CancellationTokenSource.CreateLinkedTokenSource(backgroundCancellationToken, cancellationToken))
|
||||||
@@ -107,7 +108,7 @@ namespace MQTTnet.Client
|
|||||||
_keepAlivePacketsSenderTask = Task.Run(() => TrySendKeepAliveMessagesAsync(backgroundCancellationToken), backgroundCancellationToken);
|
_keepAlivePacketsSenderTask = Task.Run(() => TrySendKeepAliveMessagesAsync(backgroundCancellationToken), backgroundCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsConnected = true;
|
_isConnected = true;
|
||||||
|
|
||||||
_logger.Info("Connected.");
|
_logger.Info("Connected.");
|
||||||
|
|
||||||
@@ -157,6 +158,11 @@ namespace MQTTnet.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task PingAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket(), cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken)
|
public Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (data == null) throw new ArgumentNullException(nameof(data));
|
if (data == null) throw new ArgumentNullException(nameof(data));
|
||||||
@@ -239,17 +245,22 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
void Cleanup()
|
void Cleanup()
|
||||||
{
|
{
|
||||||
_backgroundCancellationTokenSource?.Cancel(false);
|
try
|
||||||
_backgroundCancellationTokenSource?.Dispose();
|
{
|
||||||
_backgroundCancellationTokenSource = null;
|
_backgroundCancellationTokenSource?.Cancel(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_backgroundCancellationTokenSource?.Dispose();
|
||||||
|
_backgroundCancellationTokenSource = null;
|
||||||
|
|
||||||
_publishPacketReceiverQueue?.Dispose();
|
_publishPacketReceiverQueue?.Dispose();
|
||||||
_publishPacketReceiverQueue = null;
|
_publishPacketReceiverQueue = null;
|
||||||
|
|
||||||
_adapter?.Dispose();
|
_adapter?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
@@ -283,7 +294,10 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
void ThrowIfNotConnected()
|
void ThrowIfNotConnected()
|
||||||
{
|
{
|
||||||
if (!IsConnected || Interlocked.Read(ref _disconnectGate) == 1) throw new MqttCommunicationException("The client is not connected.");
|
if (!IsConnected || Interlocked.Read(ref _isDisconnectPending) == 1)
|
||||||
|
{
|
||||||
|
throw new MqttCommunicationException("The client is not connected.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrowIfConnected(string message)
|
void ThrowIfConnected(string message)
|
||||||
@@ -293,10 +307,11 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
async Task DisconnectInternalAsync(Task sender, Exception exception, MqttClientAuthenticateResult authenticateResult)
|
async Task DisconnectInternalAsync(Task sender, Exception exception, MqttClientAuthenticateResult authenticateResult)
|
||||||
{
|
{
|
||||||
var clientWasConnected = IsConnected;
|
var clientWasConnected = _isConnected;
|
||||||
|
var reasonCode = MqttClientDisconnectReason.NormalDisconnection;
|
||||||
|
|
||||||
TryInitiateDisconnect();
|
TryInitiateDisconnect();
|
||||||
IsConnected = false;
|
_isConnected = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -311,6 +326,7 @@ namespace MQTTnet.Client
|
|||||||
catch (Exception adapterException)
|
catch (Exception adapterException)
|
||||||
{
|
{
|
||||||
_logger.Warning(adapterException, "Error while disconnecting from adapter.");
|
_logger.Warning(adapterException, "Error while disconnecting from adapter.");
|
||||||
|
reasonCode = MqttClientDisconnectReason.UnspecifiedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -321,11 +337,12 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
await Task.WhenAll(receiverTask, publishPacketReceiverTask, keepAliveTask).ConfigureAwait(false);
|
await Task.WhenAll(receiverTask, publishPacketReceiverTask, keepAliveTask).ConfigureAwait(false);
|
||||||
|
|
||||||
_publishPacketReceiverQueue.Dispose();
|
_publishPacketReceiverQueue?.Dispose();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Warning(e, "Error while waiting for internal tasks.");
|
_logger.Warning(e, "Error while waiting for internal tasks.");
|
||||||
|
reasonCode = MqttClientDisconnectReason.UnspecifiedError;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -339,7 +356,7 @@ namespace MQTTnet.Client
|
|||||||
{
|
{
|
||||||
// This handler must be executed in a new thread because otherwise a dead lock may happen
|
// This handler must be executed in a new thread because otherwise a dead lock may happen
|
||||||
// when trying to reconnect in that handler etc.
|
// when trying to reconnect in that handler etc.
|
||||||
Task.Run(() => disconnectedHandler.HandleDisconnectedAsync(new MqttClientDisconnectedEventArgs(clientWasConnected, exception, authenticateResult))).Forget(_logger);
|
Task.Run(() => disconnectedHandler.HandleDisconnectedAsync(new MqttClientDisconnectedEventArgs(clientWasConnected, exception, authenticateResult, reasonCode))).Forget(_logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,12 +381,9 @@ namespace MQTTnet.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task SendAsync(MqttBasePacket packet, CancellationToken cancellationToken)
|
Task SendAsync(MqttBasePacket packet, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
{
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendTracker.Restart();
|
_sendTracker.Restart();
|
||||||
|
|
||||||
@@ -380,18 +394,18 @@ namespace MQTTnet.Client
|
|||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
_sendTracker.Restart();
|
|
||||||
|
|
||||||
ushort identifier = 0;
|
ushort identifier = 0;
|
||||||
if (requestPacket is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier.HasValue)
|
if (requestPacket is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
identifier = packetWithIdentifier.PacketIdentifier.Value;
|
identifier = packetWithIdentifier.PacketIdentifier.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var packetAwaiter = _packetDispatcher.AddPacketAwaiter<TResponsePacket>(identifier))
|
using (var packetAwaiter = _packetDispatcher.AddAwaiter<TResponsePacket>(identifier))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_sendTracker.Restart();
|
||||||
|
|
||||||
await _adapter.SendPacketAsync(requestPacket, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
await _adapter.SendPacketAsync(requestPacket, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -402,9 +416,7 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await packetAwaiter.WaitOneAsync(Options.CommunicationTimeout).ConfigureAwait(false);
|
return await packetAwaiter.WaitOneAsync(Options.CommunicationTimeout).ConfigureAwait(false);
|
||||||
_receiveTracker.Restart();
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@@ -424,23 +436,23 @@ namespace MQTTnet.Client
|
|||||||
{
|
{
|
||||||
_logger.Verbose("Start sending keep alive packets.");
|
_logger.Verbose("Start sending keep alive packets.");
|
||||||
|
|
||||||
|
var keepAlivePeriod = Options.KeepAlivePeriod;
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// Values described here: [MQTT-3.1.2-24].
|
// Values described here: [MQTT-3.1.2-24].
|
||||||
var keepAliveSendInterval = TimeSpan.FromSeconds(Options.KeepAlivePeriod.TotalSeconds * 0.75);
|
var waitTime = keepAlivePeriod - _sendTracker.Elapsed;
|
||||||
if (Options.KeepAliveSendInterval.HasValue)
|
|
||||||
{
|
|
||||||
keepAliveSendInterval = Options.KeepAliveSendInterval.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var waitTimeSend = keepAliveSendInterval - _sendTracker.Elapsed;
|
if (waitTime <= TimeSpan.Zero)
|
||||||
var waitTimeReceive = keepAliveSendInterval - _receiveTracker.Elapsed;
|
|
||||||
if (waitTimeSend <= TimeSpan.Zero || waitTimeReceive <= TimeSpan.Zero)
|
|
||||||
{
|
{
|
||||||
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket(), cancellationToken).ConfigureAwait(false);
|
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket(), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(keepAliveSendInterval, cancellationToken).ConfigureAwait(false);
|
// Wait a fixed time in all cases. Calculation of the remaining time is complicated
|
||||||
|
// due to some edge cases and was buggy in the past. Now we wait half a second because the
|
||||||
|
// min keep alive value is one second so that the server will wait 1.5 seconds for a PING
|
||||||
|
// packet.
|
||||||
|
await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
@@ -555,12 +567,15 @@ namespace MQTTnet.Client
|
|||||||
{
|
{
|
||||||
await SendAsync(new MqttPingRespPacket(), cancellationToken).ConfigureAwait(false);
|
await SendAsync(new MqttPingRespPacket(), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else if (packet is MqttDisconnectPacket)
|
else if (packet is MqttDisconnectPacket disconnectPacket)
|
||||||
{
|
{
|
||||||
// Also dispatch disconnect to waiting threads to generate a proper exception.
|
// Also dispatch disconnect to waiting threads to generate a proper exception.
|
||||||
_packetDispatcher.Dispatch(packet);
|
_packetDispatcher.Dispatch(packet);
|
||||||
|
|
||||||
await DisconnectAsync(null, cancellationToken).ConfigureAwait(false);
|
await DisconnectAsync(new MqttClientDisconnectOptions()
|
||||||
|
{
|
||||||
|
ReasonCode = (MqttClientDisconnectReason)(disconnectPacket.ReasonCode ?? MqttDisconnectReasonCode.UnspecifiedError)
|
||||||
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else if (packet is MqttAuthPacket authPacket)
|
else if (packet is MqttAuthPacket authPacket)
|
||||||
{
|
{
|
||||||
@@ -622,7 +637,6 @@ namespace MQTTnet.Client
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var publishPacketDequeueResult = await _publishPacketReceiverQueue.TryDequeueAsync(cancellationToken);
|
var publishPacketDequeueResult = await _publishPacketReceiverQueue.TryDequeueAsync(cancellationToken);
|
||||||
|
|
||||||
if (!publishPacketDequeueResult.IsSuccess)
|
if (!publishPacketDequeueResult.IsSuccess)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -749,7 +763,7 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
bool DisconnectIsPending()
|
bool DisconnectIsPending()
|
||||||
{
|
{
|
||||||
return Interlocked.CompareExchange(ref _disconnectGate, 1, 0) != 0;
|
return Interlocked.CompareExchange(ref _isDisconnectPending, 1, 0) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace MQTTnet.Client
|
|||||||
return client.DisconnectAsync(new MqttClientDisconnectOptions());
|
return client.DisconnectAsync(new MqttClientDisconnectOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, params TopicFilter[] topicFilters)
|
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, params MqttTopicFilter[] topicFilters)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||||
@@ -147,7 +147,7 @@ namespace MQTTnet.Client
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, string topic)
|
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient client, string topic)
|
||||||
@@ -155,7 +155,7 @@ namespace MQTTnet.Client
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientUnsubscribeResult> UnsubscribeAsync(this IMqttClient client, params string[] topicFilters)
|
public static Task<MqttClientUnsubscribeResult> UnsubscribeAsync(this IMqttClient client, params string[] topicFilters)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
||||||
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Packets;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MQTTnet.Client.Options
|
namespace MQTTnet.Client.Options
|
||||||
{
|
{
|
||||||
@@ -12,11 +14,9 @@ namespace MQTTnet.Client.Options
|
|||||||
IMqttExtendedAuthenticationExchangeHandler ExtendedAuthenticationExchangeHandler { get; }
|
IMqttExtendedAuthenticationExchangeHandler ExtendedAuthenticationExchangeHandler { get; }
|
||||||
MqttProtocolVersion ProtocolVersion { get; }
|
MqttProtocolVersion ProtocolVersion { get; }
|
||||||
IMqttClientChannelOptions ChannelOptions { get; }
|
IMqttClientChannelOptions ChannelOptions { get; }
|
||||||
|
|
||||||
TimeSpan CommunicationTimeout { get; }
|
TimeSpan CommunicationTimeout { get; }
|
||||||
TimeSpan KeepAlivePeriod { get; }
|
TimeSpan KeepAlivePeriod { get; }
|
||||||
TimeSpan? KeepAliveSendInterval { get; }
|
|
||||||
|
|
||||||
MqttApplicationMessage WillMessage { get; }
|
MqttApplicationMessage WillMessage { get; }
|
||||||
uint? WillDelayInterval { get; }
|
uint? WillDelayInterval { get; }
|
||||||
|
|
||||||
@@ -28,5 +28,6 @@ namespace MQTTnet.Client.Options
|
|||||||
bool? RequestResponseInformation { get; }
|
bool? RequestResponseInformation { get; }
|
||||||
uint? SessionExpiryInterval { get; }
|
uint? SessionExpiryInterval { get; }
|
||||||
ushort? TopicAliasMaximum { get; }
|
ushort? TopicAliasMaximum { get; }
|
||||||
|
List<MqttUserProperty> UserProperties { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Net.Security;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MQTTnet.Client.Options
|
||||||
|
{
|
||||||
|
public class MqttClientCertificateValidationCallbackContext
|
||||||
|
{
|
||||||
|
public X509Certificate Certificate { get; set; }
|
||||||
|
|
||||||
|
public X509Chain Chain { get; set; }
|
||||||
|
|
||||||
|
public SslPolicyErrors SslPolicyErrors { get; set; }
|
||||||
|
|
||||||
|
public IMqttClientChannelOptions ClientOptions { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
||||||
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Packets;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MQTTnet.Client.Options
|
namespace MQTTnet.Client.Options
|
||||||
{
|
{
|
||||||
@@ -15,8 +17,7 @@ namespace MQTTnet.Client.Options
|
|||||||
public IMqttClientChannelOptions ChannelOptions { get; set; }
|
public IMqttClientChannelOptions ChannelOptions { get; set; }
|
||||||
public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
||||||
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(15);
|
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(15);
|
||||||
public TimeSpan? KeepAliveSendInterval { get; set; }
|
|
||||||
|
|
||||||
public MqttApplicationMessage WillMessage { get; set; }
|
public MqttApplicationMessage WillMessage { get; set; }
|
||||||
public uint? WillDelayInterval { get; set; }
|
public uint? WillDelayInterval { get; set; }
|
||||||
|
|
||||||
@@ -29,5 +30,6 @@ namespace MQTTnet.Client.Options
|
|||||||
public bool? RequestResponseInformation { get; set; }
|
public bool? RequestResponseInformation { get; set; }
|
||||||
public uint? SessionExpiryInterval { get; set; }
|
public uint? SessionExpiryInterval { get; set; }
|
||||||
public ushort? TopicAliasMaximum { get; set; }
|
public ushort? TopicAliasMaximum { get; set; }
|
||||||
|
public List<MqttUserProperty> UserProperties { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
using MQTTnet.Client.ExtendedAuthenticationExchange;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Packets;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -38,6 +40,12 @@ namespace MQTTnet.Client.Options
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("This method is no longer supported. The client will send ping requests just before the keep alive interval is going to elapse. As per MQTT RFC the serve has to wait 1.5 times the interval so we don't need this anymore.")]
|
||||||
|
public MqttClientOptionsBuilder WithKeepAliveSendInterval(TimeSpan value)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithNoKeepAlive()
|
public MqttClientOptionsBuilder WithNoKeepAlive()
|
||||||
{
|
{
|
||||||
return WithKeepAlivePeriod(TimeSpan.Zero);
|
return WithKeepAlivePeriod(TimeSpan.Zero);
|
||||||
@@ -49,12 +57,6 @@ namespace MQTTnet.Client.Options
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithKeepAliveSendInterval(TimeSpan value)
|
|
||||||
{
|
|
||||||
_options.KeepAliveSendInterval = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithClientId(string value)
|
public MqttClientOptionsBuilder WithClientId(string value)
|
||||||
{
|
{
|
||||||
_options.ClientId = value;
|
_options.ClientId = value;
|
||||||
@@ -116,6 +118,20 @@ namespace MQTTnet.Client.Options
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithUserProperty(string name, string value)
|
||||||
|
{
|
||||||
|
if (name is null) throw new ArgumentNullException(nameof(name));
|
||||||
|
if (value is null) throw new ArgumentNullException(nameof(value));
|
||||||
|
|
||||||
|
if (_options.UserProperties == null)
|
||||||
|
{
|
||||||
|
_options.UserProperties = new List<MqttUserProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_options.UserProperties.Add(new MqttUserProperty(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
|
public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
|
||||||
{
|
{
|
||||||
byte[] passwordBuffer = null;
|
byte[] passwordBuffer = null;
|
||||||
@@ -261,7 +277,13 @@ namespace MQTTnet.Client.Options
|
|||||||
#else
|
#else
|
||||||
Certificates = _tlsParameters.Certificates?.ToList(),
|
Certificates = _tlsParameters.Certificates?.ToList(),
|
||||||
#endif
|
#endif
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
CertificateValidationCallback = _tlsParameters.CertificateValidationCallback,
|
CertificateValidationCallback = _tlsParameters.CertificateValidationCallback,
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
ApplicationProtocols = _tlsParameters.ApplicationProtocols,
|
||||||
|
#endif
|
||||||
|
CertificateValidationHandler = _tlsParameters.CertificateValidationHandler,
|
||||||
IgnoreCertificateChainErrors = _tlsParameters.IgnoreCertificateChainErrors,
|
IgnoreCertificateChainErrors = _tlsParameters.IgnoreCertificateChainErrors,
|
||||||
IgnoreCertificateRevocationErrors = _tlsParameters.IgnoreCertificateRevocationErrors
|
IgnoreCertificateRevocationErrors = _tlsParameters.IgnoreCertificateRevocationErrors
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,12 +10,15 @@ namespace MQTTnet.Client.Options
|
|||||||
{
|
{
|
||||||
public bool UseTls { get; set; }
|
public bool UseTls { get; set; }
|
||||||
|
|
||||||
|
[Obsolete("This property will be removed soon. Use CertificateValidationHandler instead.")]
|
||||||
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback
|
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Func<MqttClientCertificateValidationCallbackContext, bool> CertificateValidationHandler { get; set; }
|
||||||
|
|
||||||
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
||||||
|
|
||||||
#if WINDOWS_UWP
|
#if WINDOWS_UWP
|
||||||
@@ -23,9 +26,12 @@ namespace MQTTnet.Client.Options
|
|||||||
#else
|
#else
|
||||||
public IEnumerable<X509Certificate> Certificates { get; set; }
|
public IEnumerable<X509Certificate> Certificates { get; set; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public bool AllowUntrustedCertificates { get; set; }
|
#if NETCOREAPP3_1
|
||||||
|
public List<SslApplicationProtocol> ApplicationProtocols { get;set; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public bool AllowUntrustedCertificates { get; set; }
|
||||||
|
|
||||||
public bool IgnoreCertificateChainErrors { get; set; }
|
public bool IgnoreCertificateChainErrors { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,22 @@ namespace MQTTnet.Client.Options
|
|||||||
public bool IgnoreCertificateChainErrors { get; set; }
|
public bool IgnoreCertificateChainErrors { get; set; }
|
||||||
|
|
||||||
public bool AllowUntrustedCertificates { get; set; }
|
public bool AllowUntrustedCertificates { get; set; }
|
||||||
|
|
||||||
#if WINDOWS_UWP
|
#if WINDOWS_UWP
|
||||||
public List<byte[]> Certificates { get; set; }
|
public List<byte[]> Certificates { get; set; }
|
||||||
#else
|
#else
|
||||||
public List<X509Certificate> Certificates { get; set; }
|
public List<X509Certificate> Certificates { get; set; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
public List<SslApplicationProtocol> ApplicationProtocols { get; set; }
|
||||||
|
#endif
|
||||||
|
|
||||||
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
||||||
|
|
||||||
|
[Obsolete("This property will be removed soon. Use CertificateValidationHandler instead.")]
|
||||||
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback { get; set; }
|
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback { get; set; }
|
||||||
|
|
||||||
|
public Func<MqttClientCertificateValidationCallbackContext, bool> CertificateValidationHandler { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace MQTTnet.Client.Subscribing
|
|||||||
{
|
{
|
||||||
public class MqttClientSubscribeOptions
|
public class MqttClientSubscribeOptions
|
||||||
{
|
{
|
||||||
public List<TopicFilter> TopicFilters { get; set; } = new List<TopicFilter>();
|
public List<MqttTopicFilter> TopicFilters { get; set; } = new List<MqttTopicFilter>();
|
||||||
|
|
||||||
public uint? SubscriptionIdentifier { get; set; }
|
public uint? SubscriptionIdentifier { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using MQTTnet.Packets;
|
||||||
using System.Collections.Generic;
|
|
||||||
using MQTTnet.Packets;
|
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MQTTnet.Client.Subscribing
|
namespace MQTTnet.Client.Subscribing
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ namespace MQTTnet.Client.Subscribing
|
|||||||
bool? retainAsPublished = null,
|
bool? retainAsPublished = null,
|
||||||
MqttRetainHandling? retainHandling = null)
|
MqttRetainHandling? retainHandling = null)
|
||||||
{
|
{
|
||||||
return WithTopicFilter(new TopicFilter
|
return WithTopicFilter(new MqttTopicFilter
|
||||||
{
|
{
|
||||||
Topic = topic,
|
Topic = topic,
|
||||||
QualityOfServiceLevel = qualityOfServiceLevel,
|
QualityOfServiceLevel = qualityOfServiceLevel,
|
||||||
@@ -48,30 +48,30 @@ namespace MQTTnet.Client.Subscribing
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientSubscribeOptionsBuilder WithTopicFilter(Action<TopicFilterBuilder> topicFilterBuilder)
|
public MqttClientSubscribeOptionsBuilder WithTopicFilter(Action<MqttTopicFilterBuilder> topicFilterBuilder)
|
||||||
{
|
{
|
||||||
if (topicFilterBuilder == null) throw new ArgumentNullException(nameof(topicFilterBuilder));
|
if (topicFilterBuilder == null) throw new ArgumentNullException(nameof(topicFilterBuilder));
|
||||||
|
|
||||||
var internalTopicFilterBuilder = new TopicFilterBuilder();
|
var internalTopicFilterBuilder = new MqttTopicFilterBuilder();
|
||||||
topicFilterBuilder(internalTopicFilterBuilder);
|
topicFilterBuilder(internalTopicFilterBuilder);
|
||||||
|
|
||||||
return WithTopicFilter(internalTopicFilterBuilder);
|
return WithTopicFilter(internalTopicFilterBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientSubscribeOptionsBuilder WithTopicFilter(TopicFilterBuilder topicFilterBuilder)
|
public MqttClientSubscribeOptionsBuilder WithTopicFilter(MqttTopicFilterBuilder topicFilterBuilder)
|
||||||
{
|
{
|
||||||
if (topicFilterBuilder == null) throw new ArgumentNullException(nameof(topicFilterBuilder));
|
if (topicFilterBuilder == null) throw new ArgumentNullException(nameof(topicFilterBuilder));
|
||||||
|
|
||||||
return WithTopicFilter(topicFilterBuilder.Build());
|
return WithTopicFilter(topicFilterBuilder.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientSubscribeOptionsBuilder WithTopicFilter(TopicFilter topicFilter)
|
public MqttClientSubscribeOptionsBuilder WithTopicFilter(MqttTopicFilter topicFilter)
|
||||||
{
|
{
|
||||||
if (topicFilter == null) throw new ArgumentNullException(nameof(topicFilter));
|
if (topicFilter == null) throw new ArgumentNullException(nameof(topicFilter));
|
||||||
|
|
||||||
if (_subscribeOptions.TopicFilters == null)
|
if (_subscribeOptions.TopicFilters == null)
|
||||||
{
|
{
|
||||||
_subscribeOptions.TopicFilters = new List<TopicFilter>();
|
_subscribeOptions.TopicFilters = new List<MqttTopicFilter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribeOptions.TopicFilters.Add(topicFilter);
|
_subscribeOptions.TopicFilters.Add(topicFilter);
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ namespace MQTTnet.Client.Subscribing
|
|||||||
{
|
{
|
||||||
public class MqttClientSubscribeResultItem
|
public class MqttClientSubscribeResultItem
|
||||||
{
|
{
|
||||||
public MqttClientSubscribeResultItem(TopicFilter topicFilter, MqttClientSubscribeResultCode resultCode)
|
public MqttClientSubscribeResultItem(MqttTopicFilter topicFilter, MqttClientSubscribeResultCode resultCode)
|
||||||
{
|
{
|
||||||
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
|
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
|
||||||
ResultCode = resultCode;
|
ResultCode = resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TopicFilter TopicFilter { get; }
|
public MqttTopicFilter TopicFilter { get; }
|
||||||
|
|
||||||
public MqttClientSubscribeResultCode ResultCode { get; }
|
public MqttClientSubscribeResultCode ResultCode { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace MQTTnet.Client.Unsubscribing
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttClientUnsubscribeOptionsBuilder WithTopicFilter(TopicFilter topicFilter)
|
public MqttClientUnsubscribeOptionsBuilder WithTopicFilter(MqttTopicFilter topicFilter)
|
||||||
{
|
{
|
||||||
if (topicFilter is null) throw new ArgumentNullException(nameof(topicFilter));
|
if (topicFilter is null) throw new ArgumentNullException(nameof(topicFilter));
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ namespace MQTTnet.Diagnostics
|
|||||||
{
|
{
|
||||||
event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
||||||
|
|
||||||
IMqttNetLogger CreateChildLogger(string source);
|
IMqttNetScopedLogger CreateScopedLogger(string source);
|
||||||
|
|
||||||
void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception);
|
void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Diagnostics
|
||||||
|
{
|
||||||
|
public interface IMqttNetScopedLogger
|
||||||
|
{
|
||||||
|
IMqttNetScopedLogger CreateScopedLogger(string source);
|
||||||
|
|
||||||
|
void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,16 +5,7 @@ namespace MQTTnet.Diagnostics
|
|||||||
public class MqttNetLogger : IMqttNetLogger
|
public class MqttNetLogger : IMqttNetLogger
|
||||||
{
|
{
|
||||||
readonly string _logId;
|
readonly string _logId;
|
||||||
readonly string _source;
|
|
||||||
|
|
||||||
readonly MqttNetLogger _parentLogger;
|
|
||||||
|
|
||||||
public MqttNetLogger(string source, string logId)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
_logId = logId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttNetLogger()
|
public MqttNetLogger()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -24,52 +15,41 @@ namespace MQTTnet.Diagnostics
|
|||||||
_logId = logId;
|
_logId = logId;
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttNetLogger(MqttNetLogger parentLogger, string logId, string source)
|
|
||||||
{
|
|
||||||
_parentLogger = parentLogger ?? throw new ArgumentNullException(nameof(parentLogger));
|
|
||||||
_source = source ?? throw new ArgumentNullException(nameof(source));
|
|
||||||
|
|
||||||
_logId = logId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
||||||
|
|
||||||
// TODO: Consider creating a LoggerFactory which will allow creating loggers. The logger factory will
|
// TODO: Consider creating a LoggerFactory which will allow creating loggers. The logger factory will
|
||||||
// be the only place which has the published event.
|
// be the only place which has the published event.
|
||||||
public IMqttNetLogger CreateChildLogger(string source)
|
public IMqttNetScopedLogger CreateScopedLogger(string source)
|
||||||
{
|
{
|
||||||
if (source is null) throw new ArgumentNullException(nameof(source));
|
if (source is null) throw new ArgumentNullException(nameof(source));
|
||||||
|
|
||||||
return new MqttNetLogger(this, _logId, source);
|
return new MqttNetScopedLogger(this, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish(MqttNetLogLevel level, string message, object[] parameters, Exception exception)
|
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
|
||||||
{
|
{
|
||||||
var hasLocalListeners = LogMessagePublished != null;
|
var hasLocalListeners = LogMessagePublished != null;
|
||||||
var hasGlobalListeners = MqttNetGlobalLogger.HasListeners;
|
var hasGlobalListeners = MqttNetGlobalLogger.HasListeners;
|
||||||
|
|
||||||
if (!hasLocalListeners && !hasGlobalListeners && _parentLogger == null)
|
if (!hasLocalListeners && !hasGlobalListeners)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters?.Length > 0)
|
try
|
||||||
{
|
{
|
||||||
try
|
message = string.Format(message ?? string.Empty, parameters);
|
||||||
{
|
}
|
||||||
message = string.Format(message, parameters);
|
catch (FormatException)
|
||||||
}
|
{
|
||||||
catch
|
message = "MESSAGE FORMAT INVALID: " + message;
|
||||||
{
|
|
||||||
message = "MESSAGE FORMAT INVALID: " + message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var logMessage = new MqttNetLogMessage
|
var logMessage = new MqttNetLogMessage
|
||||||
{
|
{
|
||||||
LogId = _logId,
|
LogId = _logId,
|
||||||
Timestamp = DateTime.UtcNow,
|
Timestamp = DateTime.UtcNow,
|
||||||
Source = _source,
|
Source = source,
|
||||||
ThreadId = Environment.CurrentManagedThreadId,
|
ThreadId = Environment.CurrentManagedThreadId,
|
||||||
Level = level,
|
Level = level,
|
||||||
Message = message,
|
Message = message,
|
||||||
@@ -85,15 +65,6 @@ namespace MQTTnet.Diagnostics
|
|||||||
{
|
{
|
||||||
LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
|
LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
_parentLogger?.Publish(logMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Publish(MqttNetLogMessage logMessage)
|
|
||||||
{
|
|
||||||
LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
|
|
||||||
|
|
||||||
_parentLogger?.Publish(logMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Diagnostics
|
|
||||||
{
|
|
||||||
public static class MqttNetLoggerExtensions
|
|
||||||
{
|
|
||||||
public static void Verbose(this IMqttNetLogger logger, string message, params object[] parameters)
|
|
||||||
{
|
|
||||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
logger.Publish(MqttNetLogLevel.Verbose, message, parameters, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Info(this IMqttNetLogger logger, string message, params object[] parameters)
|
|
||||||
{
|
|
||||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
logger.Publish(MqttNetLogLevel.Info, message, parameters, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(this IMqttNetLogger logger, Exception exception, string message, params object[] parameters)
|
|
||||||
{
|
|
||||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
logger.Publish(MqttNetLogLevel.Warning, message, parameters, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(this IMqttNetLogger logger, Exception exception, string message, params object[] parameters)
|
|
||||||
{
|
|
||||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
logger.Publish(MqttNetLogLevel.Error, message, parameters, exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Diagnostics
|
||||||
|
{
|
||||||
|
public sealed class MqttNetScopedLogger : IMqttNetScopedLogger
|
||||||
|
{
|
||||||
|
readonly IMqttNetLogger _logger;
|
||||||
|
readonly string _source;
|
||||||
|
|
||||||
|
public MqttNetScopedLogger(IMqttNetLogger logger, string source)
|
||||||
|
{
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
_source = source ?? throw new ArgumentNullException(nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttNetScopedLogger CreateScopedLogger(string source)
|
||||||
|
{
|
||||||
|
return new MqttNetScopedLogger(_logger, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception)
|
||||||
|
{
|
||||||
|
_logger.Publish(logLevel, _source, message, parameters, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Diagnostics
|
||||||
|
{
|
||||||
|
public static class MqttNetScopedLoggerExtensions
|
||||||
|
{
|
||||||
|
public static void Verbose(this IMqttNetScopedLogger logger, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
logger.Publish(MqttNetLogLevel.Verbose, message, parameters, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Info(this IMqttNetScopedLogger logger, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
logger.Publish(MqttNetLogLevel.Info, message, parameters, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warning(this IMqttNetScopedLogger logger, Exception exception, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
logger.Publish(MqttNetLogLevel.Warning, message, parameters, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(this IMqttNetScopedLogger logger, Exception exception, string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
logger.Publish(MqttNetLogLevel.Error, message, parameters, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,8 +16,12 @@
|
|||||||
return "netstandard1.3";
|
return "netstandard1.3";
|
||||||
#elif NETSTANDARD2_0
|
#elif NETSTANDARD2_0
|
||||||
return "netstandard2.0";
|
return "netstandard2.0";
|
||||||
|
#elif NETSTANDARD2_1
|
||||||
|
return "netstandard2.1";
|
||||||
#elif WINDOWS_UWP
|
#elif WINDOWS_UWP
|
||||||
return "uap10.0";
|
return "uap10.0";
|
||||||
|
#elif NETCOREAPP3_1
|
||||||
|
return "netcoreapp3.1";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ namespace MQTTnet.Formatter
|
|||||||
{
|
{
|
||||||
if (_length < _offset + length)
|
if (_length < _offset + length)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {_offset + length} bytes but there are only {_length} bytes");
|
throw new MqttProtocolViolationException($"Expected at least {_offset + length} bytes but there are only {_length} bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter.V3;
|
using MQTTnet.Formatter.V3;
|
||||||
@@ -9,12 +10,7 @@ namespace MQTTnet.Formatter
|
|||||||
{
|
{
|
||||||
public class MqttPacketFormatterAdapter
|
public class MqttPacketFormatterAdapter
|
||||||
{
|
{
|
||||||
private IMqttPacketFormatter _formatter;
|
IMqttPacketFormatter _formatter;
|
||||||
|
|
||||||
public MqttPacketFormatterAdapter()
|
|
||||||
: this(new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttPacketFormatterAdapter(MqttProtocolVersion protocolVersion)
|
public MqttPacketFormatterAdapter(MqttProtocolVersion protocolVersion)
|
||||||
: this(protocolVersion, new MqttPacketWriter())
|
: this(protocolVersion, new MqttPacketWriter())
|
||||||
@@ -120,10 +116,18 @@ namespace MQTTnet.Formatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MqttProtocolVersion ParseProtocolVersion(ReceivedMqttPacket receivedMqttPacket)
|
MqttProtocolVersion ParseProtocolVersion(ReceivedMqttPacket receivedMqttPacket)
|
||||||
{
|
{
|
||||||
if (receivedMqttPacket == null) throw new ArgumentNullException(nameof(receivedMqttPacket));
|
if (receivedMqttPacket == null) throw new ArgumentNullException(nameof(receivedMqttPacket));
|
||||||
|
|
||||||
|
if (receivedMqttPacket.Body.Length < 7)
|
||||||
|
{
|
||||||
|
// 2 byte protocol name length
|
||||||
|
// at least 4 byte protocol name
|
||||||
|
// 1 byte protocol level
|
||||||
|
throw new MqttProtocolViolationException("CONNECT packet must have at least 7 bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
var protocolName = receivedMqttPacket.Body.ReadStringWithLengthPrefix();
|
var protocolName = receivedMqttPacket.Body.ReadStringWithLengthPrefix();
|
||||||
var protocolLevel = receivedMqttPacket.Body.ReadByte();
|
var protocolLevel = receivedMqttPacket.Body.ReadByte();
|
||||||
|
|
||||||
@@ -155,7 +159,8 @@ namespace MQTTnet.Formatter
|
|||||||
throw new MqttProtocolViolationException($"Protocol '{protocolName}' not supported.");
|
throw new MqttProtocolViolationException($"Protocol '{protocolName}' not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowIfFormatterNotSet()
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
void ThrowIfFormatterNotSet()
|
||||||
{
|
{
|
||||||
if (_formatter == null)
|
if (_formatter == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ namespace MQTTnet.Formatter
|
|||||||
/// same as for the original MemoryStream in .net. Also this implementation allows accessing the internal
|
/// same as for the original MemoryStream in .net. Also this implementation allows accessing the internal
|
||||||
/// buffer for all platforms and .net framework versions (which is not available at the regular MemoryStream).
|
/// buffer for all platforms and .net framework versions (which is not available at the regular MemoryStream).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttPacketWriter : IMqttPacketWriter
|
public sealed class MqttPacketWriter : IMqttPacketWriter
|
||||||
{
|
{
|
||||||
private static readonly ArraySegment<byte> ZeroVariableLengthIntegerArray = new ArraySegment<byte>(new byte[1], 0, 1);
|
static readonly ArraySegment<byte> ZeroVariableLengthIntegerArray = new ArraySegment<byte>(new byte[1], 0, 1);
|
||||||
private static readonly ArraySegment<byte> ZeroTwoByteIntegerArray = new ArraySegment<byte>(new byte[2], 0, 2);
|
static readonly ArraySegment<byte> ZeroTwoByteIntegerArray = new ArraySegment<byte>(new byte[2], 0, 2);
|
||||||
|
|
||||||
public static int InitialBufferSize = 128;
|
public static int InitialBufferSize = 128;
|
||||||
public static int MaxBufferSize = 4096;
|
public static int MaxBufferSize = 4096;
|
||||||
|
|
||||||
private byte[] _buffer = new byte[InitialBufferSize];
|
byte[] _buffer = new byte[InitialBufferSize];
|
||||||
|
|
||||||
private int _offset;
|
int _offset;
|
||||||
|
|
||||||
public int Length { get; private set; }
|
public int Length { get; private set; }
|
||||||
|
|
||||||
@@ -191,13 +191,13 @@ namespace MQTTnet.Formatter
|
|||||||
Array.Resize(ref _buffer, MaxBufferSize);
|
Array.Resize(ref _buffer, MaxBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Write(ArraySegment<byte> buffer)
|
void Write(ArraySegment<byte> buffer)
|
||||||
{
|
{
|
||||||
Write(buffer.Array, buffer.Offset, buffer.Count);
|
Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void EnsureAdditionalCapacity(int additionalCapacity)
|
void EnsureAdditionalCapacity(int additionalCapacity)
|
||||||
{
|
{
|
||||||
var freeSpace = _buffer.Length - _offset;
|
var freeSpace = _buffer.Length - _offset;
|
||||||
if (freeSpace >= additionalCapacity)
|
if (freeSpace >= additionalCapacity)
|
||||||
@@ -209,7 +209,7 @@ namespace MQTTnet.Formatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void EnsureCapacity(int capacity)
|
void EnsureCapacity(int capacity)
|
||||||
{
|
{
|
||||||
var newBufferLength = _buffer.Length;
|
var newBufferLength = _buffer.Length;
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ namespace MQTTnet.Formatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void IncreasePosition(int length)
|
void IncreasePosition(int length)
|
||||||
{
|
{
|
||||||
_offset += length;
|
_offset += length;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
@@ -9,26 +10,19 @@ namespace MQTTnet.Formatter.V3
|
|||||||
{
|
{
|
||||||
public class MqttV310PacketFormatter : IMqttPacketFormatter
|
public class MqttV310PacketFormatter : IMqttPacketFormatter
|
||||||
{
|
{
|
||||||
private const int FixedHeaderSize = 1;
|
const int FixedHeaderSize = 1;
|
||||||
|
|
||||||
private static readonly MqttPingReqPacket PingReqPacket = new MqttPingReqPacket();
|
static readonly MqttPingReqPacket PingReqPacket = new MqttPingReqPacket();
|
||||||
private static readonly MqttPingRespPacket PingRespPacket = new MqttPingRespPacket();
|
static readonly MqttPingRespPacket PingRespPacket = new MqttPingRespPacket();
|
||||||
private static readonly MqttDisconnectPacket DisconnectPacket = new MqttDisconnectPacket();
|
static readonly MqttDisconnectPacket DisconnectPacket = new MqttDisconnectPacket();
|
||||||
|
|
||||||
private readonly IMqttPacketWriter _packetWriter;
|
readonly IMqttPacketWriter _packetWriter;
|
||||||
|
|
||||||
public MqttV310PacketFormatter()
|
|
||||||
: this(new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttV310PacketFormatter(IMqttPacketWriter packetWriter)
|
public MqttV310PacketFormatter(IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
_packetWriter = packetWriter;
|
_packetWriter = packetWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IMqttDataConverter DataConverter { get; } = new MqttV310DataConverter();
|
public IMqttDataConverter DataConverter { get; } = new MqttV310DataConverter();
|
||||||
|
|
||||||
public ArraySegment<byte> Encode(MqttBasePacket packet)
|
public ArraySegment<byte> Encode(MqttBasePacket packet)
|
||||||
@@ -93,7 +87,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
_packetWriter.FreeBuffer();
|
_packetWriter.FreeBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte EncodePacket(MqttBasePacket packet, IMqttPacketWriter packetWriter)
|
byte EncodePacket(MqttBasePacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
switch (packet)
|
switch (packet)
|
||||||
{
|
{
|
||||||
@@ -116,7 +110,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodeUnsubAckPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodeUnsubAckPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -126,7 +120,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodePubCompPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodePubCompPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -136,7 +130,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodePubRelPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodePubRelPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -146,7 +140,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodePubRecPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodePubRecPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -156,7 +150,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodePubAckPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodePubAckPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -166,7 +160,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodeUnsubscribePacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodeUnsubscribePacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -183,7 +177,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodeSubscribePacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodeSubscribePacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -194,7 +188,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
|
|
||||||
while (!body.EndOfStream)
|
while (!body.EndOfStream)
|
||||||
{
|
{
|
||||||
var topicFilter = new TopicFilter
|
var topicFilter = new MqttTopicFilter
|
||||||
{
|
{
|
||||||
Topic = body.ReadStringWithLengthPrefix(),
|
Topic = body.ReadStringWithLengthPrefix(),
|
||||||
QualityOfServiceLevel = (MqttQualityOfServiceLevel)body.ReadByte()
|
QualityOfServiceLevel = (MqttQualityOfServiceLevel)body.ReadByte()
|
||||||
@@ -206,7 +200,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodePublishPacket(ReceivedMqttPacket receivedMqttPacket)
|
static MqttBasePacket DecodePublishPacket(ReceivedMqttPacket receivedMqttPacket)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(receivedMqttPacket.Body);
|
ThrowIfBodyIsEmpty(receivedMqttPacket.Body);
|
||||||
|
|
||||||
@@ -239,7 +233,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MqttBasePacket DecodeConnectPacket(IMqttPacketBodyReader body)
|
MqttBasePacket DecodeConnectPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -300,7 +294,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DecodeSubAckPacket(IMqttPacketBodyReader body)
|
static MqttBasePacket DecodeSubAckPacket(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
ThrowIfBodyIsEmpty(body);
|
ThrowIfBodyIsEmpty(body);
|
||||||
|
|
||||||
@@ -340,7 +334,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
||||||
private static void ValidatePublishPacket(MqttPublishPacket packet)
|
static void ValidatePublishPacket(MqttPublishPacket packet)
|
||||||
{
|
{
|
||||||
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
|
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
|
||||||
{
|
{
|
||||||
@@ -418,7 +412,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodePubRelPacket(MqttPubRelPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodePubRelPacket(MqttPubRelPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -430,7 +424,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodePublishPacket(MqttPublishPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodePublishPacket(MqttPublishPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
ValidatePublishPacket(packet);
|
ValidatePublishPacket(packet);
|
||||||
|
|
||||||
@@ -475,7 +469,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodePubAckPacket(MqttPubAckPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodePubAckPacket(MqttPubAckPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -487,7 +481,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodePubRecPacket(MqttPubRecPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodePubRecPacket(MqttPubRecPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -499,7 +493,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRec);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRec);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodePubCompPacket(MqttPubCompPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodePubCompPacket(MqttPubCompPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -511,7 +505,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodeSubscribePacket(MqttSubscribePacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodeSubscribePacket(MqttSubscribePacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
|
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
|
||||||
|
|
||||||
@@ -534,7 +528,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodeSubAckPacket(MqttSubAckPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodeSubAckPacket(MqttSubAckPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -554,7 +548,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
|
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
|
||||||
|
|
||||||
@@ -576,7 +570,7 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodeUnsubAckPacket(MqttUnsubAckPacket packet, IMqttPacketWriter packetWriter)
|
static byte EncodeUnsubAckPacket(MqttUnsubAckPacket packet, IMqttPacketWriter packetWriter)
|
||||||
{
|
{
|
||||||
if (!packet.PacketIdentifier.HasValue)
|
if (!packet.PacketIdentifier.HasValue)
|
||||||
{
|
{
|
||||||
@@ -587,12 +581,12 @@ namespace MQTTnet.Formatter.V3
|
|||||||
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck);
|
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte EncodeEmptyPacket(MqttControlPacketType type)
|
static byte EncodeEmptyPacket(MqttControlPacketType type)
|
||||||
{
|
{
|
||||||
return MqttPacketWriter.BuildFixedHeader(type);
|
return MqttPacketWriter.BuildFixedHeader(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
protected static void ThrowIfBodyIsEmpty(IMqttPacketBodyReader body)
|
protected static void ThrowIfBodyIsEmpty(IMqttPacketBodyReader body)
|
||||||
{
|
{
|
||||||
if (body == null || body.Length == 0)
|
if (body == null || body.Length == 0)
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ namespace MQTTnet.Formatter.V3
|
|||||||
{
|
{
|
||||||
public class MqttV311PacketFormatter : MqttV310PacketFormatter
|
public class MqttV311PacketFormatter : MqttV310PacketFormatter
|
||||||
{
|
{
|
||||||
public MqttV311PacketFormatter()
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttV311PacketFormatter(IMqttPacketWriter packetWriter)
|
public MqttV311PacketFormatter(IMqttPacketWriter packetWriter)
|
||||||
: base(packetWriter)
|
: base(packetWriter)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Client.Publishing;
|
using MQTTnet.Client.Publishing;
|
||||||
@@ -11,7 +8,9 @@ using MQTTnet.Exceptions;
|
|||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using MqttClientSubscribeResult = MQTTnet.Client.Subscribing.MqttClientSubscribeResult;
|
using MqttClientSubscribeResult = MQTTnet.Client.Subscribing.MqttClientSubscribeResult;
|
||||||
|
|
||||||
namespace MQTTnet.Formatter.V5
|
namespace MQTTnet.Formatter.V5
|
||||||
@@ -127,7 +126,8 @@ namespace MQTTnet.Formatter.V5
|
|||||||
RequestProblemInformation = options.RequestProblemInformation,
|
RequestProblemInformation = options.RequestProblemInformation,
|
||||||
RequestResponseInformation = options.RequestResponseInformation,
|
RequestResponseInformation = options.RequestResponseInformation,
|
||||||
SessionExpiryInterval = options.SessionExpiryInterval,
|
SessionExpiryInterval = options.SessionExpiryInterval,
|
||||||
TopicAliasMaximum = options.TopicAliasMaximum
|
TopicAliasMaximum = options.TopicAliasMaximum,
|
||||||
|
UserProperties = options.UserProperties
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -244,11 +244,11 @@ namespace MQTTnet.Formatter.V5
|
|||||||
{
|
{
|
||||||
// QoS 0 has no response. So we treat it as a success always.
|
// QoS 0 has no response. So we treat it as a success always.
|
||||||
// Both enums have the same values. So it can be easily converted.
|
// Both enums have the same values. So it can be easily converted.
|
||||||
result.ReasonCode = (MqttClientPublishReasonCode)pubAckPacket.ReasonCode;
|
result.ReasonCode = (MqttClientPublishReasonCode)pubAckPacket.ReasonCode;
|
||||||
|
|
||||||
result.PacketIdentifier = pubAckPacket.PacketIdentifier;
|
result.PacketIdentifier = pubAckPacket.PacketIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ namespace MQTTnet.Formatter.V5
|
|||||||
var retainAsPublished = (options & (1 << 3)) > 0;
|
var retainAsPublished = (options & (1 << 3)) > 0;
|
||||||
var retainHandling = (MqttRetainHandling)((options >> 4) & 3);
|
var retainHandling = (MqttRetainHandling)((options >> 4) & 3);
|
||||||
|
|
||||||
packet.TopicFilters.Add(new TopicFilter
|
packet.TopicFilters.Add(new MqttTopicFilter
|
||||||
{
|
{
|
||||||
Topic = topic,
|
Topic = topic,
|
||||||
QualityOfServiceLevel = qos,
|
QualityOfServiceLevel = qos,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using MQTTnet.Client;
|
using System.Collections.Generic;
|
||||||
|
using MQTTnet.Client;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
@@ -7,5 +8,7 @@ namespace MQTTnet
|
|||||||
public interface IMqttFactory : IMqttClientFactory, IMqttServerFactory
|
public interface IMqttFactory : IMqttClientFactory, IMqttServerFactory
|
||||||
{
|
{
|
||||||
IMqttNetLogger DefaultLogger { get; }
|
IMqttNetLogger DefaultLogger { get; }
|
||||||
|
|
||||||
|
IDictionary<object, object> Properties { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -10,6 +11,8 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
readonly Socket _socket;
|
readonly Socket _socket;
|
||||||
|
|
||||||
|
NetworkStream _networkStream;
|
||||||
|
|
||||||
public CrossPlatformSocket(AddressFamily addressFamily)
|
public CrossPlatformSocket(AddressFamily addressFamily)
|
||||||
{
|
{
|
||||||
_socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
|
_socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
@@ -17,7 +20,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public CrossPlatformSocket()
|
public CrossPlatformSocket()
|
||||||
{
|
{
|
||||||
// Having this contructor is important because avoiding the address family as parameter
|
// Having this constructor is important because avoiding the address family as parameter
|
||||||
// will make use of dual mode in the .net framework.
|
// will make use of dual mode in the .net framework.
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||||
}
|
}
|
||||||
@@ -25,79 +28,39 @@ namespace MQTTnet.Implementations
|
|||||||
public CrossPlatformSocket(Socket socket)
|
public CrossPlatformSocket(Socket socket)
|
||||||
{
|
{
|
||||||
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
|
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
|
||||||
|
_networkStream = new NetworkStream(socket, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool NoDelay
|
public bool NoDelay
|
||||||
{
|
{
|
||||||
get
|
get => (int)_socket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay) > 0;
|
||||||
{
|
set => _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
|
||||||
return (int)_socket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DualMode
|
public bool DualMode
|
||||||
{
|
{
|
||||||
get
|
get => _socket.DualMode;
|
||||||
{
|
set => _socket.DualMode = value;
|
||||||
return _socket.DualMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_socket.DualMode = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ReceiveBufferSize
|
public int ReceiveBufferSize
|
||||||
{
|
{
|
||||||
get
|
get => _socket.ReceiveBufferSize;
|
||||||
{
|
set => _socket.ReceiveBufferSize = value;
|
||||||
return _socket.ReceiveBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_socket.ReceiveBufferSize = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int SendBufferSize
|
public int SendBufferSize
|
||||||
{
|
{
|
||||||
get
|
get => _socket.SendBufferSize;
|
||||||
{
|
set => _socket.SendBufferSize = value;
|
||||||
return _socket.SendBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_socket.SendBufferSize = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EndPoint RemoteEndPoint
|
public EndPoint RemoteEndPoint => _socket.RemoteEndPoint;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _socket.RemoteEndPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ReuseAddress
|
public bool ReuseAddress
|
||||||
{
|
{
|
||||||
get
|
get => (int)_socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress) != 0;
|
||||||
{
|
set => _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, value ? 1 : 0);
|
||||||
return (int)_socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, value ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CrossPlatformSocket> AcceptAsync()
|
public async Task<CrossPlatformSocket> AcceptAsync()
|
||||||
@@ -137,7 +100,9 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Workaround for: workaround for https://github.com/dotnet/corefx/issues/24430
|
_networkStream?.Dispose();
|
||||||
|
|
||||||
|
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
||||||
using (cancellationToken.Register(() => _socket.Dispose()))
|
using (cancellationToken.Register(() => _socket.Dispose()))
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@@ -147,6 +112,7 @@ namespace MQTTnet.Implementations
|
|||||||
#else
|
#else
|
||||||
await _socket.ConnectAsync(host, port).ConfigureAwait(false);
|
await _socket.ConnectAsync(host, port).ConfigureAwait(false);
|
||||||
#endif
|
#endif
|
||||||
|
_networkStream = new NetworkStream(_socket, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
@@ -190,11 +156,18 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public NetworkStream GetStream()
|
public NetworkStream GetStream()
|
||||||
{
|
{
|
||||||
return new NetworkStream(_socket, true);
|
var networkStream = _networkStream;
|
||||||
|
if (networkStream == null)
|
||||||
|
{
|
||||||
|
throw new IOException("The socket is not connected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return networkStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_networkStream?.Dispose();
|
||||||
_socket?.Dispose();
|
_socket?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public class MqttClientAdapterFactory : IMqttClientAdapterFactory
|
public class MqttClientAdapterFactory : IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetLogger logger)
|
readonly IMqttNetLogger _logger;
|
||||||
|
|
||||||
|
public MqttClientAdapterFactory(IMqttNetLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
@@ -16,12 +23,12 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
case MqttClientTcpOptions _:
|
case MqttClientTcpOptions _:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttPacketWriter()), _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
case MqttClientWebSocketOptions webSocketOptions:
|
case MqttClientWebSocketOptions webSocketOptions:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttPacketWriter()), _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ using MQTTnet.Server;
|
|||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttTcpChannel : IMqttChannel
|
public sealed class MqttTcpChannel : IMqttChannel
|
||||||
{
|
{
|
||||||
private readonly MqttClientTcpOptions _options;
|
readonly MqttClientTcpOptions _options;
|
||||||
private readonly int _bufferSize;
|
readonly int _bufferSize;
|
||||||
|
|
||||||
private StreamSocket _socket;
|
StreamSocket _socket;
|
||||||
private Stream _readStream;
|
Stream _readStream;
|
||||||
private Stream _writeStream;
|
Stream _writeStream;
|
||||||
|
|
||||||
public MqttTcpChannel(IMqttClientOptions clientOptions)
|
public MqttTcpChannel(IMqttClientOptions clientOptions)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (_options.TlsOptions?.UseTls != true)
|
if (_options.TlsOptions?.UseTls != true)
|
||||||
{
|
{
|
||||||
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString());
|
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString()).AsTask().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,7 @@ namespace MQTTnet.Implementations
|
|||||||
socketProtectionLevel = SocketProtectionLevel.Tls10;
|
socketProtectionLevel = SocketProtectionLevel.Tls10;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), socketProtectionLevel);
|
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), socketProtectionLevel).AsTask().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint = _socket.Information.RemoteAddress + ":" + _socket.Information.RemotePort;
|
Endpoint = _socket.Information.RemoteAddress + ":" + _socket.Information.RemotePort;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public sealed class MqttTcpChannel : IDisposable, IMqttChannel
|
public sealed class MqttTcpChannel : IMqttChannel
|
||||||
{
|
{
|
||||||
readonly IMqttClientOptions _clientOptions;
|
readonly IMqttClientOptions _clientOptions;
|
||||||
readonly MqttClientTcpOptions _options;
|
readonly MqttClientTcpOptions _options;
|
||||||
@@ -46,54 +46,81 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public async Task ConnectAsync(CancellationToken cancellationToken)
|
public async Task ConnectAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CrossPlatformSocket socket;
|
CrossPlatformSocket socket = null;
|
||||||
|
try
|
||||||
if (_options.AddressFamily == AddressFamily.Unspecified)
|
|
||||||
{
|
{
|
||||||
socket = new CrossPlatformSocket();
|
if (_options.AddressFamily == AddressFamily.Unspecified)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
socket = new CrossPlatformSocket(_options.AddressFamily);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.ReceiveBufferSize = _options.BufferSize;
|
|
||||||
socket.SendBufferSize = _options.BufferSize;
|
|
||||||
socket.NoDelay = _options.NoDelay;
|
|
||||||
|
|
||||||
if (_options.DualMode.HasValue)
|
|
||||||
{
|
|
||||||
// It is important to avoid setting the flag if no specific value is set by the user
|
|
||||||
// because on IPv4 only networks the setter will always throw an exception. Regardless
|
|
||||||
// of the actual value.
|
|
||||||
socket.DualMode = _options.DualMode.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
await socket.ConnectAsync(_options.Server, _options.GetPort(), cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var networkStream = socket.GetStream();
|
|
||||||
|
|
||||||
if (_options.TlsOptions.UseTls)
|
|
||||||
{
|
|
||||||
var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), _options.TlsOptions.SslProtocol, !_options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
socket = new CrossPlatformSocket();
|
||||||
}
|
}
|
||||||
catch
|
else
|
||||||
{
|
{
|
||||||
sslStream.Dispose();
|
socket = new CrossPlatformSocket(_options.AddressFamily);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_stream = sslStream;
|
socket.ReceiveBufferSize = _options.BufferSize;
|
||||||
}
|
socket.SendBufferSize = _options.BufferSize;
|
||||||
else
|
socket.NoDelay = _options.NoDelay;
|
||||||
{
|
|
||||||
_stream = networkStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
Endpoint = socket.RemoteEndPoint?.ToString();
|
if (_options.DualMode.HasValue)
|
||||||
|
{
|
||||||
|
// It is important to avoid setting the flag if no specific value is set by the user
|
||||||
|
// because on IPv4 only networks the setter will always throw an exception. Regardless
|
||||||
|
// of the actual value.
|
||||||
|
socket.DualMode = _options.DualMode.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
await socket.ConnectAsync(_options.Server, _options.GetPort(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var networkStream = socket.GetStream();
|
||||||
|
|
||||||
|
if (_options.TlsOptions?.UseTls == true)
|
||||||
|
{
|
||||||
|
var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
var sslOptions = new SslClientAuthenticationOptions
|
||||||
|
{
|
||||||
|
ApplicationProtocols = _options.TlsOptions.ApplicationProtocols,
|
||||||
|
ClientCertificates = LoadCertificates(),
|
||||||
|
EnabledSslProtocols = _options.TlsOptions.SslProtocol,
|
||||||
|
CertificateRevocationCheckMode = _options.TlsOptions.IgnoreCertificateRevocationErrors ? X509RevocationMode.Online : X509RevocationMode.NoCheck,
|
||||||
|
TargetHost = _options.Server
|
||||||
|
};
|
||||||
|
|
||||||
|
await sslStream.AuthenticateAsClientAsync(sslOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
#else
|
||||||
|
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), _options.TlsOptions.SslProtocol, !_options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
#if NETSTANDARD2_1 || NETCOREAPP3_1
|
||||||
|
await sslStream.DisposeAsync().ConfigureAwait(false);
|
||||||
|
#else
|
||||||
|
sslStream.Dispose();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stream = sslStream;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_stream = networkStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoint = socket.RemoteEndPoint?.ToString();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
socket?.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DisconnectAsync(CancellationToken cancellationToken)
|
public Task DisconnectAsync(CancellationToken cancellationToken)
|
||||||
@@ -106,19 +133,27 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
||||||
using (cancellationToken.Register(Dispose))
|
using (cancellationToken.Register(Dispose))
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
var stream = _stream;
|
||||||
|
|
||||||
return await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
if (stream == null)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(nameof(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
return await stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return -1;
|
// Indicate a graceful socket close.
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
catch (IOException exception)
|
catch (IOException exception)
|
||||||
{
|
{
|
||||||
@@ -135,19 +170,25 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
||||||
using (cancellationToken.Register(Dispose))
|
using (cancellationToken.Register(Dispose))
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
var stream = _stream;
|
||||||
|
|
||||||
await _stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
if (stream == null)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(nameof(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch (IOException exception)
|
catch (IOException exception)
|
||||||
{
|
{
|
||||||
@@ -181,9 +222,29 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||||
{
|
{
|
||||||
if (_options.TlsOptions.CertificateValidationCallback != null)
|
#region OBSOLETE
|
||||||
|
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
var certificateValidationCallback = _options?.TlsOptions?.CertificateValidationCallback;
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
if (certificateValidationCallback != null)
|
||||||
{
|
{
|
||||||
return _options.TlsOptions.CertificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _clientOptions);
|
return certificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _clientOptions);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var certificateValidationHandler = _options?.TlsOptions?.CertificateValidationHandler;
|
||||||
|
if (certificateValidationHandler != null)
|
||||||
|
{
|
||||||
|
var context = new MqttClientCertificateValidationCallbackContext
|
||||||
|
{
|
||||||
|
Certificate = x509Certificate,
|
||||||
|
Chain = chain,
|
||||||
|
SslPolicyErrors = sslPolicyErrors,
|
||||||
|
ClientOptions = _options
|
||||||
|
};
|
||||||
|
|
||||||
|
return certificateValidationHandler(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslPolicyErrors == SslPolicyErrors.None)
|
if (sslPolicyErrors == SslPolicyErrors.None)
|
||||||
@@ -193,7 +254,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.RevocationStatusUnknown || c.Status == X509ChainStatusFlags.Revoked || c.Status == X509ChainStatusFlags.OfflineRevocation))
|
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.RevocationStatusUnknown || c.Status == X509ChainStatusFlags.Revoked || c.Status == X509ChainStatusFlags.OfflineRevocation))
|
||||||
{
|
{
|
||||||
if (!_options.TlsOptions.IgnoreCertificateRevocationErrors)
|
if (_options?.TlsOptions?.IgnoreCertificateRevocationErrors != true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -201,13 +262,13 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.PartialChain))
|
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.PartialChain))
|
||||||
{
|
{
|
||||||
if (!_options.TlsOptions.IgnoreCertificateChainErrors)
|
if (_options?.TlsOptions?.IgnoreCertificateChainErrors != true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _options.TlsOptions.AllowUntrustedCertificates;
|
return _options?.TlsOptions?.AllowUntrustedCertificates == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
X509CertificateCollection LoadCertificates()
|
X509CertificateCollection LoadCertificates()
|
||||||
|
|||||||
@@ -13,16 +13,16 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttTcpServerAdapter : IMqttServerAdapter
|
public sealed class MqttTcpServerAdapter : IMqttServerAdapter
|
||||||
{
|
{
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
|
readonly IMqttNetLogger _rootLogger;
|
||||||
|
|
||||||
IMqttServerOptions _options;
|
IMqttServerOptions _options;
|
||||||
StreamSocketListener _listener;
|
StreamSocketListener _listener;
|
||||||
|
|
||||||
public MqttTcpServerAdapter(IMqttNetLogger logger)
|
public MqttTcpServerAdapter(IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
_logger = logger.CreateScopedLogger(nameof(MqttTcpServerAdapter));
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||||
@@ -89,7 +89,7 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket, clientCertificate, _options), new MqttPacketFormatterAdapter(), _logger))
|
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket, clientCertificate, _options), new MqttPacketFormatterAdapter(new MqttPacketWriter()), _rootLogger))
|
||||||
{
|
{
|
||||||
await clientHandler(clientAdapter).ConfigureAwait(false);
|
await clientHandler(clientAdapter).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#if !WINDOWS_UWP
|
#if !WINDOWS_UWP
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Internal;
|
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,18 +12,18 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public sealed class MqttTcpServerAdapter : Disposable, IMqttServerAdapter
|
public sealed class MqttTcpServerAdapter : IMqttServerAdapter
|
||||||
{
|
{
|
||||||
readonly List<MqttTcpServerListener> _listeners = new List<MqttTcpServerListener>();
|
readonly List<MqttTcpServerListener> _listeners = new List<MqttTcpServerListener>();
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
|
readonly IMqttNetLogger _rootLogger;
|
||||||
|
|
||||||
CancellationTokenSource _cancellationTokenSource;
|
CancellationTokenSource _cancellationTokenSource;
|
||||||
|
|
||||||
public MqttTcpServerAdapter(IMqttNetLogger logger)
|
public MqttTcpServerAdapter(IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
_logger = logger.CreateScopedLogger(nameof(MqttTcpServerAdapter));
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||||
@@ -44,22 +43,12 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (options.TlsEndpointOptions?.IsEnabled == true)
|
if (options.TlsEndpointOptions?.IsEnabled == true)
|
||||||
{
|
{
|
||||||
if (options.TlsEndpointOptions.Certificate == null)
|
if (options.TlsEndpointOptions.CertificateProvider == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("TLS certificate is not set.");
|
throw new ArgumentException("TLS certificate is not set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
X509Certificate2 tlsCertificate;
|
var tlsCertificate = options.TlsEndpointOptions.CertificateProvider.GetCertificate();
|
||||||
if (string.IsNullOrEmpty(options.TlsEndpointOptions.CertificateCredentials?.Password))
|
|
||||||
{
|
|
||||||
// Use a different overload when no password is specified. Otherwise the constructor will fail.
|
|
||||||
tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate, options.TlsEndpointOptions.CertificateCredentials.Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tlsCertificate.HasPrivateKey)
|
if (!tlsCertificate.HasPrivateKey)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
|
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
|
||||||
@@ -68,23 +57,18 @@ namespace MQTTnet.Implementations
|
|||||||
RegisterListeners(options.TlsEndpointOptions, tlsCertificate, _cancellationTokenSource.Token);
|
RegisterListeners(options.TlsEndpointOptions, tlsCertificate, _cancellationTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync()
|
public Task StopAsync()
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
return Task.FromResult(0);
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (disposing)
|
Cleanup();
|
||||||
{
|
|
||||||
Cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cleanup()
|
void Cleanup()
|
||||||
@@ -105,11 +89,7 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
if (!options.BoundInterNetworkAddress.Equals(IPAddress.None))
|
if (!options.BoundInterNetworkAddress.Equals(IPAddress.None))
|
||||||
{
|
{
|
||||||
var listenerV4 = new MqttTcpServerListener(
|
var listenerV4 = new MqttTcpServerListener(AddressFamily.InterNetwork, options, tlsCertificate, _rootLogger)
|
||||||
AddressFamily.InterNetwork,
|
|
||||||
options,
|
|
||||||
tlsCertificate,
|
|
||||||
_logger)
|
|
||||||
{
|
{
|
||||||
ClientHandler = OnClientAcceptedAsync
|
ClientHandler = OnClientAcceptedAsync
|
||||||
};
|
};
|
||||||
@@ -122,11 +102,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (!options.BoundInterNetworkV6Address.Equals(IPAddress.None))
|
if (!options.BoundInterNetworkV6Address.Equals(IPAddress.None))
|
||||||
{
|
{
|
||||||
var listenerV6 = new MqttTcpServerListener(
|
var listenerV6 = new MqttTcpServerListener(AddressFamily.InterNetworkV6, options, tlsCertificate, _rootLogger)
|
||||||
AddressFamily.InterNetworkV6,
|
|
||||||
options,
|
|
||||||
tlsCertificate,
|
|
||||||
_logger)
|
|
||||||
{
|
{
|
||||||
ClientHandler = OnClientAcceptedAsync
|
ClientHandler = OnClientAcceptedAsync
|
||||||
};
|
};
|
||||||
@@ -138,7 +114,7 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OnClientAcceptedAsync(IMqttChannelAdapter channelAdapter)
|
Task OnClientAcceptedAsync(IMqttChannelAdapter channelAdapter)
|
||||||
{
|
{
|
||||||
var clientHandler = ClientHandler;
|
var clientHandler = ClientHandler;
|
||||||
if (clientHandler == null)
|
if (clientHandler == null)
|
||||||
|
|||||||
@@ -17,14 +17,15 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttTcpServerListener : IDisposable
|
public sealed class MqttTcpServerListener : IDisposable
|
||||||
{
|
{
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
|
readonly IMqttNetLogger _rootLogger;
|
||||||
readonly AddressFamily _addressFamily;
|
readonly AddressFamily _addressFamily;
|
||||||
readonly MqttServerTcpEndpointBaseOptions _options;
|
readonly MqttServerTcpEndpointBaseOptions _options;
|
||||||
readonly MqttServerTlsTcpEndpointOptions _tlsOptions;
|
readonly MqttServerTlsTcpEndpointOptions _tlsOptions;
|
||||||
readonly X509Certificate2 _tlsCertificate;
|
readonly X509Certificate2 _tlsCertificate;
|
||||||
|
|
||||||
private CrossPlatformSocket _socket;
|
CrossPlatformSocket _socket;
|
||||||
private IPEndPoint _localEndPoint;
|
IPEndPoint _localEndPoint;
|
||||||
|
|
||||||
public MqttTcpServerListener(
|
public MqttTcpServerListener(
|
||||||
AddressFamily addressFamily,
|
AddressFamily addressFamily,
|
||||||
@@ -35,7 +36,8 @@ namespace MQTTnet.Implementations
|
|||||||
_addressFamily = addressFamily;
|
_addressFamily = addressFamily;
|
||||||
_options = options;
|
_options = options;
|
||||||
_tlsCertificate = tlsCertificate;
|
_tlsCertificate = tlsCertificate;
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerListener));
|
_rootLogger = logger;
|
||||||
|
_logger = logger.CreateScopedLogger(nameof(MqttTcpServerListener));
|
||||||
|
|
||||||
if (_options is MqttServerTlsTcpEndpointOptions tlsOptions)
|
if (_options is MqttServerTlsTcpEndpointOptions tlsOptions)
|
||||||
{
|
{
|
||||||
@@ -178,7 +180,7 @@ namespace MQTTnet.Implementations
|
|||||||
var clientHandler = ClientHandler;
|
var clientHandler = ClientHandler;
|
||||||
if (clientHandler != null)
|
if (clientHandler != null)
|
||||||
{
|
{
|
||||||
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream, remoteEndPoint, clientCertificate), new MqttPacketFormatterAdapter(), _logger))
|
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream, remoteEndPoint, clientCertificate), new MqttPacketFormatterAdapter(new MqttPacketWriter()), _rootLogger))
|
||||||
{
|
{
|
||||||
await clientHandler(clientAdapter).ConfigureAwait(false);
|
await clientHandler(clientAdapter).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
using System;
|
using MQTTnet.Channel;
|
||||||
|
using MQTTnet.Client.Options;
|
||||||
|
using MQTTnet.Internal;
|
||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Channel;
|
|
||||||
using MQTTnet.Client.Options;
|
|
||||||
using MQTTnet.Internal;
|
|
||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttWebSocketChannel : Disposable, IMqttChannel
|
public sealed class MqttWebSocketChannel : IMqttChannel
|
||||||
{
|
{
|
||||||
private readonly MqttClientWebSocketOptions _options;
|
readonly MqttClientWebSocketOptions _options;
|
||||||
|
|
||||||
private SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
|
AsyncLock _sendLock = new AsyncLock();
|
||||||
private WebSocket _webSocket;
|
WebSocket _webSocket;
|
||||||
|
|
||||||
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public bool IsSecureConnection { get; private set; }
|
public bool IsSecureConnection { get; private set; }
|
||||||
|
|
||||||
public X509Certificate2 ClientCertificate { get; private set; }
|
public X509Certificate2 ClientCertificate { get; }
|
||||||
|
|
||||||
public async Task ConnectAsync(CancellationToken cancellationToken)
|
public async Task ConnectAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -53,6 +53,67 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
|
|
||||||
var clientWebSocket = new ClientWebSocket();
|
var clientWebSocket = new ClientWebSocket();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetupClientWebSocket(clientWebSocket);
|
||||||
|
|
||||||
|
await clientWebSocket.ConnectAsync(new Uri(uri), cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Prevent a memory leak when always creating new instance which will fail while connecting.
|
||||||
|
clientWebSocket.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
_webSocket = clientWebSocket;
|
||||||
|
IsSecureConnection = uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DisconnectAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_webSocket == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
|
||||||
|
{
|
||||||
|
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken).ConfigureAwait(false);
|
||||||
|
return response.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// The lock is required because the client will throw an exception if _SendAsync_ is
|
||||||
|
// called from multiple threads at the same time. But this issue only happens with several
|
||||||
|
// framework versions.
|
||||||
|
if (_sendLock == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (await _sendLock.WaitAsync(cancellationToken).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
await _webSocket.SendAsync(new ArraySegment<byte>(buffer, offset, count), WebSocketMessageType.Binary, true, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupClientWebSocket(ClientWebSocket clientWebSocket)
|
||||||
|
{
|
||||||
|
|
||||||
if (_options.ProxyOptions != null)
|
if (_options.ProxyOptions != null)
|
||||||
{
|
{
|
||||||
@@ -90,68 +151,37 @@ namespace MQTTnet.Implementations
|
|||||||
#else
|
#else
|
||||||
clientWebSocket.Options.ClientCertificates.Add(certificate);
|
clientWebSocket.Options.ClientCertificates.Add(certificate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await clientWebSocket.ConnectAsync(new Uri(uri), cancellationToken).ConfigureAwait(false);
|
var certificateValidationHandler = _options.TlsOptions?.CertificateValidationHandler;
|
||||||
_webSocket = clientWebSocket;
|
#if NETSTANDARD2_1
|
||||||
|
if (certificateValidationHandler != null)
|
||||||
|
{
|
||||||
|
clientWebSocket.Options.RemoteCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, sslPolicyErrors) =>
|
||||||
|
{
|
||||||
|
// TODO: Find a way to add client options to same callback. Problem is that they have a different type.
|
||||||
|
var context = new MqttClientCertificateValidationCallbackContext
|
||||||
|
{
|
||||||
|
Certificate = certificate,
|
||||||
|
Chain = chain,
|
||||||
|
SslPolicyErrors = sslPolicyErrors,
|
||||||
|
ClientOptions = _options
|
||||||
|
};
|
||||||
|
|
||||||
IsSecureConnection = uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase);
|
return certificateValidationHandler(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (certificateValidationHandler != null)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("The remote certificate validation callback for Web Sockets is only supported for netstandard 2.1+");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DisconnectAsync(CancellationToken cancellationToken)
|
void Cleanup()
|
||||||
{
|
|
||||||
if (_webSocket == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken).ConfigureAwait(false);
|
|
||||||
return response.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// The lock is required because the client will throw an exception if _SendAsync_ is
|
|
||||||
// called from multiple threads at the same time. But this issue only happens with several
|
|
||||||
// framework versions.
|
|
||||||
if (_sendLock == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _sendLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer, offset, count), WebSocketMessageType.Binary, true, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_sendLock?.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
Cleanup();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Cleanup()
|
|
||||||
{
|
{
|
||||||
_sendLock?.Dispose();
|
_sendLock?.Dispose();
|
||||||
_sendLock = null;
|
_sendLock = null;
|
||||||
@@ -169,7 +199,7 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWebProxy CreateProxy()
|
IWebProxy CreateProxy()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_options.ProxyOptions?.Address))
|
if (string.IsNullOrEmpty(_options.ProxyOptions?.Address))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Internal
|
|
||||||
{
|
|
||||||
public static class ArraySegmentExtensions
|
|
||||||
{
|
|
||||||
public static byte[] ToArray(this ArraySegment<byte> source)
|
|
||||||
{
|
|
||||||
if (source.Array == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buffer = new byte[source.Count];
|
|
||||||
if (buffer.Length > 0)
|
|
||||||
{
|
|
||||||
Array.Copy(source.Array, source.Offset, buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,10 +5,10 @@ using System.Threading.Tasks;
|
|||||||
namespace MQTTnet.Internal
|
namespace MQTTnet.Internal
|
||||||
{
|
{
|
||||||
// From Stephen Toub (https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6-asynclock/)
|
// From Stephen Toub (https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6-asynclock/)
|
||||||
public class AsyncLock : IDisposable
|
public sealed class AsyncLock : IDisposable
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly Task<IDisposable> _releaser;
|
readonly Task<IDisposable> _releaser;
|
||||||
|
|
||||||
public AsyncLock()
|
public AsyncLock()
|
||||||
{
|
{
|
||||||
@@ -39,9 +39,9 @@ namespace MQTTnet.Internal
|
|||||||
_semaphore?.Dispose();
|
_semaphore?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Releaser : IDisposable
|
class Releaser : IDisposable
|
||||||
{
|
{
|
||||||
private readonly AsyncLock _toRelease;
|
readonly AsyncLock _toRelease;
|
||||||
|
|
||||||
internal Releaser(AsyncLock toRelease)
|
internal Releaser(AsyncLock toRelease)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ namespace MQTTnet.Internal
|
|||||||
{
|
{
|
||||||
public sealed class AsyncQueue<TItem> : IDisposable
|
public sealed class AsyncQueue<TItem> : IDisposable
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0);
|
SemaphoreSlim _semaphore = new SemaphoreSlim(0);
|
||||||
|
ConcurrentQueue<TItem> _queue = new ConcurrentQueue<TItem>();
|
||||||
private ConcurrentQueue<TItem> _queue = new ConcurrentQueue<TItem>();
|
|
||||||
|
|
||||||
public int Count => _queue.Count;
|
public int Count => _queue.Count;
|
||||||
|
|
||||||
public void Enqueue(TItem item)
|
public void Enqueue(TItem item)
|
||||||
{
|
{
|
||||||
_queue.Enqueue(item);
|
_queue.Enqueue(item);
|
||||||
_semaphore.Release();
|
_semaphore?.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AsyncQueueDequeueResult<TItem>> TryDequeueAsync(CancellationToken cancellationToken)
|
public async Task<AsyncQueueDequeueResult<TItem>> TryDequeueAsync(CancellationToken cancellationToken)
|
||||||
@@ -25,12 +24,17 @@ namespace MQTTnet.Internal
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (_semaphore == null)
|
||||||
|
{
|
||||||
|
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||||
|
}
|
||||||
|
|
||||||
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
return new AsyncQueueDequeueResult<TItem>(false, default(TItem));
|
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queue.TryDequeue(out var item))
|
if (_queue.TryDequeue(out var item))
|
||||||
@@ -39,7 +43,7 @@ namespace MQTTnet.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AsyncQueueDequeueResult<TItem>(false, default(TItem));
|
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncQueueDequeueResult<TItem> TryDequeue()
|
public AsyncQueueDequeueResult<TItem> TryDequeue()
|
||||||
@@ -49,7 +53,7 @@ namespace MQTTnet.Internal
|
|||||||
return new AsyncQueueDequeueResult<TItem>(true, item);
|
return new AsyncQueueDequeueResult<TItem>(true, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AsyncQueueDequeueResult<TItem>(false, default(TItem));
|
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
@@ -60,6 +64,7 @@ namespace MQTTnet.Internal
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_semaphore?.Dispose();
|
_semaphore?.Dispose();
|
||||||
|
_semaphore = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MQTTnet.Internal
|
namespace MQTTnet.Internal
|
||||||
{
|
{
|
||||||
public class BlockingQueue<TItem> : Disposable
|
public sealed class BlockingQueue<TItem> : IDisposable
|
||||||
{
|
{
|
||||||
private readonly object _syncRoot = new object();
|
readonly object _syncRoot = new object();
|
||||||
private readonly LinkedList<TItem> _items = new LinkedList<TItem>();
|
readonly LinkedList<TItem> _items = new LinkedList<TItem>();
|
||||||
private readonly ManualResetEventSlim _gate = new ManualResetEventSlim(false);
|
|
||||||
|
ManualResetEventSlim _gate = new ManualResetEventSlim(false);
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
@@ -28,13 +29,13 @@ namespace MQTTnet.Internal
|
|||||||
lock (_syncRoot)
|
lock (_syncRoot)
|
||||||
{
|
{
|
||||||
_items.AddLast(item);
|
_items.AddLast(item);
|
||||||
_gate.Set();
|
_gate?.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TItem Dequeue(CancellationToken cancellationToken = default(CancellationToken))
|
public TItem Dequeue(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
while (true)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
lock (_syncRoot)
|
lock (_syncRoot)
|
||||||
{
|
{
|
||||||
@@ -48,17 +49,19 @@ namespace MQTTnet.Internal
|
|||||||
|
|
||||||
if (_items.Count == 0)
|
if (_items.Count == 0)
|
||||||
{
|
{
|
||||||
_gate.Reset();
|
_gate?.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_gate.Wait(cancellationToken);
|
_gate?.Wait(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new OperationCanceledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TItem PeekAndWait(CancellationToken cancellationToken = default(CancellationToken))
|
public TItem PeekAndWait(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
while (true)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
lock (_syncRoot)
|
lock (_syncRoot)
|
||||||
{
|
{
|
||||||
@@ -69,12 +72,14 @@ namespace MQTTnet.Internal
|
|||||||
|
|
||||||
if (_items.Count == 0)
|
if (_items.Count == 0)
|
||||||
{
|
{
|
||||||
_gate.Reset();
|
_gate?.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_gate.Wait(cancellationToken);
|
_gate?.Wait(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new OperationCanceledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveFirst(Predicate<TItem> match)
|
public void RemoveFirst(Predicate<TItem> match)
|
||||||
@@ -109,13 +114,10 @@ namespace MQTTnet.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (disposing)
|
_gate?.Dispose();
|
||||||
{
|
_gate = null;
|
||||||
_gate.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace MQTTnet.Internal
|
|||||||
{
|
{
|
||||||
public static class TaskExtensions
|
public static class TaskExtensions
|
||||||
{
|
{
|
||||||
public static void Forget(this Task task, IMqttNetLogger logger)
|
public static void Forget(this Task task, IMqttNetScopedLogger logger)
|
||||||
{
|
{
|
||||||
task?.ContinueWith(t =>
|
task?.ContinueWith(t =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace MQTTnet.LowLevelClient
|
|||||||
{
|
{
|
||||||
public sealed class LowLevelMqttClient : ILowLevelMqttClient
|
public sealed class LowLevelMqttClient : ILowLevelMqttClient
|
||||||
{
|
{
|
||||||
readonly IMqttNetLogger _logger;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
readonly IMqttClientAdapterFactory _clientAdapterFactory;
|
readonly IMqttClientAdapterFactory _clientAdapterFactory;
|
||||||
|
|
||||||
IMqttChannelAdapter _adapter;
|
IMqttChannelAdapter _adapter;
|
||||||
@@ -22,7 +22,7 @@ namespace MQTTnet.LowLevelClient
|
|||||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_clientAdapterFactory = clientAdapterFactory;
|
_clientAdapterFactory = clientAdapterFactory;
|
||||||
_logger = logger.CreateChildLogger(nameof(LowLevelMqttClient));
|
_logger = logger.CreateScopedLogger(nameof(LowLevelMqttClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsConnected => _adapter != null;
|
bool IsConnected => _adapter != null;
|
||||||
@@ -36,7 +36,7 @@ namespace MQTTnet.LowLevelClient
|
|||||||
throw new InvalidOperationException("Low level MQTT client is already connected. Disconnect first before connecting again.");
|
throw new InvalidOperationException("Low level MQTT client is already connected. Disconnect first before connecting again.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newAdapter = _clientAdapterFactory.CreateClientAdapter(options, _logger);
|
var newAdapter = _clientAdapterFactory.CreateClientAdapter(options);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -48,7 +48,7 @@ namespace MQTTnet.LowLevelClient
|
|||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
_adapter.Dispose();
|
_adapter?.Dispose();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<AssemblyName>MQTTnet</AssemblyName>
|
<AssemblyName>MQTTnet</AssemblyName>
|
||||||
@@ -14,14 +14,17 @@
|
|||||||
<PackageId />
|
<PackageId />
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<DelaySign>false</DelaySign>
|
<DelaySign>false</DelaySign>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)'=='uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)'=='uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10586.212</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
<DefineConstants>$(DefineConstants);WINDOWS_UWP</DefineConstants>
|
<DefineConstants>$(DefineConstants);WINDOWS_UWP</DefineConstants>
|
||||||
@@ -41,6 +44,10 @@
|
|||||||
<DefineConstants>RELEASE;NETSTANDARD1_3</DefineConstants>
|
<DefineConstants>RELEASE;NETSTANDARD1_3</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
|
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
|
||||||
<PackageReference Include="System.Net.Security" Version="4.3.2" />
|
<PackageReference Include="System.Net.Security" Version="4.3.2" />
|
||||||
<PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
|
<PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
|
||||||
@@ -54,7 +61,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)'=='uap10.0'">
|
<ItemGroup Condition="'$(TargetFramework)'=='uap10.0'">
|
||||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.8" />
|
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)'=='net452'">
|
<ItemGroup Condition="'$(TargetFramework)'=='net452'">
|
||||||
@@ -62,9 +69,5 @@
|
|||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)'=='net461'">
|
<ItemGroup Condition="'$(TargetFramework)'=='net461'">
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.10" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -6,12 +6,13 @@ using MQTTnet.LowLevelClient;
|
|||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
{
|
{
|
||||||
public sealed class MqttFactory : IMqttFactory
|
public sealed class MqttFactory : IMqttFactory
|
||||||
{
|
{
|
||||||
IMqttClientAdapterFactory _clientAdapterFactory = new MqttClientAdapterFactory();
|
IMqttClientAdapterFactory _clientAdapterFactory;
|
||||||
|
|
||||||
public MqttFactory() : this(new MqttNetLogger())
|
public MqttFactory() : this(new MqttNetLogger())
|
||||||
{
|
{
|
||||||
@@ -20,10 +21,18 @@ namespace MQTTnet
|
|||||||
public MqttFactory(IMqttNetLogger logger)
|
public MqttFactory(IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
DefaultLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
DefaultLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
_clientAdapterFactory = new MqttClientAdapterFactory(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMqttNetLogger DefaultLogger { get; }
|
public IMqttNetLogger DefaultLogger { get; }
|
||||||
|
|
||||||
|
public IList<Func<IMqttFactory, IMqttServerAdapter>> DefaultServerAdapters { get; } = new List<Func<IMqttFactory, IMqttServerAdapter>>
|
||||||
|
{
|
||||||
|
factory => new MqttTcpServerAdapter(factory.DefaultLogger)
|
||||||
|
};
|
||||||
|
|
||||||
|
public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
|
||||||
|
|
||||||
public IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory)
|
public IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory)
|
||||||
{
|
{
|
||||||
_clientAdapterFactory = clientAdapterFactory ?? throw new ArgumentNullException(nameof(clientAdapterFactory));
|
_clientAdapterFactory = clientAdapterFactory ?? throw new ArgumentNullException(nameof(clientAdapterFactory));
|
||||||
@@ -49,10 +58,10 @@ namespace MQTTnet
|
|||||||
return new LowLevelMqttClient(_clientAdapterFactory, DefaultLogger);
|
return new LowLevelMqttClient(_clientAdapterFactory, DefaultLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory clientAdapterFactoryy)
|
public ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory clientAdapterFactory)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
if (clientAdapterFactoryy == null) throw new ArgumentNullException(nameof(clientAdapterFactoryy));
|
if (clientAdapterFactory == null) throw new ArgumentNullException(nameof(clientAdapterFactory));
|
||||||
|
|
||||||
return new LowLevelMqttClient(_clientAdapterFactory, logger);
|
return new LowLevelMqttClient(_clientAdapterFactory, logger);
|
||||||
}
|
}
|
||||||
@@ -93,7 +102,8 @@ namespace MQTTnet
|
|||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
return CreateMqttServer(new List<IMqttServerAdapter> { new MqttTcpServerAdapter(logger) }, logger);
|
var serverAdapters = DefaultServerAdapters.Select(a => a.Invoke(this));
|
||||||
|
return CreateMqttServer(serverAdapters, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters, IMqttNetLogger logger)
|
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters, IMqttNetLogger logger)
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
{
|
{
|
||||||
// TODO: Consider renaming to "MqttTopicFilter"
|
[Obsolete("Use MqttTopicFilter instead. It is just a renamed version to align with general namings in this lib.")]
|
||||||
public class TopicFilter
|
public class TopicFilter : MqttTopicFilter
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MqttTopicFilter
|
||||||
{
|
{
|
||||||
public string Topic { get; set; }
|
public string Topic { get; set; }
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user