Compare commits

...
482 Commits
Author SHA1 Message Date
HansM bb52159e49 Added reference to SparkplugNet. 2021-01-31 17:35:39 +01:00
HansM 109acccd19 Update MQTTnet.nuspec
Added code documentation hint.
2021-01-31 11:34:27 +01:00
HansM deb2c3dec6 Merge pull request #1055 from chkr1011/add-code-doc
Added client documentation.
2021-01-31 11:33:13 +01:00
HansM 63ca6086d5 Added missing changelog entry.
Missing changelog change from https://github.com/chkr1011/MQTTnet/pull/1076.
2021-01-30 15:39:04 +01:00
Christian 3f92f2ca2b Remove UWP test app because it gets replaced by MQTTnet.App in a separate repository. 2021-01-30 13:24:24 +01:00
Christian a13874d8a5 Add missing overloads for client disconnect.
Add timeout for disconnect in managed client.
2021-01-30 13:17:03 +01:00
Christian c91a1f8572 Update solution settings. 2021-01-30 13:12:41 +01:00
Christian b103718bd9 Add Unit Tests. 2021-01-29 23:17:16 +01:00
Christian b88924bce5 Fixed wrong buffer size calculation. 2021-01-29 23:10:40 +01:00
Christian f3f1d81b52 Update docs. 2021-01-29 22:44:18 +01:00
Christian 031b60878d Merge pull request #1071 from muneebmajeed/master
Allow to respond with a reason code in PUBACK/PUBREC
2021-01-29 22:27:09 +01:00
HansM 1fbf20a569 Merge pull request #1076 from dagophil/bug/topic-filter-comparer-edge-case
The topic filter comparer now checks for e.g. "foo/" matching "foo/#".
2021-01-29 18:24:37 +01:00
Philip Schill b1bf7698aa The topic filter comparer now checks for e.g. "foo/" matching "foo/#". 2021-01-29 17:37:47 +01:00
Muneeb Majeed f8eaf02516 Allow to respond with a reason code in PUBACK/PUBREC 2021-01-26 17:18:52 -05:00
Christian df45540d6b Update docs. 2021-01-25 22:28:01 +01:00
Christian 2abcf6d8bc Update docs. 2021-01-25 22:27:45 +01:00
Christian c1001db450 Add packet inspector API. 2021-01-24 20:58:15 +01:00
SeppPenner 3d8d06f9b3 Hopefully completely reset the IManagedMqttClient file. 2021-01-15 20:43:57 +01:00
SeppPenner d804b805c1 Smaller changes on the comments. 2021-01-15 20:41:47 +01:00
SeppPenner bba04e2b5d Updated all code comments, should be ok now. 2021-01-15 20:34:33 +01:00
SeppPenner 5eab337e13 Removed not needed comments on client side (Server side is still missing). 2021-01-15 19:41:45 +01:00
Christian e1d39a3fef Fix build of MQTTnet Server. 2021-01-10 12:55:38 +01:00
Christian 3f5d627e9e Fix issues in QoS 2 handling. 2021-01-07 23:22:45 +01:00
SeppPenner 2047f44554 Added client documentation. 2021-01-03 21:46:53 +01:00
Christian 75845d6416 Fix cancellation issues when connecting. 2021-01-01 15:56:38 +01:00
Christian 74e952bb03 Merge remote-tracking branch 'origin/master' 2020-12-23 21:38:14 +01:00
Christian 3773048bc5 Update docs. 2020-12-23 21:38:08 +01:00
Christian f9aec0c067 Merge pull request #1048 from tobiasfrick/bugfix/cleandisconnect
Only set _cleanDisconnectInitiated if no disconnect is pending
2020-12-23 17:21:04 +01:00
Tobias Frick 91c8a15f65 Only set _cleanDisconnectInitiated if no disconnect is pending 2020-12-21 13:26:59 +01:00
Christian b95d6b08bc Update docs. 2020-12-19 13:45:13 +01:00
Christian a44ea74739 Merge pull request #1027 from StefanOssendorf/feature/Add-net5-tfm
.Net5.0 TFMs added
2020-12-19 13:02:11 +01:00
JanEggers 02e65bca67 fixed .net 5 build 2020-12-16 14:45:15 +01:00
Stefan Ossendorf 37b783908a .Net5.0 TFMs added
.Net5.0 TFMs added and related nuget packages updated.
2020-12-16 14:45:15 +01:00
Christian 72211ae85a Improve packet writer performance. 2020-12-14 21:17:22 +01:00
Christian 1f78a92c4d Remove timeout from send method. 2020-12-14 21:17:11 +01:00
Christian f92cfcd293 Add new multi threaded application message handler for server. 2020-12-13 11:36:31 +01:00
Christian 86256d1b10 Update README.md 2020-12-09 22:42:07 +01:00
Christian c3e65390ab Improve performance test. 2020-12-08 21:08:05 +01:00
Christian b0699003e2 Refactor code. 2020-12-08 21:07:58 +01:00
Christian 1214b15260 Update docs. 2020-11-29 11:43:29 +01:00
Christian 322067466b Fix wrong usage of client session items for undelivered messages. 2020-11-25 21:31:26 +01:00
Christian ef2ed1c897 Remove _WithoutAutoReconnect_ from managed client. 2020-11-25 21:18:36 +01:00
Christian 9fddfb3e77 Add UnitTests 2020-11-25 21:08:01 +01:00
Christian ec015e7620 Refactor naming for background tasks. 2020-11-25 21:07:50 +01:00
Christian 7738c5faa1 Refactor platform detection for unsupported features. 2020-11-21 15:43:32 +01:00
Christian 01bb09ff4b Remove obsolete files. 2020-11-17 22:23:08 +01:00
Christian e1494c1004 Update nuget packages. 2020-11-17 22:06:20 +01:00
Christian 1e2231c461 Improve Unit Tests. 2020-11-16 21:03:18 +01:00
Christian de0f5dc1f0 Update docs. 2020-11-16 20:57:31 +01:00
Christian a93f44217b Align different formats of log messages. 2020-11-16 20:47:44 +01:00
Christian f9c3014e52 Fix Unit Tests. 2020-11-15 14:34:59 +01:00
Christian 483c2d8b10 Fix Unit Tests. 2020-11-15 14:21:11 +01:00
Christian 02ab0e4903 Fix Unit Tests. 2020-11-15 14:17:18 +01:00
Christian 0bc25571e0 Fix Unit Tests 2020-11-15 12:46:10 +01:00
Christian Kratky 5b29b8cfd8 Fix Unit Tests. 2020-11-14 16:06:43 +01:00
Christian Kratky dd9dc054e8 Merge remote-tracking branch 'origin/master' 2020-11-14 15:31:06 +01:00
Christian Kratky b7c178b85c Fix Unit Tests. 2020-11-14 15:30:57 +01:00
Christian f8e29f8dc0 Update appveyor.yml 2020-11-14 15:24:49 +01:00
Christian 3d68951f68 Update MQTTnet.nuspec 2020-11-14 11:40:58 +01:00
Christian 7eb6d2d1e3 Merge pull request #1019 from chkr1011/feature/Single_Connection_Monitoring_Task
Feature/single connection monitoring task
2020-11-14 10:36:18 +01:00
Christian Kratky 0446635ed6 Add comments. 2020-11-14 10:35:08 +01:00
Christian Kratky 4514348821 Fix Unit Tests. 2020-11-13 23:24:45 +01:00
Christian Kratky 7b32abe625 Fix Unit Tests. 2020-11-13 23:11:01 +01:00
Christian Kratky 0febc12b3d Merge branch 'master' into feature/Single_Connection_Monitoring_Task 2020-11-13 20:36:51 +01:00
Christian Kratky d0a848c8b4 Improve performance. 2020-11-13 20:33:47 +01:00
Christian fe69f5a633 Merge pull request #1029 from mmuecke/patch-1
Added reference to Rx Wrapper for Managed Client
2020-11-12 11:26:22 +01:00
mmuecke ca95754fc3 Added reference to Rx Wrapper for Managed Client 2020-11-12 00:24:01 +00:00
Christian Kratky cc405c3e90 Update settings. 2020-11-11 21:12:37 +01:00
Christian Kratky 315206f05e Update settings. 2020-11-11 21:12:15 +01:00
Christian Kratky f252374437 Extend support for topic alias. 2020-11-11 21:12:04 +01:00
Christian Kratky 38d3531db6 Refactor code. 2020-11-11 21:11:49 +01:00
Christian Kratky da5a172504 Refactor code. 2020-11-09 21:30:36 +01:00
Christian Kratky f894622884 Merge branch 'master' into feature/Single_Connection_Monitoring_Task 2020-11-09 21:29:38 +01:00
Christian 88b0af9b21 Merge pull request #1023 from StefanOssendorf/fix/compile-error
Fix: Compile error, cancellation token removed since the method does not support it
2020-11-09 21:11:48 +01:00
Christian Kratky e1bf9de347 Add support for topic alias. 2020-11-09 21:10:05 +01:00
Christian Kratky 6c15693456 Add support for TopicAlias in application message builder. 2020-11-09 17:22:32 +01:00
Stefan Ossendorf 4608930a37 Cancellation token removed since the method does not support it
Cancellation token removed because the SendAsync() method does not support it.
2020-11-08 14:31:01 +01:00
Christian Kratky eaf1195f95 Cleanup Unit Tests. 2020-11-06 21:00:25 +01:00
Christian Kratky a35dee9352 Update docs. 2020-11-06 20:03:33 +01:00
Christian 6cef746ed9 Merge pull request #1021 from nayato/max-qos
Add support for Maximum QoS property on CONNACK
2020-11-06 20:00:09 +01:00
Max Gortman 344cf674e6 PR fixes 2020-11-05 16:55:50 -08:00
Christian Kratky 26af205ab0 Update docs. 2020-11-04 21:29:26 +01:00
Christian Kratky 06c9d27c87 Fixed bug in PubRel packet generation (MQTTv5 only). 2020-11-04 21:28:40 +01:00
Max Gortman 14224e4180 Add support for Maximum QoS property on CONNACK 2020-11-03 12:19:38 -08:00
Christian Kratky b954c9512e Fix swagger configuration. 2020-11-02 22:03:47 +01:00
Christian Kratky fb2be79673 Remove not used timeout for receiving. 2020-11-02 21:45:23 +01:00
Christian Kratky 44b7133a1c Improve keep alive tests. 2020-11-02 21:17:31 +01:00
Christian Kratky 2f0513212e Merge branch 'master' into feature/Single_Connection_Monitoring_Task 2020-11-01 12:35:59 +01:00
Christian Kratky 1a9460776b Update docs. 2020-11-01 12:03:19 +01:00
Christian Kratky 2716db04e3 Move the RPC topic validation to the topic generation strategy. 2020-11-01 12:00:12 +01:00
Christian Kratky 3e4f4a59a8 Improve Unit Tests. 2020-11-01 11:58:43 +01:00
Christian Kratky 24f0ea01f5 Improve session takeover and keep alive handling. 2020-10-31 20:59:41 +01:00
Christian Kratky 1625aadae9 Improve disconnect reason transfer to client (especially for session take over). 2020-10-31 11:43:14 +01:00
Christian Kratky e800901b4c Merge branch 'master' into feature/Single_Connection_Monitoring_Task 2020-10-31 11:33:54 +01:00
Christian Kratky 34ae54d542 Improve Unit Tests. 2020-10-31 11:33:44 +01:00
Christian Kratky 838d50c1d3 Remove file which is not part of the solution. 2020-10-31 11:27:46 +01:00
Christian Kratky 558d281a33 Refactor TLS 1.3 support. 2020-10-31 11:23:14 +01:00
Christian Kratky f8c956a9e2 Merge remote-tracking branch 'origin/master' 2020-10-31 11:14:07 +01:00
Christian 9a6823597e Merge pull request #1020 from Dvergatal/master
Added support for Tls1.3
2020-10-31 11:13:50 +01:00
Christian Kratky 42c1155bee Fix nullref exception in connection handler. 2020-10-30 23:51:11 +01:00
Christian Kratky f773257c86 Improve exception handling in AsyncQueue. 2020-10-30 20:43:39 +01:00
Christian Kratky 4e9df98817 Improve test environment. 2020-10-30 20:43:02 +01:00
Christian Kratky 3208045baa Extend application message builder. 2020-10-30 20:42:52 +01:00
Piotr Łobacz 7274f4390c added support for Tls1.3 protocol 2020-10-30 12:45:57 +01:00
Dvergatal 11c8abfd54 Merge pull request #1 from chkr1011/master
Merging with mainline.
2020-10-30 11:16:09 +01:00
Christian Kratky f606a5996b Merge remote-tracking branch 'origin/master' 2020-10-30 00:26:40 +01:00
Christian Kratky 58ad599783 Improve disconnect code of client. 2020-10-30 00:23:45 +01:00
Christian Kratky ccd102a59f Refactor code. 2020-10-30 00:21:08 +01:00
Christian Kratky 05101f0e0e Improve exception handling of AsyncLock. 2020-10-30 00:19:57 +01:00
Christian Kratky f9630ef347 Improve internal session/connection management and connection takeover. 2020-10-30 00:19:30 +01:00
Christian Kratky c5b7735a2c Improve cancellation token handling for client connections (Server). 2020-10-29 20:02:03 +01:00
HansM 12fca2f05a Merge pull request #1015 from Jay424/patch-1
Fixed evaluation of IgnoreCertificateRevocationErrors to correctly se…
2020-10-29 11:34:23 +01:00
Christian Kratky b7fb0c1002 Refactor package object model. 2020-10-28 23:11:12 +01:00
Jay424 3ea281ff84 Updated release notes 2020-10-28 17:58:48 +01:00
Jay424 c778cd7a0f Fixed evaluation of IgnoreCertificateRevocationErrors to correctly set SslClientAuthenticationOptions.CertificateRevocationCheckMode
The if was just flipped.
2020-10-28 17:14:09 +01:00
Christian Kratky adce5662eb Prepare docs for next release. 2020-10-24 12:22:03 +02:00
Christian Kratky a26b641284 Fix broken connection takeover. 2020-10-15 01:01:35 +02:00
Christian Kratky 7be3685850 Merge remote-tracking branch 'origin/master' 2020-10-14 23:10:40 +02:00
Christian Kratky 1a6be47144 Update docs. 2020-10-14 23:10:13 +02:00
Christian 5d73de2a86 Merge pull request #1004 from JanEggers/fix#990
improved behavior when multiple connections fight over a session
2020-10-14 21:18:36 +02:00
JanEggers 2eaebe0e6a removed todo 2020-10-13 15:59:39 +02:00
JanEggers d7b552fce2 renaming and added cast 2020-10-13 15:57:21 +02:00
Christian bea6d75251 Merge pull request #993 from chkr1011/client-disconnected-handler
Tried to add a MqttServerOptions fluent method for the client disconn…
2020-10-12 20:38:15 +02:00
JanEggers f7db00c08e improved behavior when multiple connections fight over a session 2020-10-11 16:41:13 +02:00
Christian Kratky f259bbcc9b ManagedClient: Expose internal client. 2020-10-07 19:38:42 +02:00
SeppPenner 252772007b Changed MqttServerClientDisconnectedHandlerDelegate back again. 2020-09-27 17:43:06 +02:00
SeppPenner 21a9974e5d Tried to add a MqttServerOptions fluent method for the client disconnected handler. 2020-09-21 18:23:11 +02:00
Christian Kratky d63143bdc9 ManagedClient: Add new option for disabling auto reconnect. 2020-09-14 23:49:27 +02:00
Christian Kratky aad9eac361 Refactor AWS integration. 2020-09-14 22:01:07 +02:00
Christian Kratky e8a683b936 Merge remote-tracking branch 'origin/master' 2020-09-14 21:47:38 +02:00
Christian Kratky e475e36ce7 Update docs. 2020-09-14 21:47:36 +02:00
Christian 611c230da2 Merge pull request #981 from henning-krause/master
Added ApplicationProtocols support to the TLS options to support AWS MQTT on port 443
2020-09-14 21:46:18 +02:00
Krause, Henning 18839de083 Removed -prelease switch from build 2020-09-14 19:14:39 +02:00
Krause, Henning 194664bc9c Reverted bogus change 2020-09-14 19:13:49 +02:00
Krause, Henning 10a33fd153 Removed -prelease switch from build 2020-09-14 19:12:30 +02:00
Christian Kratky 868aa7d89a Merge remote-tracking branch 'origin/master' 2020-09-14 10:02:40 +02:00
Christian Kratky 1f8792cf87 Update docs. 2020-09-14 09:59:19 +02:00
Christian 7bb99c8b37 Merge pull request #979 from msallin/bugfix/978/ClientMessageQueueInterceptor
Bugfix/978/client message queue interceptor
2020-09-14 09:48:13 +02:00
Marc Sallin 7f5504b01b Fix wrong QoS when using MqttClientMessageQueueInterceptor #978 2020-09-04 09:53:34 +02:00
Marc Sallin fd789417e7 Extend MqttClientMessageQueueInterceptorContext to expose SubscriptionQualityOfServiceLevel 2020-09-04 09:53:34 +02:00
Marc Sallin f1f9924bce Expose WithClientMessageQueueInterceptor 2020-09-04 09:53:34 +02:00
Marc Sallin b0c603082b Rename "QualityOfServiceLevel" to SubscriptionQualityOfServiceLevel where appropriated to make the difference between the two different QoS fields more clear 2020-09-04 09:53:34 +02:00
Krause, Henning f3f10e9f65 Added missing nuget instructions for the build 2020-09-01 19:44:52 +02:00
Krause, Henning beb228cc05 Fixed issues from code review 2020-08-29 13:51:16 +02:00
Krause, Henning 7a7f0640ba Reverted solution file 2020-08-28 19:12:30 +02:00
Krause, Henning 55d009ce6b Reverted solution file 2020-08-28 19:11:37 +02:00
Krause, Henning e23ac4f703 Removed test program 2020-08-28 19:08:45 +02:00
Krause, Henning fc367ddb64 Added support to set TLS Application Protocols 2020-08-28 19:07:31 +02:00
Christian Kratky cf217034fa Fix broken ClientWasConnected detection. 2020-08-22 20:44:24 +02:00
Christian Kratky 6b6627f823 Fix null ref exception in low level client. 2020-08-05 20:49:11 +02:00
Christian Kratky 4f51a238b3 Fix UnitTests 2020-07-26 20:07:52 +02:00
Christian Kratky 733c587e45 Fix Unit Tests. 2020-07-26 12:01:33 +02:00
Christian Kratky 3260920828 Fix UnitTests 2020-07-25 23:47:29 +02:00
Christian Kratky 4e6aeb91a4 Fix server adapter memory leak and UnitTests 2020-07-25 23:34:30 +02:00
Christian Kratky 5056843611 Fix UnitTests. 2020-07-25 14:21:09 +02:00
Christian Kratky a65c015a58 Refactor exception message. 2020-07-25 13:43:26 +02:00
Christian e63f26789f Merge pull request #959 from Mephistofeles/ManagedMqttClientExtensions
Modified ManagedMqttClientExtensions to work on less specific interfaces
2020-07-25 13:32:31 +02:00
Christian 9a598892a7 Merge pull request #954 from JanEggers/fix#788
improve exceptions in case of corrupt packages
2020-07-25 13:30:54 +02:00
Paweł Słowik 857ab005be Modified IManagedMqttClient extension methods to work on less specific interfaces (IApplicationMessagePublisher and IApplicationMessageReceiver) 2020-07-18 18:25:16 +02:00
JanEggers 33e4ec1943 improve exceptions in case of corrupt packages close pipes after exception occoured to avoid lingering connections should fix #788 2020-07-09 21:19:00 +02:00
Christian Kratky 6a564a0c72 Align nuget dependency versions and project references. 2020-07-04 17:04:36 +02:00
Christian 3a4dce5080 Update MQTTnet.nuspec 2020-06-28 00:17:30 +02:00
Christian 4e6118d324 Merge pull request #946 from JTOne123/master
[PR] The proj files have been updated to enable SourceLink
2020-06-27 23:10:39 +02:00
Pavlo Datsiuk 269bfa09ac [COMMIT] The proj files have been updated to enable SourceLink [MQTTnet.AspNetCore.csproj] 2020-06-25 12:53:00 +03:00
Pavlo Datsiuk 59dd6b98a3 [COMMIT] The proj files have been updated to enable SourceLink [MQTTnet.csproj] 2020-06-25 12:52:58 +03:00
Pavlo Datsiuk 9f37306f20 [COMMIT] The proj files have been updated to enable SourceLink [MQTTnet.Extensions.WebSocket4Net.csproj] 2020-06-25 12:52:55 +03:00
Pavlo Datsiuk 85b000c6b7 [COMMIT] The proj files have been updated to enable SourceLink [MQTTnet.Extensions.Rpc.csproj] 2020-06-25 12:52:52 +03:00
Pavlo Datsiuk 5a919ce5d2 [COMMIT] The proj files have been updated to enable SourceLink [MQTTnet.Extensions.ManagedClient.csproj] 2020-06-25 12:52:49 +03:00
Christian 57ab8e5abc Merge pull request #941 from chkr1011/disconnect-reason-codes
Added missing disconnect reason codes.
2020-06-18 20:25:16 +02:00
SeppPenner 8f6d48be81 Adjusted ImplementationSpecificError to be UnspecifiedError reason code in the MqttClient. 2020-06-18 10:03:44 +02:00
Christian 38cfa15cc3 Merge pull request #938 from chkr1011/interceptor-undelivered
Added interceptor for undelivered messages.
2020-06-15 23:13:06 +02:00
SeppPenner 6adf7096ec Updated client sessions manager to handle the delivery count for the handler correctly. 2020-06-12 20:25:51 +02:00
SeppPenner df149eb0b3 Added reason code to MqttClientDisconnectedEventArgs and use it. 2020-06-12 20:21:23 +02:00
Christian Kratky 63c9329190 Merge remote-tracking branch 'origin/master' 2020-06-12 11:19:36 +02:00
Christian Kratky 246a10649a Minor refactorings. 2020-06-12 11:19:29 +02:00
SeppPenner 0a76ac15c6 Added missing disconnect reason codes. 2020-06-11 18:06:24 +02:00
HansM d801af5616 Merge branch 'master' into interceptor-undelivered 2020-06-11 12:46:02 +02:00
SeppPenner 257211fc7a Moved undeliveredMessageInterceptor to local variable to avoid threading issues. 2020-06-11 12:41:48 +02:00
SeppPenner a407fc381b Made deliveryCount a local variable. 2020-06-11 12:39:56 +02:00
Christian 4fa275bf2b Merge pull request #937 from chkr1011/fix-writeasync-nre
Added checks for null references in the MqttTcpChannel.
2020-06-10 21:09:48 +02:00
SeppPenner 7cf12dc751 Made delivery count internal. 2020-06-10 18:45:15 +02:00
SeppPenner 40aefd0ad3 Added local variable to avoid that the solution is not threadsafe. 2020-06-10 12:00:34 +02:00
SeppPenner c20142671f MQTTnet: Adjusted UndeliveredMessageInterceptor handler to return if it's null instead of throwing an exception. 2020-06-10 11:52:55 +02:00
SeppPenner 75dfe68a94 Added interceptor for undelivered messages. 2020-06-09 20:54:42 +02:00
Christian 92518fc4ec Merge pull request #935 from JanEggers/fixedParallelWrites
fixed parallel writes #932
2020-05-27 21:44:26 +02:00
JanEggers 16180e83ba fixed parallel writes #932 2020-05-27 20:38:34 +02:00
Christian Kratky c779b394f1 Add abstraction layer for server certificate. 2020-05-26 23:46:43 +02:00
Christian Kratky e60a732b61 Merge remote-tracking branch 'origin/master' 2020-05-26 23:17:10 +02:00
Christian Kratky 7ea9415c63 Add proper state checks for server API. 2020-05-26 23:17:06 +02:00
Christian 13c399bc9a Merge pull request #895 from borigas/x509Cert
Add an x509 certificate parameter
2020-05-26 23:14:23 +02:00
Christian Kratky 4565c3990a Fix Blazor projects. 2020-05-25 22:33:05 +02:00
Christian Kratky 2bd2648b48 Merge remote-tracking branch 'origin/master' 2020-05-25 22:31:11 +02:00
Christian Kratky 1b56155f1c Add Blazor test app. 2020-05-25 22:31:07 +02:00
Christian 626930cfae Update README.md 2020-05-24 16:37:02 +02:00
Christian 6cf9cb0af2 Update README.md 2020-05-24 16:36:54 +02:00
Christian Kratky 60941c04e5 Add new factory overloads. 2020-05-22 22:02:05 +02:00
Christian Kratky ba68b1274b Merge remote-tracking branch 'origin/master' 2020-05-21 12:40:56 +02:00
Christian Kratky dbe12b9c48 General code refactoring. 2020-05-21 12:40:51 +02:00
Christian 52b79a140b Merge pull request #930 from prime167/patch-1
Update MqttTopicFilterBuilder.cs
2020-05-21 12:38:17 +02:00
Jeff Zhou c270225e9e Update MqttTopicFilterBuilder.cs
Fix TopicFilterBuilder obsolete message
2020-05-21 09:35:07 +08:00
Christian Kratky 3f5d4e9825 Added MQTT JS examples for MQTTnet.Server. 2020-05-16 20:59:54 +02:00
Christian Kratky e80d19ba9b Update docs. 2020-05-16 13:01:50 +02:00
Christian Kratky 48837529a2 Fix web socket sub protocol negotiation. 2020-05-16 13:01:41 +02:00
Christian Kratky 43e3ad4c00 Add support for static files. 2020-05-16 13:01:12 +02:00
Christian Kratky 08c9ecb011 Fix wrong keep alive delay calculation. 2020-05-16 10:32:50 +02:00
Christian Kratky 763f0e7934 Update nuspec. 2020-05-14 21:01:39 +02:00
Christian Kratky 9d381c2cf9 Update nuspec. 2020-05-14 00:40:14 +02:00
Christian Kratky 17ceb20169 Add dummy method to allow safe downgrade. 2020-05-14 00:18:50 +02:00
Christian Kratky 683bb43486 Fix performance issue in logger. 2020-05-14 00:05:52 +02:00
Christian Kratky d25b51740b Merge remote-tracking branch 'origin/master' 2020-05-12 21:55:17 +02:00
Christian Kratky a58ab607ad Improve logger performance. 2020-05-12 21:55:15 +02:00
Christian 0a7d450f3b Merge pull request #920 from mseyock/change-icon
Remove shadow from icon
2020-05-08 16:37:31 +02:00
ms 999fa7a468 Remove shadow from icon 2020-05-08 15:21:50 +02:00
Christian Kratky f0a1f9ca93 Add support for user properties in client connect. 2020-05-04 23:15:38 +02:00
Christian Kratky 89e9cb224f Update nuspec. 2020-05-02 21:20:22 +02:00
Christian Kratky fe48c9c837 Update nuspecs. 2020-05-01 23:39:17 +02:00
Christian Kratky 2a421d1d42 Refactor code. 2020-05-01 21:47:25 +02:00
Christian Kratky 48d0344a40 Fix WebSocket4Net extension nuspec. 2020-04-30 23:15:28 +02:00
Christian Kratky db5ed594f7 Merge remote-tracking branch 'origin/master' 2020-04-30 23:02:09 +02:00
Christian Kratky f85bc9b956 Dispose socket when TCP connect failed. 2020-04-30 23:02:05 +02:00
Christian eec46dd9bc Update LICENSE 2020-04-30 22:07:50 +02:00
Christian 9c9e2293c8 Update README.md 2020-04-29 18:04:17 +02:00
Christian 856861e1b1 Merge pull request #909 from JanEggers/nuget
removed unused dependecies
2020-04-27 21:24:24 +02:00
JanEggers 4b481b4833 removed unused dependecies 2020-04-27 17:09:54 +02:00
Christian c05f11a495 Update README.md 2020-04-25 14:44:07 +02:00
Christian Kratky e798c91ff3 Fix exception handling when using invalid host names upon connect. 2020-04-24 19:29:03 +02:00
Christian Kratky 5df4fc3d5d Update docs. 2020-04-22 21:10:55 +02:00
Christian Kratky c6236c0865 Remove nuget config. 2020-04-22 21:09:48 +02:00
Christian Kratky 85c0cb3bcc Remove nuget config because it breaks the CI. 2020-04-22 12:32:57 +02:00
Christian Kratky 9810e52bcb Fix build. 2020-04-22 12:30:11 +02:00
Christian Kratky 948a5eaae3 Merge remote-tracking branch 'origin/master' 2020-04-22 12:05:11 +02:00
Christian Kratky 31df8247fa Try to fix CI build. 2020-04-22 12:05:05 +02:00
Christian 229418100c Merge pull request #904 from JanEggers/nuget
fixed netcoreapp3.1 build #903
2020-04-22 12:04:02 +02:00
JanEggers 93d8679bbc fixed netcoreapp3.1 build 2020-04-21 21:19:49 +02:00
Christian 6cec126862 Update README.md 2020-04-19 01:11:15 +02:00
Christian Kratky 9749f790ea Try to fix CI builds. 2020-04-18 20:35:39 +02:00
Christian Kratky fbbc638c75 Try to fix CI builds. 2020-04-18 20:28:46 +02:00
Christian Kratky bf679adb6b Try to fix CI builds. 2020-04-18 19:43:28 +02:00
Christian Kratky cf7e59a774 Improve unit tests. 2020-04-18 16:55:37 +02:00
Christian e9724c0202 Merge pull request #882 from xljiulang/master
Use IConnectionEndPointFeature to get IMqttChannelAdapter.Endpoint in aspnetcore31
2020-04-18 13:49:45 +02:00
Christian Kratky 7931af7487 Add support for certificate validation callback for Web Socket connections. 2020-04-18 13:46:20 +02:00
Christian Kratky bb5f023b74 Update docs. 2020-04-18 01:38:53 +02:00
Christian Kratky c2ac4fffaf Expose PING method for clients. 2020-04-18 01:38:48 +02:00
Christian Kratky 4b78710705 Refactor topic filter naming. 2020-04-18 01:38:20 +02:00
Christian Kratky 2e69f8be78 Merge remote-tracking branch 'origin/master' 2020-04-16 12:48:31 +02:00
Christian Kratky 2d6c44e45b MQTTnet.Server: Fix version detection. 2020-04-16 12:48:26 +02:00
Ben Origas fc3965f5a3 Also Wrap certificate namespace in a !UWP compiler directive in options builder 2020-04-15 10:00:25 -05:00
Ben Origas 1d553c5ece Wrap certificate namespace in a !UWP compiler directive 2020-04-15 09:57:06 -05:00
Ben Origas 07ad9fc557 Add exception if both Certificate and X509Certificate are set 2020-04-15 09:55:23 -05:00
Christian f001d7aecc Merge pull request #898 from xgstation/master
Fix hanging issue under UWP.
2020-04-14 22:21:31 +02:00
JanEggers d49a4384c0 use the RemoteEndpoint property from the ConnectionContext and added test 2020-04-14 19:16:32 +02:00
Gen 4e6658e014 Fix typo. 2020-04-14 09:36:02 -07:00
Gen 2b2b30912c Configure context. 2020-04-14 07:37:23 -07:00
Gen 79d95c8516 Fix hanging issue under UWP. 2020-04-13 03:04:44 -07:00
Ben Origas 88e8691ce0 Move server x509 certs into non-uwp compiler flags 2020-04-10 17:16:42 -05:00
Ben Origas 28641892f5 Add an x509 certificate parameter 2020-04-10 17:16:42 -05:00
Christian Kratky 4b08bb41f5 Refactor code. 2020-04-10 10:53:17 +02:00
Christian Kratky c89918a890 Update python runtime for MQTTnet.Server. 2020-04-08 22:01:20 +02:00
Christian 6546175ea2 Update README.md 2020-04-07 12:22:16 +02:00
Christian Kratky b9e9fe64ac Refactor adapter handling. 2020-04-05 15:43:16 +02:00
Christian 9fd7c7bc1e Merge pull request #891 from PSanetra/async-message-processing
Introduce asynchronous message processing
2020-04-04 23:36:58 +02:00
PSanetra fcd6b7ff52 Process messages async
This commit fixes issues which were caused by processing messages synchronously in the packet receiver loop. This blocked KeepAlive and Ack packets from being processed while a message was processed.

Fixes #648
Fixes #587
Fixes #829
2020-04-04 22:40:16 +02:00
Christian Kratky 54870adc64 Fix build warnings and errors. 2020-04-04 19:40:09 +02:00
PSanetra 892e4842ed Fix MQTTnet.Tests/Server_Tests/Same_Client_Id_Connect_Disconnect_Event_Order
This failing test was caused by a raise condition in the MqttClientSessionsManager
The test failed as the value of `flow` in the assertion `Assert.AreEqual("cdc", flow);` was "ccd"
2020-04-04 15:03:15 +02:00
Christian Kratky fc358f9015 Fix build errors. 2020-04-04 13:08:29 +02:00
Christian Kratky b93cd5b673 Refactor code. 2020-04-04 13:07:10 +02:00
Christian aafc99f39e Merge pull request #884 from chkr1011/feature-isconnected
Added check if the server is started or not.
2020-04-04 13:05:58 +02:00
Christian b14d7affe5 Merge branch 'master' into feature-isconnected 2020-04-04 13:05:45 +02:00
Christian Kratky 67d56644b2 Expose custom session items in session status. 2020-04-04 12:54:33 +02:00
Christian Kratky 6e0d3ec0fb Update nuget packages. 2020-04-04 12:15:51 +02:00
Christian Kratky 2c6613a7b7 Merge branch 'feature/low_level_client' 2020-04-04 01:09:48 +02:00
Christian Kratky d464bfb7c5 Fix connect and disconnect event flow. 2020-04-04 01:01:37 +02:00
Christian Kratky 7a24970035 Fix UnitTests. 2020-04-03 23:08:54 +02:00
Christian Kratky db906eca24 Merge branch 'master' into feature/low_level_client 2020-04-03 22:53:22 +02:00
Christian Kratky ad128c7889 Improve socket handling. 2020-04-03 22:52:55 +02:00
Christian 3e096bc353 Merge pull request #886 from PMExtra/feature-userproperties
GetUserProperty extension.
2020-04-03 22:50:52 +02:00
HansM f0be8404cf Merge branch 'master' into feature-userproperties 2020-04-03 18:49:39 +02:00
Christian 6de28d32e4 Merge pull request #889 from PMExtra/feature-with-uri
Support MqttClientOptionsBuilder.WithConnectionUri()
2020-04-03 14:32:11 +02:00
PM Extra 2ede7df38a Merge branch 'master' into feature-userproperties 2020-04-03 18:04:00 +08:00
PM Extra 2a35108a73 Merge branch 'master' into feature-with-uri 2020-04-03 18:03:11 +08:00
PMExtra 774d49a908 Fix exception message and add test cases. 2020-04-03 15:03:10 +08:00
PMExtra c83bec6e81 Fix for Nullable. 2020-04-03 14:44:04 +08:00
PMExtra 763d9778bb Check parameters and add friendly exceptions. 2020-04-02 17:29:24 +08:00
PMExtra 9368eebfd5 Update nuspec. 2020-04-02 16:07:21 +08:00
Christian Kratky 81b547f386 Fix logging issues. 2020-04-01 23:15:08 +02:00
Christian e33c5ccb4c Merge pull request #885 from chkr1011/fix-userproperties
Removed checks for user properties in MQTT v3 and instead ignore them.
2020-04-01 23:02:08 +02:00
Christian Kratky 0ca4c88e69 Merge branch 'master' into feature/low_level_client 2020-04-01 23:01:03 +02:00
Christian Kratky 04ccdcd562 Add low level client. 2020-04-01 20:43:00 +02:00
PMExtra aafd4ea658 Fix. 2020-04-01 15:30:24 +08:00
PMExtra 4eb65fc3d2 Support MqttClientOptionsBuilder.WithConnectionUri() 2020-03-31 16:42:04 +08:00
PMExtra f7f00f4e06 Update nuspec. 2020-03-31 12:03:00 +08:00
HansM af0b98eace Merge pull request #888 from chkr1011/fix-copyright-date
Adjusted copyright information in the nuget package specifications.
2020-03-30 19:47:46 +02:00
SeppPenner 0da2ab9de6 Adjusted copyright information in the nuget package specifications. 2020-03-30 19:46:18 +02:00
SeppPenner ea22ef4164 Adjusted .nuspec file, added property to interface as well. 2020-03-30 19:44:15 +02:00
SeppPenner cb5a0cf38b Updated nuget package description. 2020-03-30 19:38:44 +02:00
PMExtra 55dc940abb GetUserProperty extension. 2020-03-30 17:10:04 +08:00
SeppPenner c40e3c64aa Removed checks for user properties in MQTT v3 and instead ignore them. 2020-03-29 17:26:40 +02:00
SeppPenner 87c4fa14ee Added check if the server is started or not. 2020-03-29 16:48:19 +02:00
Christian Kratky 0653b89701 Fix broken unit tests. 2020-03-26 22:33:30 +01:00
Christian Kratky 561474c572 Fix broken unit tests. 2020-03-26 15:35:14 +01:00
陈国伟 c10145f743 Use IConnectionEndPointFeature to get IMqttChannelAdapter.Endpoint in aspnetcore31 2020-03-26 12:32:09 +08:00
Christian dca2af47d8 Merge pull request #880 from xljiulang/master
Reduce the performance cost of Memory<T>.getSpan()
2020-03-25 21:33:34 +01:00
xljiulang 9ed80daf83 Reduce the performance cost of Memory<T>.getSpan() 2020-03-25 21:32:43 +08:00
Christian 0d39bbbc0c Merge pull request #870 from JanEggers/aspnetcore3bugfixes
Aspnetcore3bugfixes
2020-03-17 10:17:12 +01:00
JanEggers 52faf6d76a updated releasenotes 2020-03-15 14:47:50 +01:00
JanEggers 20eda96921 fixed core 3.1 startup and verified it still works with 2.1 and net461 2020-03-15 14:43:59 +01:00
Christian Kratky f6a814c6d7 Update build script. 2020-03-14 23:52:07 +01:00
Christian Kratky 8e0bce7734 Remove obsolete references. 2020-03-14 23:49:26 +01:00
Christian Kratky 72fa13ca5b Fix build errors. 2020-03-14 22:59:17 +01:00
Christian Kratky 45e3455e6c Merge remote-tracking branch 'origin/master' 2020-03-14 22:46:23 +01:00
Christian 160da00f55 Merge pull request #873 from andrei-m-code/bugfix/mqttnet-client-semaphore-dispose
DIspose semaphore in MqttChannelAdapter
2020-03-14 22:39:46 +01:00
Christian Kratky 6b4b829cf6 Merge branch 'develop' 2020-03-14 22:38:36 +01:00
Andrei Mikhalevich e7fa465616 DIspose semaphore in MqttChannelAdapter 2020-03-12 11:07:30 -04:00
Christian 799005803e Merge pull request #869 from dominikviererbe/feature/MqttClientUnsubscribeOptionsBuilder
Added MqttClientUnsubscribeOptionsBuilder
2020-03-10 09:55:57 +01:00
Dominik Viererbe a20c845a5a Update MQTTnet.nuspec 2020-03-09 18:27:35 +01:00
Dominik Viererbe 5f59aca62c Added MqttClientUnsubscribeOptionsBuilder analogous to MqttClientSubscribeOptionsBuilder 2020-02-25 16:30:08 +01:00
HansM 76ddf8c503 Merge pull request #852 from cdobler/check-"Keep-Alive"-while-other-messages-are-sent-#851
Added receiveTracker to detect whether messages are received from broker.
2020-02-24 17:02:42 +01:00
Christoph 122034296c Merge branch 'develop' into check-"Keep-Alive"-while-other-messages-are-sent-#851 2020-02-24 08:20:25 +01:00
Christian 6f71aaf1ce Merge pull request #868 from wazzamatazz/master
Add .NET 3.1 target
2020-02-22 19:32:12 +01:00
Graham Watts fd8caed9af Add .NET 3.1 target
Add .NET Core 3.1 target that uses ASP.NET Core framework reference instead of NuGet package references
2020-02-22 11:25:01 +02:00
Christoph 313f90a526 Added receiveTracker to detect whether messages are received from broker. 2020-01-28 14:36:19 +01:00
Christian Kratky 4d27f42e72 Merge remote-tracking branch 'origin/develop' into develop 2020-01-25 23:34:53 +01:00
Christian 8ae318fd5c Merge pull request #838 from jimsch/connectErrors
Allow access to full packet on failed connect
2020-01-12 22:11:28 +01:00
Jim Schaad 7dde2f1f4c Change variable name per review request
Change the name of the variable from requestCode to request
2020-01-12 12:31:09 -08:00
Christian Kratky 49c5278ba0 Merge branch 'master' into develop 2020-01-10 22:18:48 +01:00
Christian Kratky ce51d12a03 Update SDK versions. 2020-01-10 22:16:31 +01:00
Jim Schaad b1559a8fa5 Correct to print right result
Lost a change while moving from my developement branch to here.
2020-01-08 11:11:41 -08:00
Jim Schaad 457143c840 Merge branch 'develop' into connectErrors 2020-01-08 11:10:58 -08:00
Christian c60bf51b1e Merge pull request #839 from JanEggers/develop
bugfixes
2020-01-08 19:14:08 +01:00
JanEggers 630400da53 avoid task.run on newer platforms 2020-01-04 11:55:12 +01:00
JanEggers a152066ed3 fixed managed client so it does not send disconnect packet when disposed 2020-01-04 11:54:41 +01:00
JanEggers 138cd16c8d fixed compilation 2020-01-04 11:53:15 +01:00
JanEggers 27a61819d3 removed unused code 2020-01-04 11:52:43 +01:00
Jim Schaad 9c378fb088 Provide the full ACK on a connection failure
There are some systems that return information on a failed exception and thus the client wants access to the full set of ACK information.  Specifically the user properties.
2019-12-31 14:44:25 -08:00
Jim Schaad d4088420cf Return correct set of user properties
Return the response not the request set of user properties
2019-12-31 14:33:31 -08:00
Christian 2e7d074174 Merge pull request #833 from JanEggers/bugfixes
Bugfixes
2019-12-28 20:28:38 +01:00
JanEggers 328ffc734f dont allow publish before the client is started and adjusted testclient accordingly 2019-12-28 15:55:35 +01:00
Christian 8ecf658059 Update MQTTnet.nuspec 2019-12-28 14:05:24 +01:00
Christian 7b25c6f274 Merge pull request #836 from PMExtra/develop
Support existing session with ManagedMqttClient.
2019-12-28 14:04:27 +01:00
PMExtra 069c19aab9 Support existing session with ManagedMqttClient. 2019-12-23 20:38:29 +08:00
Christian 35e729bd7b Merge pull request #826 from fogzot/develop-iretainedmesagesmanager
Added IMqttRetainedMessagesManager
2019-12-22 16:50:37 +01:00
JanEggers ac06a001e2 fixed some warnings 2019-12-21 10:42:18 +01:00
JanEggers a77e0b8dde spread dispose pattern 2019-12-21 09:09:03 +01:00
JanEggers 698f0b66d2 fixed object disposed exception on netfx fixing #803 #733 #728 #486 #158 2019-12-20 15:37:42 +01:00
JanEggers 14419e4d63 fixed clients overlapping from one test to another by:
- adding client and server wrappers to verify the clientid starts with the testname
- adding disposable baseclass
- clear disconnect handler from client so it does not try to reconnect after it is disposed
- moved code from dispose to cleanup in case it is called in a stop method as dispose may only be called once while start / stop may be called multiple times
2019-12-20 15:37:23 +01:00
Federico Di Gregorio 3600ebbc62 Create default MqttRetainedMessagesManager in options 2019-12-18 10:25:24 +01:00
Federico Di Gregorio 55676965d9 Use IList in IMqttRetainedMessagesManager return values 2019-12-17 12:39:57 +01:00
Federico Di Gregorio f949d54aef Added IMqttRetainedMessagesManager
* Added interface IMqttRetainedMessagesManager to allow for different
retained messages manager implementations. The interface copies almost
exactly the current MqttRetainedMessagesManager implementation.

* Added IMqttRetainedMessagesManager.Start() to configure the provided
IMqttRetainedMessagesManager outside the constructor. This method returns
Task because some implementations that use external storage may be slow on
initialization (e.g., connect to a database).

* Modified MqttRetainedMessagesManager to implement new interface.
2019-12-17 11:57:17 +01:00
Christian Kratky 624fafc662 Update nugets. 2019-12-08 20:10:46 +01:00
Christian 23e93212a4 Merge pull request #800 from stepkillah/develop
Replace raw bytes with x509 certificate to allow specify passwords and flags #2
2019-11-27 21:33:21 +01:00
Anton Yaroshenko f9b2c91ddb merged 2019-11-18 11:32:00 +02:00
Anton Yaroshenko 9fb1cc3320 added UWP compiler flags 2019-11-18 11:16:34 +02:00
Christian Kratky 1c89a8bc75 Update docs. 2019-11-17 21:25:30 +01:00
Christian Kratky 8be9ce8024 Merge remote-tracking branch 'origin/develop' into develop 2019-11-17 21:25:05 +01:00
Christian 002ba27fd3 Merge pull request #799 from chkr1011/revert-798-master
Revert "Replace raw bytes with x509 certificate to allow specify passwords and flags"
2019-11-17 21:24:47 +01:00
Christian 9aaa94e821 Revert "Replace raw bytes with x509 certificate to allow specify passwords and flags" 2019-11-17 21:24:30 +01:00
Anton Yaroshenko e8ff48bfd3 Revert "blind uwp fix"
This reverts commit ac326babdf.
2019-11-17 21:23:20 +01:00
Anton Yaroshenko 5db05f186f Revert "replace raw byte with x509 certificate to allow specify passwords"
This reverts commit a38623cb5a.
2019-11-17 21:23:16 +01:00
Christian b2c2209b4f Update MQTTnet.nuspec 2019-11-17 21:06:37 +01:00
Christian c490e83c91 Merge pull request #798 from stepkillah/master
Replace raw bytes with x509 certificate to allow specify passwords and flags
2019-11-17 21:05:05 +01:00
Anton Yaroshenko ac326babdf blind uwp fix 2019-11-17 20:12:03 +02:00
Anton Yaroshenko a38623cb5a replace raw byte with x509 certificate to allow specify passwords 2019-11-17 19:42:23 +02:00
Christian Kratky a63489fa5e Update docs. 2019-11-14 20:52:35 +01:00
Christian Kratky 4b7409240b Merge remote-tracking branch 'origin/develop' into develop 2019-11-14 20:47:36 +01:00
Christian Kratky 896e9ed0aa Add interceptor for unsubscriptions. 2019-11-14 20:47:33 +01:00
Christian 0950dfbb8b Merge pull request #786 from llrosa/debugFixClientId
Fix for #785 - Skip client disconnection process if unauthorized
2019-11-03 13:23:23 +01:00
Lucas Rosa 4105beb7e6 Some more cleaning up: 2019-10-29 12:55:57 -03:00
Lucas Rosa 5c25905510 Clean up 2019-10-29 12:48:04 -03:00
Lucas Rosa e3f6b579b2 Working PoC 2019-10-29 12:32:20 -03:00
Lucas Rosa c467c9c818 Debugging duplicated client id issue 2019-10-29 11:44:41 -03:00
Christian Kratky 78b57531b6 Update docs. 2019-10-24 20:09:11 +02:00
Christian 84d9f533bd Merge pull request #782 from cstichlberger/develop
Reduce subscription publishing loglevel in ManagedMqttClient
2019-10-24 20:06:47 +02:00
Christoph Stichlberger 7479e320ee Turn subscription publishing loglevel down
- the Info level for publishing subscriptions is quite noisy
 - previously this wasn't a problem because subscription processing was buffered, now the message is logged for nearly every single un/subscription that is made
 - all other frequently recurring log events are also on level Verbose
2019-10-23 17:01:44 +02:00
Christian Kratky 152303dfbd Update docs. 2019-10-18 19:31:40 +02:00
Christian a495668f2b Merge pull request #776 from cstichlberger/branches/fix_managed_client_subscription_issues
Separate current and reconnect subscriptions in managed client
2019-10-18 19:29:09 +02:00
HansM 82b714d4c7 Merge pull request #777 from cstichlberger/develop
Adapt test assembly paths in buildscript
2019-10-18 11:39:06 +02:00
Christoph Stichlberger 44d71b884c Adapt test assembly paths in buildscript 2019-10-17 06:45:46 +02:00
Christoph Stichlberger 781c5d4d7d Separate current and reconnect subscsriptions in managed client
This change kills several birds with one stone:
 - by performing the re-publishing of all subscriptions only at reconnect it fixes issue https://github.com/chkr1011/MQTTnet/issues/569 (retained messages are received again with every new subscription that is added)
 - not sending the subscriptions again with every (un)subscription is also a performance improvement if subscriptions are modified on a regular basis, because only the updated subscriptions are sent to the broker (previously, if you had 100 subscriptions and added a new one, 100 suscriptions were re-sent to the broker along with the new one, causing a significant delay)
 -until now subscriptions were sent to the broker only every ConnectionCheckInterval which caused unnecessary delays, and for request-response patterns could cause reponse messages to be missed due to the subscription delay. Now (un)subscriptions are published immediately

Subscriptions are now cleaned up at logout (after the connection stops being maintained). This is in line with the clearing of the _messageQueue in StopAsync

Explanatory note: the _subscriptionsQueuedSignal could ideally be a ManualResetEvent(Slim) but those do not offer an awaitable Wait method, so a SemaphoreSlim is used. This possibly causes a few empty loops in PublishSubscriptionsAsync due to the semaphore being incremented with every SubscribeAsync call but all subscriptions getting processed in one sweep, but those empty loops shouldn't be a problem
2019-10-15 15:26:05 +02:00
Christian Kratky b175119008 Refactoring and doc updates. 2019-10-04 20:01:51 +02:00
Christian Kratky cfcb858423 Update libs. 2019-10-04 19:51:35 +02:00
Christian Kratky 5fa12649bf Merge remote-tracking branch 'origin/develop' into develop 2019-10-04 19:51:13 +02:00
Christian a9a09f4ecd Merge pull request #754 from jltjohanlindqvist/branches/fixUnhandledTaskCrash
Remove if clause that stopped handling of tasks with exceptions
2019-10-04 19:50:56 +02:00
Christian Kratky 3ff5806dbb Dispose queue in managed client. 2019-10-03 15:26:33 +02:00
Christian Kratky 0ec78cf5cc Merge remote-tracking branch 'origin/develop' into develop 2019-10-03 15:25:02 +02:00
Christian c3193c568a Merge pull request #763 from zawodskoj/master
Fix for #762 - thread pool leak
2019-10-03 15:24:56 +02:00
Christian Kratky a1f02284e9 Merge branch 'master' into develop 2019-10-03 15:23:52 +02:00
Christian Kratky 851db2e808 Merge remote-tracking branch 'origin/master' 2019-10-03 15:23:42 +02:00
Christian Kratky 073cd5243f Update docs. Add UnitTests. 2019-10-03 15:23:35 +02:00
Jimmy Rosenskog 699558e47a Added exception handling to make sure all tasks are observed to avoid UnobservedTaskException. 2019-10-03 09:46:40 +02:00
Бессонов Дмитрий 15ff03c136 use C#7.0 for default arguments 2019-09-30 16:10:30 +03:00
Бессонов Дмитрий b12e3bc611 fix for #762 2019-09-30 16:05:23 +03:00
Johan x Lindqvist 61c3e02242 Updated exception message to be in line with other exception messages. 2019-09-19 13:31:57 +02:00
Johan x Lindqvist 5618c4c1f7 Always access the exception property on the task if it has status IsFaulted.
By checking the Exception property it will consider the task exception as handled which means the finalizer won't throw an unhandled task exception.
2019-09-18 13:49:59 +02:00
Johan x Lindqvist ba9ceed7ce Use Task.WhenAll to handle errors in both tasks.
Previously if there was an exception in the first task that is awaited the second task would not be awaited.
2019-09-16 11:33:37 +02:00
Johan x Lindqvist ad1c198e43 Remove if clause that stopped handling of tasks with exceptions.
Now the task is always awaited and thus the exception in the task is handled.
2019-09-12 09:05:08 +02:00
SeppPenner 2918be18c6 Added automatic labels to the issue templates. 2019-09-05 10:37:55 +02:00
Christian 248e2a5bdd Merge pull request #746 from bcrosnier/pr/mqtt5-assigned-client-id
Better handling of AssignedClientIdentifier - chkr1011/MQTTnet#745
2019-08-25 22:12:57 +02:00
Benjamin Crosnier 1a41415dd1 Allow AssignedClientIdentifier in ClientConnected, ClientDisconnected and ConnectedHandler - Fixes chkr1011/MQTTnet#745 2019-08-19 10:41:28 +02:00
Christian Kratky 9302e80d73 Merge branch 'develop' 2019-08-18 21:00:40 +02:00
Christian Kratky cf6f0ece0e Add test execution in build script. 2019-08-18 20:56:26 +02:00
Christian Kratky 50d65f2fed Update nugets. 2019-08-14 23:06:45 +02:00
Christian Kratky 4614df7fa5 Update docs. 2019-08-14 22:57:17 +02:00
Christian 22aedcba09 Merge pull request #744 from JanEggers/pr/fix#743
fixed #743
2019-08-14 22:53:55 +02:00
Christian Kratky 2767d897a4 Fix serialization issue of MQTTv5 PubRec packet. 2019-08-14 22:45:15 +02:00
JanEggers a4420063c0 fixed #743 2019-08-14 22:29:51 +02:00
Christian Kratky 2320352124 Update docs. 2019-08-13 20:09:21 +02:00
Christian Kratky c0b4155ab4 Update docs. 2019-08-13 20:07:14 +02:00
Christian Kratky b09f31d654 Fix TCP server adpater when using empty password. 2019-08-13 20:07:10 +02:00
Christian Kratky 30c33d46f9 Merge remote-tracking branch 'origin/develop' into develop 2019-08-13 19:56:36 +02:00
Christian 651b79a124 Merge pull request #740 from cslutgen/chain
Fix Client SslStream CRL verification
2019-08-13 19:56:26 +02:00
Christian Kratky 2e3cf54f11 Add support for different strategies when generating RPC topics. 2019-08-13 19:53:55 +02:00
Craig Lutgen d7948afd98 Fix client SslStream certificate chain CRL validation. The logic was inverse and CRLs were never checked.
Add a missing dispose in managed client.
2019-08-12 17:34:05 -05:00
cslutgen 4cefa1dfa9 Merge pull request #2 from chkr1011/develop
Develop
2019-08-12 17:28:31 -05:00
Christian Kratky 0cfb8b4020 Remove not async task handling. 2019-08-11 22:25:05 +02:00
Christian Kratky 9ac726b271 Revert "Remove dedicated UWP builds and code."
This reverts commit 6d0e2c2022.
2019-08-11 22:19:49 +02:00
Christian Kratky 232605304e Revert "Update nugets."
This reverts commit 6c53677e7d.
2019-08-11 22:19:29 +02:00
Christian Kratky 6c53677e7d Update nugets. 2019-08-11 22:10:49 +02:00
Christian Kratky 6d0e2c2022 Remove dedicated UWP builds and code. 2019-08-11 22:07:57 +02:00
Christian Kratky 8ad1fb2871 Refactor server certificate classes (breaking change). 2019-08-11 21:46:13 +02:00
Christian Kratky 4a7ff9e9ed Add TLS certificate password support for MQTTnet.Server. 2019-08-11 21:45:41 +02:00
Christian Kratky f54598c201 Merge branch 'develop' 2019-08-11 16:33:40 +02:00
Christian Kratky 2300e68fff Add UnitTests for RPC. 2019-08-11 10:41:36 +02:00
Christian Kratky 6996824157 Merge branch 'master' into develop 2019-08-11 10:17:51 +02:00
Christian Kratky 524f695829 Update docs. 2019-08-09 22:21:42 +02:00
Christian 72faa067cc Merge pull request #729 from cslutgen/clientcerts
Add Server certificate password and client certificate builders
2019-08-09 22:07:26 +02:00
SeppPenner 01aa75471c Updated description of issue templates. 2019-08-09 11:20:28 +02:00
HansM 048206eb1e Fixed my spelling mistake from before. 2019-08-09 11:14:52 +02:00
HansM ad5b0caa4d Fixed spelling issue in feature request issue template. 2019-08-09 11:13:40 +02:00
HansM 0f14ddcf79 Updated bug report issue template. 2019-08-09 11:13:06 +02:00
Craig Lutgen 59d2a8e551 Changed server crentials property name from password to certificateCredentials 2019-08-08 13:35:14 -05:00
HansM 8607ceb3b7 Fixed feature request issue template. 2019-08-02 08:47:09 +02:00
HansM b82e5a48a4 Fixed custom issue template. 2019-08-02 08:46:35 +02:00
HansM 30c5147c62 Fixed bug reports issue template. 2019-08-02 08:46:12 +02:00
Craig Lutgen 9d63500f95 Fix build issue with UWP 2019-07-31 13:27:33 -05:00
Craig Lutgen a03bdc7616 Expose server certificate password and client certificate options to MqttServerOptionsBuilder 2019-07-31 13:04:03 -05:00
Christian Kratky 413daee551 Merge branch 'master' into develop 2019-07-30 20:35:48 +02:00
Christian Kratky f3ea7008e5 Merge remote-tracking branch 'origin/develop' into develop 2019-07-30 20:35:39 +02:00
Christian Kratky 8bfbbd2b29 Refactoring. 2019-07-30 20:35:33 +02:00
Christian Kratky ab8c7df0b9 Add unit Tests. 2019-07-30 20:35:22 +02:00
Christian Kratky 975eb60e90 Fix memory leak when SSL is not working properly. 2019-07-30 20:02:46 +02:00
Christian Kratky 6076151222 Update docs. 2019-07-30 20:01:57 +02:00
Christian Kratky 9cc96f1888 Refactor log messages. 2019-07-30 20:01:45 +02:00
HansM 7aa4d5159c Fixed styling in feature request template. 2019-07-30 09:56:00 +02:00
Christian 9b021c4093 Update README.md 2019-07-27 09:57:36 +02:00
Christian 54c303369e Update README.md 2019-07-27 09:56:59 +02:00
Christian 8f30042e49 Update README.md 2019-07-27 09:56:46 +02:00
Christian 4c33270d26 Merge pull request #718 from PaulFake/patch-3
Fixed AsyncLock::WaitAsync cancellation bug
2019-07-26 21:23:29 +02:00
Paul Fake 5c40577bec Fixed AsyncLock::WaitAsync cancellation bug
There isn't any code in MQTTnet that actually uses a cancellation token in WaitAsync, so this is more of a preventative thing than a bug fix.  The original code just checks if the task was completed, not whether it was cancelled.  If the process is cancelled immediately before the call to WaitAsync, it'll return as normal (https://referencesource.microsoft.com/#mscorlib/system/threading/SemaphoreSlim.cs,612) rather than throw a cancellation exception.  This change will ensure we only return the releaser if the wait actually ran to completion rather than exited early due to cancellation.  I've tested this, and it properly throws a cancellation exception later on.
2019-07-23 16:20:36 -04:00
Christian Kratky 3d404f9755 Fixed build. 2019-07-23 22:08:51 +02:00
Christian Kratky 1b5e0197e4 Update docs. 2019-07-23 21:56:14 +02:00
Christian 1dab729d84 Merge pull request #717 from PaulFake/patch-2
Storage queue drain test
2019-07-23 21:54:48 +02:00
Christian 3eac5bcaf3 Merge pull request #709 from PaulFake/patch-1
Fixed storage queue race condition
2019-07-23 21:54:21 +02:00
Paul Fake 8eb23f0f1d Storage queue drain test
It's a unit test to ensure the storage queue is drained.
2019-07-23 15:45:50 -04:00
Christian 1fd1a12fce Merge pull request #715 from mseyock/change-icon
Remove shadow and made text bold
2019-07-23 19:59:32 +02:00
Matthias Seyock 349d506b37 Remove shadow and made text bold 2019-07-23 16:03:18 +02:00
Christian a981b05aa7 Merge pull request #712 from mseyock/change-icon
fix typo in icon
2019-07-19 22:12:59 +02:00
Matthias Seyock 654f06d20d fix typo in icon 2019-07-19 20:34:39 +02:00
Christian c92cd10499 Merge pull request #711 from mseyock/change-icon
Replace icon
2019-07-19 19:33:32 +02:00
Christian Kratky ed06ea6bc9 Add version information to MQTTnet.Server. 2019-07-19 19:32:33 +02:00
Matthias Seyock 3d531151c6 Replace icon 2019-07-19 16:52:58 +02:00
Paul Fake e1590fc0c8 Fixed storage queue race condition
Sometimes, TryPublishQueuedMessageAsync would try to remove a message from the storage queue before PublishAsync added it to the storage queue, resulting in a message being stuck in the storage queue forever.  Switched the message queue lock to an async lock and synchronized the storage queue updates with the message queue updates.
2019-07-17 16:55:56 -04:00
Christian Kratky dbb227406b Added UnitTests. 2019-07-17 21:58:37 +02:00
Christian b891e1d1f4 Update issue templates 2019-07-17 19:45:08 +02:00
Christian 1d697e3b87 Merge pull request #702 from rudacs/clientCertificate-is-null
X509Certificate convert to X509Certificate2 in ClientCertificate
2019-07-15 19:18:03 +02:00
Rudá Cunha 128484c55a X509Certificate convert to X509Certificate2 in ClientCertificate 2019-07-15 10:46:45 -03:00
Christian Kratky ff22c34bb2 Add first classes for persisted session support. 2019-07-12 20:36:46 +02:00
Christian Kratky e7ba3f76dc Add options builder methods for remote certificate validation callback. 2019-07-11 23:03:56 +02:00
Christian 1ae3324581 Merge pull request #697 from rudacs/add-server-remove-validation-callback
Add remote certificate validation callback on server
2019-07-11 22:56:36 +02:00
Rudá Cunha ba8ce15ab4 Add remote certificate validation callback on server 2019-07-11 16:28:09 -03:00
Christian Kratky 87b4ce5185 Extend build and upload script to publish symbols as well. 2019-07-11 21:28:07 +02:00
Christian Kratky 4eb2b77138 Fix wrong NoDelay usage in server implementation. 2019-07-11 21:11:11 +02:00
Christian Kratky 70ee49f3c6 Merge remote-tracking branch 'origin/develop' into develop 2019-07-09 22:42:50 +02:00
Christian Kratky f223a26748 Update docs. 2019-07-09 22:42:44 +02:00
Christian 4574fdc951 Merge pull request #693 from JanEggers/pr/fix691
fixed #691
2019-07-09 22:39:48 +02:00
Jan Eggers 4f66614cdd fixed #691 2019-07-09 14:15:46 +02:00
Christian Kratky 6608172719 MQTTnet.Server: Extend messages API. 2019-07-07 21:26:07 +02:00
Christian Kratky 6c8db47e25 Remove dedicated values from contexts and only provide session items. 2019-07-05 18:28:18 +02:00
Christian Kratky 3eb5e82d10 Expose connect packet in application message interceptor and subscription interceptor. 2019-07-04 23:06:37 +02:00
Christian Kratky 8563230f9c Update docs. 2019-07-04 20:38:01 +02:00
Christian Kratky 019f428f0a MQTTnet.Server: Add HTTP API for publishing of messages. 2019-07-04 20:27:48 +02:00
Christian Kratky 1847af13d2 Merge branch 'develop' 2019-06-28 10:20:51 +02:00
Christian Kratky 8916df8d7b Move ReuseAddress to server options. 2019-06-27 15:20:27 +02:00
398 changed files with 12095 additions and 5878 deletions
+84
View File
@@ -0,0 +1,84 @@
[*.cs]
# CA1031: Do not catch general exception types
# Microsoft .NET properties
csharp_new_line_before_members_in_object_initializers = false
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
dotnet_naming_rule.constants_rule.severity = warning
dotnet_naming_rule.constants_rule.style = upper_camel_case_style
dotnet_naming_rule.constants_rule.symbols = constants_symbols
dotnet_naming_rule.public_fields_rule.severity = warning
dotnet_naming_rule.public_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.public_fields_rule.symbols = public_fields_symbols
dotnet_naming_rule.static_readonly_rule.severity = warning
dotnet_naming_rule.static_readonly_rule.style = upper_camel_case_style
dotnet_naming_rule.static_readonly_rule.symbols = static_readonly_symbols
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
dotnet_naming_style.lower_camel_case_style.required_prefix = _
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
dotnet_naming_symbols.constants_symbols.required_modifiers = const
dotnet_naming_symbols.public_fields_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.public_fields_symbols.applicable_kinds = field
dotnet_naming_symbols.static_readonly_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.static_readonly_symbols.applicable_kinds = field
dotnet_naming_symbols.static_readonly_symbols.required_modifiers = static,readonly
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_qualification_for_event = false:suggestion
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
# ReSharper properties
resharper_autodetect_indent_settings = true
resharper_default_private_modifier = implicit
resharper_place_accessorholder_attribute_on_same_line = false
resharper_use_indent_from_vs = false
# ReSharper inspection severities
resharper_arrange_redundant_parentheses_highlighting = hint
resharper_arrange_this_qualifier_highlighting = hint
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
resharper_built_in_type_reference_style_highlighting = hint
resharper_redundant_base_qualifier_highlighting = warning
resharper_suggest_var_or_type_built_in_types_highlighting = hint
resharper_suggest_var_or_type_elsewhere_highlighting = hint
resharper_suggest_var_or_type_simple_types_highlighting = hint
resharper_web_config_module_not_resolved_highlighting = warning
resharper_web_config_type_not_resolved_highlighting = warning
resharper_web_config_wrong_module_highlighting = warning
[*]
charset = utf-8
end_of_line = crlf
trim_trailing_whitespace = false
insert_final_newline = false
indent_style = space
indent_size = 4
[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]
indent_style = space
indent_size = 2
[{*.yaml,*.yml}]
indent_style = space
indent_size = 2
[{tsconfig.app.json,tsconfig.e2e.json,tsconfig.json,tsconfig.lib.json,tsconfig.spec.json}]
indent_style = space
indent_size = 2
[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]
indent_style = space
indent_size = 4
tab_width = 4
+46
View File
@@ -0,0 +1,46 @@
---
name: Bug report
about: Create a report to help us improve.
title: ''
labels: 'bug'
assignees: ''
---
### Describe the bug
A clear and concise description of what the bug is.
### Which project is your bug related to?
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic
### To Reproduce
Steps to reproduce the behavior:
1. Using this version of MQTTnet '...'.
2. Run this code '....'.
3. With these arguments '....'.
4. See error.
### Expected behavior
A clear and concise description of what you expected to happen.
### Screenshots
If applicable, add screenshots to help explain your problem.
### Additional context / logging
Add any other context about the problem here.
Include debugging or logging information here:
```batch
\\ Put your logging output here.
```
### Code example
Please provide full code examples below where possible to make it easier for the developers to check your issues.
```csharp
\\ Put your code here.
```
+19
View File
@@ -0,0 +1,19 @@
---
name: Custom issue template
about: Do you have a question related to the project? Use this template.
title: ''
labels: 'question'
assignees: ''
---
### Describe your question
A clear and concise description of what you want to know.
### Which project is your question related to?
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic
+29
View File
@@ -0,0 +1,29 @@
---
name: Feature request
about: Suggest an idea for this project.
title: ''
labels: 'feature-request'
assignees: ''
---
### Describe the feature request
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Example. I'm am trying to do [...] but [...]
### Which project is your feature request related to?
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
### Additional context
Add any other context or screenshots about the feature request here.
+2
View File
@@ -292,3 +292,5 @@ __pycache__/
*.map
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
Build/NuGet/
+26 -10
View File
@@ -3,23 +3,30 @@
<metadata>
<id>MQTTnet.AspNetCore</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</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>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\Logo_128x128.png</icon>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<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>
<copyright>Copyright Christian Kratky 2016-2019</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>
<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 Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
<group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="$nugetVersion" />
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.0" />
</group>
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="2.1.3" />
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.3" />
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.1.1" />
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="2.1.1" />
<group targetFramework="netcoreapp3.1">
<dependency id="MQTTnet" version="$nugetVersion" />
</group>
<group targetFramework="net5.0">
<dependency id="MQTTnet" version="$nugetVersion" />
</group>
</dependencies>
</metadata>
@@ -27,7 +34,16 @@
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\net5.0\MQTTnet.*" target="lib\net5.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>
</package>
+16 -9
View File
@@ -3,16 +3,17 @@
<metadata>
<id>MQTTnet.Extensions.ManagedClient</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</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>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\Logo_128x128.png</icon>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<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>
<copyright>Copyright Christian Kratky 2016-2019</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>
<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 Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
@@ -22,20 +23,26 @@
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.0\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.0\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\uap10.0\MQTTnet.Extensions.ManagedClient.*" target="lib\uap10.0\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\uap10.0\MQTTnet.Extensions.ManagedClient.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net452\MQTTnet.Extensions.ManagedClient.*" target="lib\net452\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net452\MQTTnet.Extensions.ManagedClient.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
+16 -9
View File
@@ -3,16 +3,17 @@
<metadata>
<id>MQTTnet.Extensions.Rpc</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</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>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\Logo_128x128.png</icon>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<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>
<copyright>Copyright Christian Kratky 2016-2019</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>
<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 Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
@@ -22,20 +23,26 @@
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.0\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.0\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\uap10.0\MQTTnet.Extensions.Rpc.*" target="lib\uap10.0\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\uap10.0\MQTTnet.Extensions.Rpc.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net452\MQTTnet.Extensions.Rpc.*" target="lib\net452\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net452\MQTTnet.Extensions.Rpc.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
+32 -10
View File
@@ -3,18 +3,34 @@
<metadata>
<id>MQTTnet.Extensions.WebSocket4Net</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</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>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\Logo_128x128.png</icon>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<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>
<copyright>Copyright Christian Kratky 2016-2019</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>
<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 Blazor</tags>
<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>
</metadata>
@@ -22,20 +38,26 @@
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\"/>
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\"/>
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\uap10.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\uap10.0\"/>
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\uap10.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net452\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net452\"/>
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net452\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net461\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net461\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
-42
View File
@@ -1,42 +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>
<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-2019</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" />
<!-- .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>
+58 -15
View File
@@ -3,25 +3,44 @@
<metadata>
<id>MQTTnet</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</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>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\Logo_128x128.png</icon>
<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>
<releaseNotes>
* [Core] Fixed wrong versions in nuget packages.
* [Server] The TCP address is now reused when starting which should prevent "port in used" error when restarting.
* [Core] Added .NET 5.0 TFMs (thanks to @StefanOssendorf, @JanEggers).
* [Core] Added support for TLS 1.3 (requires .NET Core 3.1+) (thanks to @Dvergatal).
* [Core] Added support for _MaximumQoS_ transmit when using MQTTv5 (thanks to @nayato).
* [Core] Aligned the format of some log messages.
* [Client] Fixed an issue with connection state detection (thanks to @tobiasfrick).
* [Client] Fixed an issue when receiving partial QoS 2 packets after a reconnect.
* [Client] Added new API for raw packet inspection.
* [ManagedClient] Removed _AutoReconnect_ since this does no longer work (BREAKING CHANGE!).
* [RpcClient] Moved the RPC topic validation to the topic generation strategy.
* [RcpClient] Added interface for _MqttRpcClient_.
* [Server] Reduced async tasks count by moving dedicated keep alive tasks per connection to shared one.
* [Server] Session takeover and keep alive timeout are now properly set in DISCONNECT packet.
* [Server] Fixed bug in PubRel packet generation (MQTTv5 only).
* [Server] Improved message processing performance (+ ~5%).
* [Server] Fix wrong usage of client session items for undelivered messages.
* [Server] Allow to respond with a reason code in PUBACK/PUBREC (thanks to @muneebmajeed).
* [Server] Fixed topic filter comparer on edge cases, e.g. "foo/" matching "foo/#" (thanks to @dagophil).
* [Core] Added code documentation.
Git commit: $gitCommit
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</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>
<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 Blazor</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" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="NETStandard.Library" version="2.0.0" />
@@ -29,8 +48,20 @@
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</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">
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.8" />
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.10" />
</group>
</dependencies>
</metadata>
@@ -39,21 +70,33 @@
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.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\"/>
<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 -->
<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\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\"/>
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet\bin\Release\net461\MQTTnet.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet\bin\Release\net461\MQTTnet.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
</package>
+39 -20
View File
@@ -12,21 +12,36 @@ Write-Host "Nuget version = $nugetVersion"
Write-Host "MSBuild path = $msbuild"
Write-Host
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
.\nuget.exe restore ..\MQTTnet.sln
# Build and execute tests
&$msbuild ..\Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
&$msbuild ..\Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
vstest.console.exe ..\Tests\MQTTnet.Core.Tests\bin\Release\netcoreapp3.1\MQTTnet.Tests.dll
vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.Tests.dll
# Build the core library
&$msbuild ..\Source\MQTTnet\MQTTnet.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\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="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"
# 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="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# 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="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="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"
# Build the Managed Client extension
@@ -34,6 +49,7 @@ Write-Host
&$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="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"
# Build the WebSocket4Net extension
@@ -41,14 +57,17 @@ Write-Host
&$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="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"
# Create NuGet packages.
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
$gitCommit = git log -1 --format=%h
Copy-Item MQTTnet.nuspec -Destination MQTTnet.nuspec.old -Force
(Get-Content MQTTnet.nuspec) -replace '\$gitCommit', $gitCommit | Set-Content MQTTnet.nuspec
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
(Get-Content MQTTnet.AspNetCore.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.AspNetCore.nuspec
Copy-Item MQTTnet.Extensions.Rpc.nuspec -Destination MQTTnet.Extensions.Rpc.nuspec.old -Force
@@ -59,13 +78,13 @@ Copy-Item MQTTnet.Extensions.WebSocket4Net.nuspec -Destination MQTTnet.Extension
(Get-Content MQTTnet.Extensions.WebSocket4Net.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.WebSocket4Net.nuspec
New-Item -ItemType Directory -Force -Path .\NuGet
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.NETStandard.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.WebSocket4Net.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.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.ManagedClient.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.WebSocket4Net.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
Move-Item MQTTnet.nuspec.old -Destination MQTTnet.nuspec -Force
Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force
Move-Item MQTTnet.Extensions.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force
@@ -76,10 +95,10 @@ Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
####################################################################
# Build MQTTnet.Server Portable
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --framework net5.0
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\publish"
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Portable-v$nugetVersion.zip"
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\netcoreapp3.1\publish"
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Portable-v$nugetVersion.zip"
If(Test-path $destination) {Remove-item $destination}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
@@ -87,10 +106,10 @@ If(Test-path $destination) {Remove-item $destination}
####################################################################
# Build MQTTnet.Server Linux-x64
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-x64
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-x64 --framework net5.0
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\linux-x64\publish"
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-x64-v$nugetVersion.zip"
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\netcoreapp3.1\linux-x64\publish"
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-x64-v$nugetVersion.zip"
If(Test-path $destination) {Remove-item $destination}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
@@ -98,10 +117,10 @@ If(Test-path $destination) {Remove-item $destination}
####################################################################
# Build MQTTnet.Server Linux-ARM
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-arm
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-arm --framework net5.0
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\linux-ARM\publish"
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-ARM-v$nugetVersion.zip"
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\netcoreapp3.1\linux-ARM\publish"
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-ARM-v$nugetVersion.zip"
If(Test-path $destination) {Remove-item $destination}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
@@ -109,10 +128,10 @@ If(Test-path $destination) {Remove-item $destination}
####################################################################
# Build MQTTnet.Server Windows-x64
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime win-x64
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime win-x64 --framework net5.0
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\win-x64\publish"
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Windows-x64-v$nugetVersion.zip"
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\netcoreapp3.1\win-x64\publish"
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Windows-x64-v$nugetVersion.zip"
If(Test-path $destination) {Remove-item $destination}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
+1 -1
View File
@@ -7,7 +7,7 @@ foreach ($file in $files)
{
Write-Host "Uploading: " $file
.\nuget.exe push $file.Fullname $apiKey -NoSymbols -Source https://api.nuget.org/v3/index.json
.\nuget.exe push $file.Fullname $apiKey -Source https://api.nuget.org/v3/index.json
}
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
+2 -2
View File
@@ -1,9 +1,9 @@
# Import codeSigningKey.pfx
In order to import the key for code signing on a new developer machine use the following command within the VS developer command line:
> sn –i codeSigningKey.pfx VS_KEY_EFCA4C5B6DFD4B4F
sn –i .\codeSigningKey.pfx VS_KEY_62CA73019ED23333
The container name may be different.
# Check if the assembly has a strong name
> sn -vf MQTTnet.dll
sn -vf MQTTnet.dll
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

+239
View File
@@ -0,0 +1,239 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="MQTT.svg">
<defs
id="defs2">
<filter
inkscape:label="Blur Double"
inkscape:menu="Blurs"
inkscape:menu-tooltip="Overlays two copies with different blur amounts and modifiable blend and composite"
style="color-interpolation-filters:sRGB;"
id="filter3801">
<feGaussianBlur
stdDeviation="5"
result="fbSourceGraphic"
id="feGaussianBlur3793" />
<feGaussianBlur
stdDeviation="0.01"
in="SourceGraphic"
result="result1"
id="feGaussianBlur3795" />
<feComposite
in2="result1"
operator="arithmetic"
in="fbSourceGraphic"
k2="0.5"
k3="0.5"
result="result2"
id="feComposite3797" />
<feBlend
in2="fbSourceGraphic"
mode="normal"
result="result3"
id="feBlend3799" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.24748737"
inkscape:cx="955.72999"
inkscape:cy="295.38958"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3840"
inkscape:window-height="2066"
inkscape:window-x="2989"
inkscape:window-y="-11"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
ry="50"
rx="50"
style="fill:#000000;stroke-width:0.26458332;filter:url(#filter3801)"
y="92.501205"
x="56.367012"
height="512"
width="512"
id="rect3791"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<rect
id="rect3713"
width="512"
height="512"
x="53.721176"
y="88.797035"
style="fill:#aa0000;stroke-width:0.26458332"
rx="50"
ry="50"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<rect
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:0.28100395"
id="rect3806"
width="143.25298"
height="9.0714283"
x="270.81995"
y="554.02386"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<path
inkscape:connector-curvature="0"
id="path4638"
d="m 494.14104,142.00092 -5.35736,41.28822 67.77684,374.38977 a 263.46279,229.17651 36.835702 0 1 4.98278,-0.4605 263.46279,229.17651 36.835702 0 1 7.77403,0.0471 z"
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:0.59952348"
inkscape:transform-center-x="-28.818481"
inkscape:transform-center-y="146.97441"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<path
style="fill:#d40000;stroke-width:1.76103246"
d="m 2138.1582,1411.377 a 995.76488,866.17897 0 0 0 -842.3984,854.3418 995.76488,866.17897 0 0 0 0.2988,5.0097 h 653.123 c 104.693,0 188.9766,-84.2836 188.9766,-188.9765 z"
transform="scale(0.26458333)"
id="path3715-5-8"
inkscape:connector-curvature="0"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<ellipse
style="fill:#d40000;stroke-width:0.06901014"
id="path3715-5"
cx="492.58557"
cy="170.58017"
rx="39.021355"
ry="33.94323"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<path
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:2.26591563"
d="M 464.66602,532.89453 542.01562,669.92969 1595.373,1648.873 a 995.76487,866.17896 0 0 1 14.0293,-12.6835 995.76487,866.17896 0 0 1 23.6231,-17.4727 z"
id="rect3806-2"
inkscape:connector-curvature="0"
transform="scale(0.26458333)"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="102.34985"
y="320.75201"
id="text3774"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001"><tspan
sodipodi:role="line"
id="tspan3772"
x="102.34985"
y="320.75201"
style="font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332">MQTT</tspan></text>
<ellipse
ry="33.94323"
rx="39.021355"
cy="148.56271"
cx="124.47787"
id="ellipse3768"
style="fill:#d40000;stroke-width:0.06901014"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<ellipse
style="fill:#d40000;stroke-width:0.06901014"
id="ellipse3770"
cx="234.9953"
cy="556.91571"
rx="39.021355"
ry="33.94323"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001" />
<text
id="text3778"
y="474.73837"
x="194.57605"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"
inkscape:export-xdpi="2.6500001"
inkscape:export-ydpi="2.6500001"><tspan
style="font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332"
y="474.73837"
x="194.57605"
id="tspan3776"
sodipodi:role="line">net</tspan></text>
<rect
ry="50"
rx="50"
style="fill:#aa0000;stroke-width:0.26458332"
y="97.349655"
x="-672.18286"
height="512"
width="512"
id="rect4642"
inkscape:export-xdpi="6.3499999"
inkscape:export-ydpi="6.3499999" />
<path
inkscape:connector-curvature="0"
id="path4648"
d="m -160.18302,381.97945 a 263.46279,229.17652 0 0 0 -222.88457,226.0446 263.46279,229.17652 0 0 0 0.0791,1.32549 h 172.80546 c 27.70002,0 50.00005,-22.30004 50.00005,-50.00004 z"
style="fill:#d40000;stroke-width:0.46593982"
inkscape:export-xdpi="6.3499999"
inkscape:export-ydpi="6.3499999" />
<text
id="text4656"
y="329.30466"
x="-639.42944"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"
inkscape:export-xdpi="6.3499999"
inkscape:export-ydpi="6.3499999"><tspan
style="font-weight:bold;font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332"
y="329.30466"
x="-639.42944"
id="tspan4654"
sodipodi:role="line">MQTT</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="-550.90747"
y="482.23267"
id="text4664"
inkscape:export-xdpi="6.3499999"
inkscape:export-ydpi="6.3499999"><tspan
sodipodi:role="line"
id="tspan4662"
x="-550.90747"
y="482.23267"
style="font-weight:bold;font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332">net</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
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
of this software and associated documentation files (the "Software"), to deal
+64 -28
View File
@@ -9,8 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.UniversalWindows", "Tests\MQTTnet.TestApp.UniversalWindows\MQTTnet.TestApp.UniversalWindows.csproj", "{FF1F72D6-9524-4422-9497-3CC0002216ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
@@ -20,7 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.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\upload.ps1 = Build\upload.ps1
EndProjectSection
@@ -28,6 +25,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
ProjectSection(SolutionItems) = preProject
.bettercodehub.yml = .bettercodehub.yml
.editorconfig = .editorconfig
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
@@ -53,6 +51,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQ
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{2BD01D53-4CA5-4142-BE8D-313876395E3E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{A56E3128-1639-4F31-873A-325E14BB6295}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Server", "Tests\MQTTnet.Test.BlazorApp\Server\MQTTnet.Test.BlazorApp.Server.csproj", "{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Client", "Tests\MQTTnet.Test.BlazorApp\Client\MQTTnet.Test.BlazorApp.Client.csproj", "{D260D63D-7902-4C55-9665-84C5CACBBB24}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Shared", "Tests\MQTTnet.Test.BlazorApp\Shared\MQTTnet.Test.BlazorApp.Shared.csproj", "{DDB069BA-6E1A-48C7-B374-5D903B553CAD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -81,29 +89,6 @@ Global
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.ActiveCfg = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Build.0 = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Deploy.0 = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.ActiveCfg = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Build.0 = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Deploy.0 = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.ActiveCfg = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Build.0 = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Deploy.0 = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|Any CPU.Build.0 = Release|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.ActiveCfg = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Build.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Deploy.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.ActiveCfg = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Build.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Deploy.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.ActiveCfg = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Build.0 = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Deploy.0 = Release|x86
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -264,13 +249,60 @@ Global
{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.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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{FF1F72D6-9524-4422-9497-3CC0002216ED} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
@@ -279,8 +311,12 @@ Global
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {A56E3128-1639-4F31-873A-325E14BB6295}
{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
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
+2 -1
View File
@@ -11,4 +11,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsub/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+30 -12
View File
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://github.com/chkr1011/MQTTnet/blob/master/Images/Logo_128x128.png?raw=true" width="128">
<img src="https://github.com/chkr1011/MQTTnet/blob/master/Images/icon_det_256.png?raw=true" width="196">
<br/>
<br/>
</p>
@@ -7,8 +7,7 @@
[![NuGet Badge](https://buildstats.info/nuget/MQTTnet)](https://www.nuget.org/packages/MQTTnet)
[![Build status](https://ci.appveyor.com/api/projects/status/ycit86voxfevm2aa/branch/master?svg=true)](https://ci.appveyor.com/project/chkr1011/mqttnet)
[![BCH compliance](https://bettercodehub.com/edge/badge/chkr1011/MQTTnet?branch=master)](https://bettercodehub.com/)
[![OpenCollective](https://opencollective.com/mqttnet/backers/badge.svg)](https://opencollective.com/mqttnet)
[![OpenCollective](https://opencollective.com/mqttnet/sponsors/badge.svg)](https://opencollective.com/mqttnet) [![Join the chat at https://gitter.im/MQTTnet/community](https://badges.gitter.im/MQTTnet/community.svg)](https://gitter.im/MQTTnet/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join the chat at https://gitter.im/MQTTnet/community](https://badges.gitter.im/MQTTnet/community.svg)](https://gitter.im/MQTTnet/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/chkr1011/MQTTnet/master/LICENSE)
# MQTTnet
@@ -20,14 +19,14 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
### General
* Async support
* TLS 1.2 support for client and server (but not UWP servers)
* TLS support for client and server (but not UWP servers)
* Extensible communication channels (e.g. In-Memory, TCP, TCP+TLS, WS)
* Lightweight (only the low level implementation of MQTT, no overhead)
* Performance optimized (processing ~70.000 messages / second)*
* Uniform API across all supported versions of the MQTT protocol
* Interfaces included for mocking and testing
* Access to internal trace messages
* Unit tested (~210 tests)
* Unit tested (~250 tests)
* 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_.
@@ -35,7 +34,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
### Client
* 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.
* Rx support (via another project)
* Compatible with Microsoft Azure IoT Hub
@@ -65,14 +64,32 @@ _MQTTnet Server_ is a standalone cross platform MQTT server (like mosquitto) bas
## Supported frameworks
* .NET 5.0+
* .NET Standard 1.3+
* .NET Core 1.1+
* .NET Core App 1.1+
* .NET Framework 4.5.2+ (x86, x64, AnyCPU)
* .NET Framework 4.5.2+
* Mono 5.2+
* Universal Windows Platform (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU, Windows 10 IoT Core)
* Universal Windows Platform (UWP) 10.0.10240+ (Windows 10 IoT Core)
* Xamarin.Android 7.5+
* Xamarin.iOS 10.14+
* Blazor WebAssembly 3.2.0+
## Supported platforms
* x86
* x64
* AnyCPU
* ARM
## Supported OS
* Windows
* Windows 10 IoT Core
* Linux (Ubuntu, Raspbian etc.)
* macOS
* Android
* iOS
## Supported MQTT versions
@@ -93,17 +110,18 @@ Please find examples and the documentation at the Wiki of this repository (<http
If you want to contribute to this project just create a pull request. But only pull requests which are matching the code style of this library will be accepted. Before creating a pull request please have a look at the library to get an overview of the required style.
Also additions and updates in the Wiki are welcome.
**This project, like all projects requires time and money. If you feel compelled to support the development team, you can do so through Open Collective (https://opencollective.com/mqttnet)**.
## References
This library is used in the following projects:
* Azure Functions MQTT Bindings, [CaseOnline.Azure.WebJobs.Extensions.Mqtt](https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt/)
* Azure Functions MQTT Bindings, <https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt>)
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
* MQTT Client Rx (Managed Client Wrapper for Reactive Extensions, <https://github.com/mmuecke/RxMQTTnet>)
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
* MQTTnet App (Cross platform client application for MQTT debugging, inspection etc., <https://github.com/chkr1011/MQTTnet.App>)
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
* SparkplugNet (Sparkplug library for .Net, <https://github.com/SeppPenner/SparkplugNet>)
Further projects using this project can be found under https://github.com/chkr1011/MQTTnet/network/dependents.
@@ -113,7 +131,7 @@ If you use this library and want to see your project here please create a pull r
MIT License
MQTTnet Copyright (c) 2016-2019 Christian Kratky
MQTTnet Copyright (c) 2016-2021 Christian Kratky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -1,17 +1,15 @@
using System;
using System.Net;
using MQTTnet.Adapter;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Client.Tcp;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using System;
using System.Net;
namespace MQTTnet.AspNetCore.Client
{
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
{
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger)
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
@@ -1,13 +1,13 @@
using System;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Features;
using MQTTnet.Exceptions;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipelines;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Features;
using MQTTnet.Exceptions;
namespace MQTTnet.AspNetCore.Client.Tcp
{
@@ -40,8 +40,11 @@ namespace MQTTnet.AspNetCore.Client.Tcp
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
_receiver = new SocketReceiver(_socket, PipeScheduler.ThreadPool);
}
#if NETCOREAPP3_1 || NET5_0
public override ValueTask DisposeAsync()
#else
public Task DisposeAsync()
#endif
{
IsConnected = false;
@@ -50,8 +53,15 @@ namespace MQTTnet.AspNetCore.Client.Tcp
_socket?.Dispose();
#if NETCOREAPP3_1 || NET5_0
return base.DisposeAsync();
}
#else
return Task.CompletedTask;
}
#endif
public async Task StartAsync()
{
@@ -1,14 +1,13 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using MQTTnet.Server;
using System.Collections.Generic;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ApplicationBuilderExtensions
{
[Obsolete("This class is obsolete and will be removed in a future version. The recommended alternative is to use MapMqtt inside Microsoft.AspNetCore.Builder.UseEndpoints(...).")]
public static IApplicationBuilder UseMqttEndpoint(this IApplicationBuilder app, string path = "/mqtt")
{
app.UseWebSockets();
@@ -24,7 +23,7 @@ namespace MQTTnet.AspNetCore
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
{
subProtocol = SelectSubProtocol(requestedSubProtocolValues);
subProtocol = MqttSubProtocolSelector.SelectSubProtocol(requestedSubProtocolValues);
}
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
@@ -37,14 +36,6 @@ namespace MQTTnet.AspNetCore
return app;
}
public static string SelectSubProtocol(IList<string> requestedSubProtocolValues)
{
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
return requestedSubProtocolValues
.OrderByDescending(p => p.Length)
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
}
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
{
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Connections;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ConnectionBuilderExtensions
{
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
#if NETCOREAPP3_1
using System;
#endif
namespace MQTTnet.AspNetCore.Extensions
{
public static class ConnectionRouteBuilderExtensions
{
#if NETCOREAPP3_1
[Obsolete("This class is obsolete and will be removed in a future version. The recommended alternative is to use MapMqtt inside Microsoft.AspNetCore.Builder.UseEndpoints(...).")]
#endif
#if NETCOREAPP3_1 || NETCOREAPP2_1 || NETSTANDARD
public static void MapMqtt(this ConnectionsRouteBuilder connection, PathString path)
{
connection.MapConnectionHandler<MqttConnectionHandler>(path, options =>
{
options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol;
});
}
#endif
}
}
@@ -0,0 +1,21 @@
#if NETCOREAPP3_1 || NET5_0
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
namespace MQTTnet.AspNetCore
{
public static class EndpointRouterExtensions
{
public static void MapMqtt(this IEndpointRouteBuilder endpoints, string pattern)
{
endpoints.MapConnectionHandler<MqttConnectionHandler>(pattern, options =>
{
options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol;
});
}
}
}
#endif
@@ -5,7 +5,7 @@ using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ReaderExtensions
{
@@ -80,7 +80,7 @@ namespace MQTTnet.AspNetCore
headerLength = 0;
bodyLength = 0;
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory();
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory().Span;
do
{
@@ -88,7 +88,7 @@ namespace MQTTnet.AspNetCore
{
return false;
}
encodedByte = temp.Span[index];
encodedByte = temp[index];
index++;
value += (byte)(encodedByte & 127) * multiplier;
@@ -3,17 +3,17 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Server;
using MQTTnet.Implementations;
using MQTTnet.Server;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, IMqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
services.AddSingleton(options);
services.AddHostedMqttServer();
@@ -23,7 +23,8 @@ namespace MQTTnet.AspNetCore
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
{
services.AddSingleton<IMqttServerOptions>(s => {
services.AddSingleton<IMqttServerOptions>(s =>
{
var builder = new MqttServerOptionsBuilder();
configure(builder);
return builder.Build();
@@ -36,7 +37,8 @@ namespace MQTTnet.AspNetCore
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
{
services.AddSingleton<IMqttServerOptions>(s => {
services.AddSingleton<IMqttServerOptions>(s =>
{
var builder = new AspNetMqttServerOptionsBuilder(s);
configure(builder);
return builder.Build();
@@ -60,14 +62,12 @@ namespace MQTTnet.AspNetCore
private static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
{
var logger = new MqttNetLogger();
var childLogger = logger.CreateChildLogger();
services.AddSingleton<IMqttNetLogger>(logger);
services.AddSingleton(childLogger);
services.AddSingleton<MqttHostedServer>();
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
services.AddSingleton<IMqttServer>(s => s.GetService<MqttHostedServer>());
return services;
}
@@ -1,24 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<Product />
<Company />
<Authors />
<PackageId />
<LangVersion>7.2</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.0.3" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.1" />
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' ">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1' and '$(TargetFramework)' != 'net5.0' ">
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
@@ -10,11 +10,19 @@ using System.IO.Pipelines;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.AspNetCore.Extensions;
using MQTTnet.Internal;
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)
{
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
@@ -25,18 +33,20 @@ namespace MQTTnet.AspNetCore
_input = Connection.Transport.Input;
_output = Connection.Transport.Output;
}
_reader = new SpanBasedMqttPacketBodyReader();
}
private PipeReader _input;
private PipeWriter _output;
private readonly SpanBasedMqttPacketBodyReader _reader;
public string Endpoint
{
get
{
#if NETCOREAPP3_1
if (Connection?.RemoteEndPoint != null)
{
return Connection.RemoteEndPoint.ToString();
}
#endif
var connection = Http?.HttpContext?.Connection;
if (connection == null)
{
@@ -51,18 +61,17 @@ namespace MQTTnet.AspNetCore
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
private IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
public ConnectionContext Connection { get; }
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
public long BytesSent { get; set; }
public long BytesReceived { get; set; }
public Action ReadingPacketStartedCallback { get; set; }
public Action ReadingPacketCompletedCallback { get; set; }
public bool IsReadingPacket { get; private set; }
private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
@@ -83,7 +92,7 @@ namespace MQTTnet.AspNetCore
return Task.CompletedTask;
}
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
public async Task<MqttBasePacket> ReceivePacketAsync(CancellationToken cancellationToken)
{
var input = Connection.Transport.Input;
@@ -119,7 +128,7 @@ namespace MQTTnet.AspNetCore
else
{
// we did receive something but the message is not yet complete
ReadingPacketStartedCallback?.Invoke();
IsReadingPacket = true;
}
}
else if (readResult.IsCompleted)
@@ -136,9 +145,16 @@ namespace MQTTnet.AspNetCore
}
}
}
catch (Exception e)
{
// completing the channel makes sure that there is no more data read after a protocol error
_input?.Complete(e);
_output?.Complete(e);
throw;
}
finally
{
ReadingPacketCompletedCallback?.Invoke();
IsReadingPacket = false;
}
cancellationToken.ThrowIfCancellationRequested();
@@ -151,26 +167,21 @@ namespace MQTTnet.AspNetCore
BytesSent = 0;
}
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
public async Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
{
var formatter = PacketFormatterAdapter;
await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
using (await _writerLock.WaitAsync(cancellationToken).ConfigureAwait(false))
{
var buffer = formatter.Encode(packet);
var msg = buffer.AsMemory();
var output = _output;
msg.CopyTo(output.GetMemory(msg.Length));
BytesSent += msg.Length;
var result = await output.WriteAsync(msg, cancellationToken).ConfigureAwait(false);
if (result.IsCompleted)
{
BytesSent += msg.Length;
}
PacketFormatterAdapter.FreeBuffer();
output.Advance(msg.Length);
await output.FlushAsync().ConfigureAwait(false);
}
finally
{
_writerSemaphore.Release();
}
}
@@ -14,14 +14,15 @@ namespace MQTTnet.AspNetCore
private readonly IMqttServerOptions _options;
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));
}
public Task StartAsync(CancellationToken cancellationToken)
{
return StartAsync(_options);
_ = StartAsync(_options);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
namespace MQTTnet.AspNetCore
{
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)
{
if (requestedSubProtocolValues == null) throw new ArgumentNullException(nameof(requestedSubProtocolValues));
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
return requestedSubProtocolValues
.OrderByDescending(p => p.Length)
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
}
}
}
@@ -1,24 +1,22 @@
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Server;
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
namespace MQTTnet.AspNetCore
{
public class MqttWebSocketServerAdapter : IMqttServerAdapter
public sealed class MqttWebSocketServerAdapter : IMqttServerAdapter
{
private readonly IMqttNetChildLogger _logger;
readonly IMqttNetLogger _rootLogger;
public MqttWebSocketServerAdapter(IMqttNetChildLogger logger)
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
@@ -38,7 +36,7 @@ namespace MQTTnet.AspNetCore
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}";
var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false);
try
{
@@ -51,7 +49,7 @@ namespace MQTTnet.AspNetCore
var formatter = new MqttPacketFormatterAdapter(writer);
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, null, _rootLogger))
{
await clientHandler(channelAdapter).ConfigureAwait(false);
}
@@ -8,9 +8,9 @@ namespace MQTTnet.AspNetCore
{
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
{
private ReadOnlyMemory<byte> _buffer;
ReadOnlyMemory<byte> _buffer;
private int _offset;
int _offset;
public void SetBuffer(ReadOnlyMemory<byte> buffer)
{
@@ -38,16 +38,6 @@ namespace MQTTnet.AspNetCore
{
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()
{
@@ -121,5 +111,19 @@ namespace MQTTnet.AspNetCore
{
_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
{
private readonly ArrayPool<byte> _pool;
readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create();
public SpanBasedMqttPacketWriter()
{
_pool = ArrayPool<byte>.Create();
Reset(0);
}
private byte[] _buffer;
private int _position;
byte[] _buffer;
int _position;
public int Length { get; set; }
@@ -64,7 +63,6 @@ namespace MQTTnet.AspNetCore
GrowIfNeeded(propertyWriter.Length);
Write(propertyWriter.GetBuffer(), 0, propertyWriter.Length);
Commit(propertyWriter.Length);
}
public void Write(byte[] payload, int start, int length)
@@ -113,7 +111,7 @@ namespace MQTTnet.AspNetCore
Commit(payload.Length);
}
private void Commit(int count)
void Commit(int count)
{
if (_position == Length)
{
@@ -123,7 +121,7 @@ namespace MQTTnet.AspNetCore
_position += count;
}
private void GrowIfNeeded(int requiredAdditional)
void GrowIfNeeded(int requiredAdditional)
{
var requiredTotal = _position + requiredAdditional;
if (_buffer.Length >= requiredTotal)
@@ -1,31 +1,49 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Client;
namespace MQTTnet.Extensions.ManagedClient
{
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
{
bool IsStarted { get; }
bool IsConnected { get; }
int PendingApplicationMessagesCount { get; }
IManagedMqttClientOptions Options { get; }
/// <summary>
/// Gets the internally used MQTT client.
/// This property should be used with caution because manipulating the internal client might break the managed client.
/// </summary>
IMqttClient InternalClient { get; }
bool IsStarted { get; }
bool IsConnected { get; }
int PendingApplicationMessagesCount { get; }
IManagedMqttClientOptions Options { get; }
IMqttClientConnectedHandler ConnectedHandler { get; set; }
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
Task StartAsync(IManagedMqttClientOptions options);
Task StopAsync();
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
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 PublishAsync(ManagedMqttApplicationMessage applicationMessages);
@@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</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>
<Product />
<Company />
<Authors />
<PackageId />
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
@@ -23,6 +26,10 @@
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Client;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Publishing;
@@ -13,56 +8,74 @@ using MQTTnet.Exceptions;
using MQTTnet.Internal;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public class ManagedMqttClient : IManagedMqttClient
public class ManagedMqttClient : Disposable, IManagedMqttClient
{
private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
private readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
private readonly HashSet<string> _unsubscriptions = new HashSet<string>();
readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
private readonly IMqttClient _mqttClient;
private readonly IMqttNetChildLogger _logger;
/// <summary>
/// The subscriptions are managed in 2 separate buckets:
/// <see cref="_subscriptions"/> and <see cref="_unsubscriptions"/> are processed during normal operation
/// and are moved to the <see cref="_reconnectSubscriptions"/> when they get processed. They can be accessed by
/// 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"/>.
/// </summary>
readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
readonly HashSet<string> _unsubscriptions = new HashSet<string>();
readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0);
private CancellationTokenSource _connectionCancellationToken;
private CancellationTokenSource _publishingCancellationToken;
private Task _maintainConnectionTask;
readonly IMqttNetScopedLogger _logger;
private ManagedMqttClientStorageManager _storageManager;
readonly AsyncLock _messageQueueLock = new AsyncLock();
private bool _disposed;
private bool _subscriptionsNotPushed;
CancellationTokenSource _connectionCancellationToken;
CancellationTokenSource _publishingCancellationToken;
Task _maintainConnectionTask;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
ManagedMqttClientStorageManager _storageManager;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
{
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
InternalClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
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 => InternalClient.IsConnected;
public bool IsStarted => _connectionCancellationToken != null;
public IMqttClient InternalClient { get; }
public int PendingApplicationMessagesCount => _messageQueue.Count;
public IManagedMqttClientOptions Options { get; private set; }
public IMqttClientConnectedHandler ConnectedHandler
{
get => _mqttClient.ConnectedHandler;
set => _mqttClient.ConnectedHandler = value;
get => InternalClient.ConnectedHandler;
set => InternalClient.ConnectedHandler = value;
}
public IMqttClientDisconnectedHandler DisconnectedHandler
{
get => _mqttClient.DisconnectedHandler;
set => _mqttClient.DisconnectedHandler = value;
get => InternalClient.DisconnectedHandler;
set => InternalClient.DisconnectedHandler = value;
}
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
{
get => _mqttClient.ApplicationMessageReceivedHandler;
set => _mqttClient.ApplicationMessageReceivedHandler = value;
get => InternalClient.ApplicationMessageReceivedHandler;
set => InternalClient.ApplicationMessageReceivedHandler = value;
}
public IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
@@ -80,18 +93,13 @@ namespace MQTTnet.Extensions.ManagedClient
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.CleanSession)
{
throw new NotSupportedException("The managed client does not support existing sessions.");
}
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
Options = options;
if (Options.Storage != null)
if (options.Storage != null)
{
_storageManager = new ManagedMqttClientStorageManager(Options.Storage);
_storageManager = new ManagedMqttClientStorageManager(options.Storage);
var messages = await _storageManager.LoadQueuedMessagesAsync().ConfigureAwait(false);
foreach (var message in messages)
@@ -100,10 +108,12 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
_connectionCancellationToken = new CancellationTokenSource();
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
_connectionCancellationToken = cancellationTokenSource;
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
_maintainConnectionTask.Forget(_logger);
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(cancellationToken), cancellationToken);
_maintainConnectionTask.RunInBackground(_logger);
_logger.Info("Started");
}
@@ -124,6 +134,11 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
public Task PingAsync(CancellationToken cancellationToken)
{
return InternalClient.PingAsync(cancellationToken);
}
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
{
ThrowIfDisposed();
@@ -139,6 +154,7 @@ namespace MQTTnet.Extensions.ManagedClient
ThrowIfDisposed();
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
if (Options == null) throw new InvalidOperationException("call StartAsync before publishing messages");
MqttTopicValidator.ThrowIfInvalid(applicationMessage.ApplicationMessage.Topic);
@@ -147,7 +163,7 @@ namespace MQTTnet.Extensions.ManagedClient
try
{
lock (_messageQueue)
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
{
if (_messageQueue.Count >= Options.MaxPendingMessages)
{
@@ -167,6 +183,16 @@ namespace MQTTnet.Extensions.ManagedClient
}
_messageQueue.Enqueue(applicationMessage);
if (_storageManager != null)
{
if (removedMessage != null)
{
await _storageManager.RemoveAsync(removedMessage).ConfigureAwait(false);
}
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
}
}
}
finally
@@ -181,19 +207,9 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
if (_storageManager != null)
{
if (removedMessage != null)
{
await _storageManager.RemoveAsync(removedMessage).ConfigureAwait(false);
}
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
}
}
public Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
public Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters)
{
ThrowIfDisposed();
@@ -204,10 +220,12 @@ namespace MQTTnet.Extensions.ManagedClient
foreach (var topicFilter in topicFilters)
{
_subscriptions[topicFilter.Topic] = topicFilter.QualityOfServiceLevel;
_subscriptionsNotPushed = true;
_unsubscriptions.Remove(topicFilter.Topic);
}
}
_subscriptionsQueuedSignal.Release();
return Task.FromResult(0);
}
@@ -221,47 +239,38 @@ namespace MQTTnet.Extensions.ManagedClient
{
foreach (var topic in topics)
{
if (_subscriptions.Remove(topic))
{
_unsubscriptions.Add(topic);
_subscriptionsNotPushed = true;
}
_subscriptions.Remove(topic);
_unsubscriptions.Add(topic);
}
}
_subscriptionsQueuedSignal.Release();
return Task.FromResult(0);
}
public void Dispose()
protected override void Dispose(bool disposing)
{
if (_disposed)
if (disposing)
{
return;
StopPublishing();
StopMaintainingConnection();
if (_maintainConnectionTask != null)
{
_maintainConnectionTask.GetAwaiter().GetResult();
_maintainConnectionTask = null;
}
_messageQueue.Dispose();
_messageQueueLock.Dispose();
InternalClient.Dispose();
_subscriptionsQueuedSignal.Dispose();
}
_disposed = true;
StopPublishing();
StopMaintainingConnection();
if (_maintainConnectionTask != null)
{
Task.WaitAny(_maintainConnectionTask);
_maintainConnectionTask = null;
}
_mqttClient.Dispose();
base.Dispose(disposing);
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(ManagedMqttClient));
}
}
private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
async Task MaintainConnectionAsync(CancellationToken cancellationToken)
{
try
{
@@ -275,15 +284,22 @@ namespace MQTTnet.Extensions.ManagedClient
}
catch (Exception exception)
{
_logger.Error(exception, "Unhandled exception while maintaining connection.");
_logger.Error(exception, "Error exception while maintaining connection.");
}
finally
{
if (!_disposed)
if (!IsDisposed)
{
try
{
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
using (var disconnectTimeout = new CancellationTokenSource(Options.ClientOptions.CommunicationTimeout))
{
await InternalClient.DisconnectAsync(disconnectTimeout.Token).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
_logger.Warning("Timeout while sending DISCONNECT packet.");
}
catch (Exception exception)
{
@@ -292,14 +308,22 @@ namespace MQTTnet.Extensions.ManagedClient
_logger.Info("Stopped");
}
_reconnectSubscriptions.Clear();
lock (_subscriptions)
{
_subscriptions.Clear();
_unsubscriptions.Clear();
}
}
}
private async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
{
try
{
var connectionState = await ReconnectIfRequiredAsync().ConfigureAwait(false);
var connectionState = await ReconnectIfRequiredAsync(cancellationToken).ConfigureAwait(false);
if (connectionState == ReconnectionResult.NotConnected)
{
StopPublishing();
@@ -307,16 +331,22 @@ namespace MQTTnet.Extensions.ManagedClient
return;
}
if (connectionState == ReconnectionResult.Reconnected || _subscriptionsNotPushed)
if (connectionState == ReconnectionResult.Reconnected)
{
await PublishReconnectSubscriptionsAsync().ConfigureAwait(false);
StartPublishing();
return;
}
if (connectionState == ReconnectionResult.Recovered)
{
await SynchronizeSubscriptionsAsync().ConfigureAwait(false);
StartPublishing();
return;
}
if (connectionState == ReconnectionResult.StillConnected)
{
await Task.Delay(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
await PublishSubscriptionsAsync(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
@@ -324,19 +354,19 @@ namespace MQTTnet.Extensions.ManagedClient
}
catch (MqttCommunicationException exception)
{
_logger.Warning(exception, "Communication exception while maintaining connection.");
_logger.Warning(exception, "Communication error while maintaining connection.");
}
catch (Exception exception)
{
_logger.Error(exception, "Unhandled exception while maintaining connection.");
_logger.Error(exception, "Error exception while maintaining connection.");
}
}
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested && _mqttClient.IsConnected)
while (!cancellationToken.IsCancellationRequested && InternalClient.IsConnected)
{
// Peek at the message without dequeueing in order to prevent the
// possibility of the queue growing beyond the configured cap.
@@ -346,7 +376,7 @@ namespace MQTTnet.Extensions.ManagedClient
// of the messages, the DropOldestQueuedMessage strategy would
// be unable to know which message is actually the oldest and would
// instead drop the first item in the queue.
var message = _messageQueue.PeekAndWait();
var message = _messageQueue.PeekAndWait(cancellationToken);
if (message == null)
{
continue;
@@ -362,7 +392,7 @@ namespace MQTTnet.Extensions.ManagedClient
}
catch (Exception exception)
{
_logger.Error(exception, "Unhandled exception while publishing queued application messages.");
_logger.Error(exception, "Error while publishing queued application messages.");
}
finally
{
@@ -370,14 +400,14 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
private async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
{
Exception transmitException = null;
try
{
await _mqttClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
await InternalClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false)) //lock to avoid conflict with this.PublishAsync
{
// While publishing this message, this.PublishAsync could have booted this
// message off the queue to make room for another (when using a cap
@@ -386,18 +416,18 @@ namespace MQTTnet.Extensions.ManagedClient
// it from the queue. If not, that means this.PublishAsync has already
// removed it, in which case we don't want to do anything.
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
}
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
}
catch (MqttCommunicationException exception)
{
transmitException = exception;
_logger.Warning(exception, $"Publishing application ({message.Id}) message failed.");
_logger.Warning(exception, "Publishing application message ({0}) failed.", message.Id);
if (message.ApplicationMessage.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
@@ -408,21 +438,21 @@ namespace MQTTnet.Extensions.ManagedClient
//contradict the expected behavior of QoS 1 and 2, that's also true
//for the usage of a message queue cap, so it's still consistent
//with prior behavior in that way.
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false)) //lock to avoid conflict with this.PublishAsync
{
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
}
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
}
}
catch (Exception exception)
{
transmitException = exception;
_logger.Error(exception, $"Unhandled exception while publishing application message ({message.Id}).");
_logger.Error(exception, "Error while publishing application message ({0}).", message.Id);
}
finally
{
@@ -435,64 +465,99 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
private async Task SynchronizeSubscriptionsAsync()
async Task PublishSubscriptionsAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
_logger.Info("Synchronizing subscriptions");
var endTime = DateTime.UtcNow + timeout;
List<TopicFilter> subscriptions;
HashSet<string> unsubscriptions;
lock (_subscriptions)
while (await _subscriptionsQueuedSignal.WaitAsync(GetRemainingTime(endTime), cancellationToken).ConfigureAwait(false))
{
subscriptions = _subscriptions.Select(i => new TopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
List<MqttTopicFilter> subscriptions;
HashSet<string> unsubscriptions;
unsubscriptions = new HashSet<string>(_unsubscriptions);
_unsubscriptions.Clear();
_subscriptionsNotPushed = false;
}
if (!subscriptions.Any() && !unsubscriptions.Any())
{
return;
}
try
{
if (unsubscriptions.Any())
lock (_subscriptions)
{
await _mqttClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false);
subscriptions = _subscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
_subscriptions.Clear();
unsubscriptions = new HashSet<string>(_unsubscriptions);
_unsubscriptions.Clear();
}
if (subscriptions.Any())
if (!subscriptions.Any() && !unsubscriptions.Any())
{
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
continue;
}
}
catch (Exception exception)
{
_logger.Warning(exception, "Synchronizing subscriptions failed.");
_subscriptionsNotPushed = true;
var synchronizingSubscriptionsFailedHandler = SynchronizingSubscriptionsFailedHandler;
if (SynchronizingSubscriptionsFailedHandler != null)
_logger.Verbose("Publishing {0} subscriptions and {1} unsubscriptions)", subscriptions.Count, unsubscriptions.Count);
foreach (var unsubscription in unsubscriptions)
{
await synchronizingSubscriptionsFailedHandler.HandleSynchronizingSubscriptionsFailedAsync(new ManagedProcessFailedEventArgs(exception)).ConfigureAwait(false);
_reconnectSubscriptions.Remove(unsubscription);
}
foreach (var subscription in subscriptions)
{
_reconnectSubscriptions[subscription.Topic] = subscription.QualityOfServiceLevel;
}
try
{
if (unsubscriptions.Any())
{
await InternalClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false);
}
if (subscriptions.Any())
{
await InternalClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
}
}
catch (Exception exception)
{
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
}
}
}
private async Task<ReconnectionResult> ReconnectIfRequiredAsync()
async Task PublishReconnectSubscriptionsAsync()
{
if (_mqttClient.IsConnected)
_logger.Info("Publishing subscriptions at reconnect");
try
{
if (_reconnectSubscriptions.Any())
{
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value });
await InternalClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
}
}
catch (Exception exception)
{
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
}
}
async Task HandleSubscriptionExceptionAsync(Exception exception)
{
_logger.Warning(exception, "Synchronizing subscriptions failed.");
var synchronizingSubscriptionsFailedHandler = SynchronizingSubscriptionsFailedHandler;
if (SynchronizingSubscriptionsFailedHandler != null)
{
await synchronizingSubscriptionsFailedHandler.HandleSynchronizingSubscriptionsFailedAsync(new ManagedProcessFailedEventArgs(exception)).ConfigureAwait(false);
}
}
async Task<ReconnectionResult> ReconnectIfRequiredAsync(CancellationToken cancellationToken)
{
if (InternalClient.IsConnected)
{
return ReconnectionResult.StillConnected;
}
try
{
await _mqttClient.ConnectAsync(Options.ClientOptions).ConfigureAwait(false);
return ReconnectionResult.Reconnected;
var result = await InternalClient.ConnectAsync(Options.ClientOptions, cancellationToken).ConfigureAwait(false);
return result.IsSessionPresent ? ReconnectionResult.Recovered : ReconnectionResult.Reconnected;
}
catch (Exception exception)
{
@@ -505,32 +570,51 @@ namespace MQTTnet.Extensions.ManagedClient
return ReconnectionResult.NotConnected;
}
}
private void StartPublishing()
void StartPublishing()
{
if (_publishingCancellationToken != null)
{
StopPublishing();
}
var cts = new CancellationTokenSource();
_publishingCancellationToken = cts;
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
_publishingCancellationToken = cancellationTokenSource;
Task.Run(() => PublishQueuedMessagesAsync(cts.Token), cts.Token).Forget(_logger);
Task.Run(() => PublishQueuedMessagesAsync(cancellationToken), cancellationToken).RunInBackground(_logger);
}
private void StopPublishing()
void StopPublishing()
{
_publishingCancellationToken?.Cancel(false);
_publishingCancellationToken?.Dispose();
_publishingCancellationToken = null;
try
{
_publishingCancellationToken?.Cancel(false);
}
finally
{
_publishingCancellationToken?.Dispose();
_publishingCancellationToken = null;
}
}
private void StopMaintainingConnection()
void StopMaintainingConnection()
{
_connectionCancellationToken?.Cancel(false);
_connectionCancellationToken?.Dispose();
_connectionCancellationToken = null;
try
{
_connectionCancellationToken?.Cancel(false);
}
finally
{
_connectionCancellationToken?.Dispose();
_connectionCancellationToken = null;
}
}
static TimeSpan GetRemainingTime(DateTime endTime)
{
var remainingTime = endTime - DateTime.UtcNow;
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime;
}
}
}
}
@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Publishing;
using MQTTnet.Client.Receiving;
using MQTTnet.Protocol;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
@@ -76,39 +76,42 @@ namespace MQTTnet.Extensions.ManagedClient
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)
{
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)
{
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;
return client;
receiver.ApplicationMessageReceivedHandler = handler;
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));
@@ -120,7 +123,7 @@ namespace MQTTnet.Extensions.ManagedClient
if (client == null) throw new ArgumentNullException(nameof(client));
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)
@@ -128,7 +131,7 @@ namespace MQTTnet.Extensions.ManagedClient
if (client == null) throw new ArgumentNullException(nameof(client));
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)
@@ -138,92 +141,92 @@ namespace MQTTnet.Extensions.ManagedClient
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));
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));
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));
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));
return client.PublishAsync(builder => builder
return publisher.PublishAsync(builder => builder
.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));
return client.PublishAsync(builder => builder
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.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));
return client.PublishAsync(builder => builder
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.WithPayload(payload)
.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));
return client.PublishAsync(builder => builder
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel(qualityOfServiceLevel)
.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();
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();
return client.PublishAsync(message, CancellationToken.None);
return publisher.PublishAsync(message, CancellationToken.None);
}
}
}
@@ -1,5 +1,4 @@
using System;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
@@ -1,5 +1,4 @@
using System;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
@@ -7,8 +6,8 @@ namespace MQTTnet.Extensions.ManagedClient
{
public class ManagedMqttClientOptionsBuilder
{
private readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
private MqttClientOptionsBuilder _clientOptionsBuilder;
readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
MqttClientOptionsBuilder _clientOptionsBuilder;
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
{
@@ -69,7 +68,7 @@ namespace MQTTnet.Extensions.ManagedClient
options(_clientOptionsBuilder);
return this;
}
public ManagedMqttClientOptions Build()
{
if (_clientOptionsBuilder != null)
@@ -1,5 +1,5 @@
using System;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics;
using System;
namespace MQTTnet.Extensions.ManagedClient
{
@@ -9,7 +9,7 @@ namespace MQTTnet.Extensions.ManagedClient
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger.CreateChildLogger());
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger);
}
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory, IMqttNetLogger logger)
@@ -17,7 +17,7 @@ namespace MQTTnet.Extensions.ManagedClient
if (factory == null) throw new ArgumentNullException(nameof(factory));
if (logger == null) throw new ArgumentNullException(nameof(logger));
return new ManagedMqttClient(factory.CreateMqttClient(logger), logger.CreateChildLogger());
return new ManagedMqttClient(factory.CreateMqttClient(logger), logger);
}
}
}
@@ -4,6 +4,7 @@
{
StillConnected,
Reconnected,
Recovered,
NotConnected
}
}
@@ -0,0 +1,18 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Protocol;
namespace MQTTnet.Extensions.Rpc
{
public interface IMqttRpcClient : IDisposable
{
Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel);
Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken);
Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel);
Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken);
}
}
@@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</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>
<Product />
<Company />
<Authors />
<PackageId />
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
@@ -23,6 +26,10 @@
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
+40 -18
View File
@@ -1,23 +1,32 @@
using System;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Extensions.Rpc.Options;
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
using MQTTnet.Protocol;
using System;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Protocol;
namespace MQTTnet.Extensions.Rpc
{
public class MqttRpcClient : IDisposable
public sealed class MqttRpcClient : IMqttRpcClient
{
private readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
private readonly IMqttClient _mqttClient;
private readonly RpcAwareApplicationMessageReceivedHandler _applicationMessageReceivedHandler;
readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
readonly IMqttClient _mqttClient;
readonly IMqttRpcClientOptions _options;
readonly RpcAwareApplicationMessageReceivedHandler _applicationMessageReceivedHandler;
public MqttRpcClient(IMqttClient mqttClient)
[Obsolete("Use MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options).")]
public MqttRpcClient(IMqttClient mqttClient) : this(mqttClient, new MqttRpcClientOptions())
{
}
public MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options)
{
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
_options = options ?? throw new ArgumentNullException(nameof(options));
_applicationMessageReceivedHandler = new RpcAwareApplicationMessageReceivedHandler(
mqttClient.ApplicationMessageReceivedHandler,
@@ -45,18 +54,31 @@ namespace MQTTnet.Extensions.Rpc
{
if (methodName == null) throw new ArgumentNullException(nameof(methodName));
if (methodName.Contains("/") || methodName.Contains("+") || methodName.Contains("#"))
{
throw new ArgumentException("The method name cannot contain /, + or #.");
}
if (!(_mqttClient.ApplicationMessageReceivedHandler is RpcAwareApplicationMessageReceivedHandler))
{
throw new InvalidOperationException("The application message received handler was modified.");
}
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{methodName}";
var responseTopic = requestTopic + "/response";
var topicNames = _options.TopicGenerationStrategy.CreateRpcTopics(new TopicGenerationContext
{
MethodName = methodName,
QualityOfServiceLevel = qualityOfServiceLevel,
MqttClient = _mqttClient,
Options = _options
});
var requestTopic = topicNames.RequestTopic;
var responseTopic = topicNames.ResponseTopic;
if (string.IsNullOrWhiteSpace(requestTopic))
{
throw new MqttProtocolViolationException("RPC request topic is empty.");
}
if (string.IsNullOrWhiteSpace(responseTopic))
{
throw new MqttProtocolViolationException("RPC response topic is empty.");
}
var requestMessage = new MqttApplicationMessageBuilder()
.WithTopic(requestTopic)
@@ -74,7 +96,7 @@ namespace MQTTnet.Extensions.Rpc
await _mqttClient.SubscribeAsync(responseTopic, qualityOfServiceLevel).ConfigureAwait(false);
await _mqttClient.PublishAsync(requestMessage).ConfigureAwait(false);
using (var timeoutCts = new CancellationTokenSource(timeout))
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token))
{
@@ -112,7 +134,7 @@ namespace MQTTnet.Extensions.Rpc
}
}
private Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
{
if (!_waitingCalls.TryRemove(eventArgs.ApplicationMessage.Topic, out var tcs))
{
@@ -0,0 +1,9 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
namespace MQTTnet.Extensions.Rpc.Options
{
public interface IMqttRpcClientOptions
{
IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; }
}
}
@@ -0,0 +1,9 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
namespace MQTTnet.Extensions.Rpc.Options
{
public sealed class MqttRpcClientOptions : IMqttRpcClientOptions
{
public IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; } = new DefaultMqttRpcClientTopicGenerationStrategy();
}
}
@@ -0,0 +1,25 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
using System;
namespace MQTTnet.Extensions.Rpc.Options
{
public sealed class MqttRpcClientOptionsBuilder
{
IMqttRpcClientTopicGenerationStrategy _topicGenerationStrategy = new DefaultMqttRpcClientTopicGenerationStrategy();
public MqttRpcClientOptionsBuilder WithTopicGenerationStrategy(IMqttRpcClientTopicGenerationStrategy value)
{
_topicGenerationStrategy = value ?? throw new ArgumentNullException(nameof(value));
return this;
}
public IMqttRpcClientOptions Build()
{
return new MqttRpcClientOptions
{
TopicGenerationStrategy = _topicGenerationStrategy
};
}
}
}
@@ -0,0 +1,9 @@
namespace MQTTnet.Extensions.Rpc.Options
{
public sealed class MqttRpcTopicPair
{
public string RequestTopic { get; set; }
public string ResponseTopic { get; set; }
}
}
@@ -0,0 +1,24 @@
using System;
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public sealed class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
{
public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context)
{
if (context.MethodName.Contains("/") || context.MethodName.Contains("+") || context.MethodName.Contains("#"))
{
throw new ArgumentException("The method name cannot contain /, + or #.");
}
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{context.MethodName}";
var responseTopic = requestTopic + "/response";
return new MqttRpcTopicPair
{
RequestTopic = requestTopic,
ResponseTopic = responseTopic
};
}
}
}
@@ -0,0 +1,7 @@
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public interface IMqttRpcClientTopicGenerationStrategy
{
MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context);
}
}
@@ -0,0 +1,24 @@
using MQTTnet.Client;
using MQTTnet.Protocol;
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public sealed class TopicGenerationContext
{
public string MethodName { get; set; }
/// <summary>
/// Gets or sets the quality of service level.
/// The Quality of Service (QoS) level is an agreement between the sender of a message and the receiver of a message that defines the guarantee of delivery for a specific message.
/// There are 3 QoS levels in MQTT:
/// - At most once (0): Message gets delivered no time, once or multiple times.
/// - At least once (1): Message gets delivered at least once (one time or more often).
/// - Exactly once (2): Message gets delivered exactly once (It's ensured that the message only comes once).
/// </summary>
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
public IMqttClient MqttClient { get; set; }
public IMqttRpcClientOptions Options { get; set; }
}
}
@@ -4,9 +4,9 @@ using MQTTnet.Client.Receiving;
namespace MQTTnet.Extensions.Rpc
{
public class RpcAwareApplicationMessageReceivedHandler : IMqttApplicationMessageReceivedHandler
public sealed class RpcAwareApplicationMessageReceivedHandler : IMqttApplicationMessageReceivedHandler
{
private readonly Func<MqttApplicationMessageReceivedEventArgs, Task> _handleReceivedApplicationMessageAsync;
readonly Func<MqttApplicationMessageReceivedEventArgs, Task> _handleReceivedApplicationMessageAsync;
public RpcAwareApplicationMessageReceivedHandler(
IMqttApplicationMessageReceivedHandler originalHandler,
@@ -18,14 +18,14 @@ namespace MQTTnet.Extensions.Rpc
public IMqttApplicationMessageReceivedHandler OriginalHandler { get; }
public async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
{
if (OriginalHandler != null)
{
await OriginalHandler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
return OriginalHandler.HandleApplicationMessageReceivedAsync(eventArgs);
}
await _handleReceivedApplicationMessageAsync(eventArgs).ConfigureAwait(false);
return _handleReceivedApplicationMessageAsync(eventArgs);
}
}
}
@@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</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>
<Product />
<Company />
<Authors />
<PackageId />
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
@@ -23,6 +26,10 @@
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
</ItemGroup>
@@ -8,7 +8,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
{
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory());
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory(mqttFactory.DefaultLogger));
}
}
}
@@ -16,14 +16,14 @@ using WebSocket4Net;
namespace MQTTnet.Extensions.WebSocket4Net
{
public class WebSocket4NetMqttChannel : IMqttChannel
public sealed class WebSocket4NetMqttChannel : IMqttChannel
{
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
private readonly IMqttClientOptions _clientOptions;
private readonly MqttClientWebSocketOptions _webSocketOptions;
readonly IMqttClientOptions _clientOptions;
readonly MqttClientWebSocketOptions _webSocketOptions;
private WebSocket _webSocket;
WebSocket _webSocket;
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions, MqttClientWebSocketOptions webSocketOptions)
{
@@ -85,7 +85,12 @@ namespace MQTTnet.Extensions.WebSocket4Net
{
foreach (var certificate in _webSocketOptions.TlsOptions.Certificates)
{
#if WINDOWS_UWP
certificates.Add(new X509Certificate(certificate));
#else
certificates.Add(certificate);
#endif
}
}
@@ -161,12 +166,12 @@ namespace MQTTnet.Extensions.WebSocket4Net
_webSocket = null;
}
private void OnError(object sender, ErrorEventArgs e)
static void OnError(object sender, ErrorEventArgs e)
{
System.Diagnostics.Debug.Write(e.Exception.ToString());
}
private void OnDataReceived(object sender, DataReceivedEventArgs e)
void OnDataReceived(object sender, DataReceivedEventArgs e)
{
foreach (var @byte in e.Data)
{
@@ -174,7 +179,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
}
}
private async Task ConnectInternalAsync(CancellationToken cancellationToken)
async Task ConnectInternalAsync(CancellationToken cancellationToken)
{
_webSocket.Error += OnError;
_webSocket.DataReceived += OnDataReceived;
@@ -196,7 +201,9 @@ namespace MQTTnet.Extensions.WebSocket4Net
_webSocket.Opened += SuccessHandler;
_webSocket.Error += ErrorHandler;
#pragma warning disable AsyncFixer02 // Long-running or blocking operations inside an async method
_webSocket.Open();
#pragma warning restore AsyncFixer02 // Long-running or blocking operations inside an async method
var exception = await MqttTaskTimeout.WaitAsync(c =>
{
@@ -1,35 +1,49 @@
using System;
using MQTTnet.Adapter;
using MQTTnet.Adapter;
using MQTTnet.Client.Options;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using System;
namespace MQTTnet.Extensions.WebSocket4Net
{
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
public sealed class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
{
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger 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 (logger == null) throw new ArgumentNullException(nameof(logger));
switch (options.ChannelOptions)
{
case MqttClientTcpOptions _:
{
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
return new MqttChannelAdapter(
new MqttTcpChannel(options),
new MqttPacketFormatterAdapter(options.ProtocolVersion),
options.PacketInspector,
_logger);
}
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),
options.PacketInspector,
_logger);
}
default:
{
throw new NotSupportedException();
}
{
throw new NotSupportedException();
}
}
}
}
@@ -1,134 +0,0 @@
using MQTTnet.Client;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Adapter;
using MQTTnet.Channel;
using MQTTnet.Diagnostics;
using MQTTnet.Serializer;
using WebSocket4Net;
namespace MQTTnet.TestApp.NetCore
{
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
{
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (logger == null) throw new ArgumentNullException(nameof(logger));
if (!(options.ChannelOptions is MqttClientWebSocketOptions))
{
throw new NotSupportedException("Only WebSocket connections are supported.");
}
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options), new MqttPacketSerializer(), logger);
}
private class WebSocket4NetMqttChannel : IMqttChannel
{
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
private readonly IMqttClientOptions _clientOptions;
private WebSocket4Net.WebSocket _webSocket;
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions)
{
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions));
}
public string Endpoint { get; } = "";
public Task ConnectAsync(CancellationToken cancellationToken)
{
var channelOptions = (MqttClientWebSocketOptions)_clientOptions.ChannelOptions;
var uri = "ws://" + channelOptions.Uri;
var sslProtocols = SslProtocols.None;
if (channelOptions.TlsOptions.UseTls)
{
uri = "wss://" + channelOptions.Uri;
sslProtocols = SslProtocols.Tls12;
}
var subProtocol = channelOptions.SubProtocols.FirstOrDefault() ?? string.Empty;
_webSocket = new WebSocket4Net.WebSocket(uri, subProtocol, sslProtocols: sslProtocols);
_webSocket.DataReceived += OnDataReceived;
_webSocket.Open();
SpinWait.SpinUntil(() => _webSocket.State == WebSocketState.Open, _clientOptions.CommunicationTimeout);
return Task.FromResult(0);
}
public Task DisconnectAsync()
{
if (_webSocket != null)
{
_webSocket.DataReceived -= OnDataReceived;
_webSocket.Close();
SpinWait.SpinUntil(() => _webSocket.State == WebSocketState.Closed, _clientOptions.CommunicationTimeout);
}
_webSocket = null;
return Task.FromResult(0);
}
public Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
var readBytes = 0;
while (count > 0 && !cancellationToken.IsCancellationRequested)
{
byte @byte;
if (readBytes == 0)
{
// Block until at lease one byte was received.
@byte = _receiveBuffer.Take(cancellationToken);
}
else
{
if (!_receiveBuffer.TryTake(out @byte))
{
return Task.FromResult(readBytes);
}
}
buffer[offset] = @byte;
offset++;
count--;
readBytes++;
}
return Task.FromResult(readBytes);
}
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
_webSocket.Send(buffer, offset, count);
return Task.FromResult(0);
}
public void Dispose()
{
if (_webSocket != null)
{
_webSocket.DataReceived -= OnDataReceived;
_webSocket.Dispose();
}
}
private void OnDataReceived(object sender, WebSocket4Net.DataReceivedEventArgs e)
{
foreach (var @byte in e.Data)
{
_receiveBuffer.Add(@byte);
}
}
}
}
}
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "3.1.4",
"commands": [
"dotnet-ef"
]
}
}
}
@@ -0,0 +1,35 @@
using System.IO;
namespace MQTTnet.Server.Configuration
{
public class CertificateSettingsModel
{
/// <summary>
/// Path to certificate.
/// </summary>
public string Path { get; set; }
/// <summary>
/// Password of certificate.
/// </summary>
public string Password { get; set; }
/// <summary>
/// Read certificate file.
/// </summary>
public byte[] ReadCertificate()
{
if (string.IsNullOrEmpty(Path) || string.IsNullOrWhiteSpace(Path))
{
throw new FileNotFoundException("No path set");
}
if (!File.Exists(Path))
{
throw new FileNotFoundException($"Could not find Certificate in path: {Path}");
}
return File.ReadAllBytes(Path);
}
}
}
@@ -9,9 +9,9 @@ namespace MQTTnet.Server.Configuration
public class TcpEndPointModel
{
/// <summary>
/// Path to Certificate
/// Certificate settings.
/// </summary>
public string CertificatePath { get; set; }
public CertificateSettingsModel Certificate { get; set; }
/// <summary>
/// Enabled / Disable
@@ -33,25 +33,6 @@ namespace MQTTnet.Server.Configuration
/// </summary>
public int Port { get; set; } = 1883;
/// <summary>
/// Read Certificate file
/// </summary>
/// <returns></returns>
public byte[] ReadCertificate()
{
if (string.IsNullOrEmpty(CertificatePath) || string.IsNullOrWhiteSpace(CertificatePath))
{
throw new FileNotFoundException("No path set");
}
if (!File.Exists(CertificatePath))
{
throw new FileNotFoundException($"Could not find Certificate in path: {CertificatePath}");
}
return File.ReadAllBytes(CertificatePath);
}
/// <summary>
/// Read IPv4
/// </summary>
@@ -13,7 +13,7 @@ namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class ClientsController : ControllerBase
public class ClientsController : Controller
{
private readonly MqttServerService _mqttServerService;
@@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MQTTnet.Protocol;
using MQTTnet.Server.Mqtt;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class MessagesController : Controller
{
private readonly MqttServerService _mqttServerService;
public MessagesController(MqttServerService mqttServerService)
{
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService));
}
[Route("api/v1/messages")]
[HttpPost]
public async Task<ActionResult> PostMessage(MqttApplicationMessage message)
{
await _mqttServerService.PublishAsync(message);
return Ok();
}
[Route("api/v1/messages/{*topic}")]
[HttpPost]
public async Task<ActionResult> PostMessage(string topic, int qosLevel = 0)
{
byte[] payload;
using (var memoryStream = new MemoryStream())
{
await HttpContext.Request.Body.CopyToAsync(memoryStream);
payload = memoryStream.ToArray();
}
var message = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel((MqttQualityOfServiceLevel)qosLevel)
.Build();
return await PostMessage(message);
}
}
}
@@ -12,7 +12,7 @@ namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class RetainedApplicationMessagesController : ControllerBase
public class RetainedApplicationMessagesController : Controller
{
private readonly MqttServerService _mqttServerService;
@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Reflection;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class ServerController : Controller
{
[Route("api/v1/server/version")]
[HttpGet]
public ActionResult<string> GetVersion()
{
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
return fileVersion.ProductVersion.ToString();
}
}
}
@@ -13,7 +13,7 @@ namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class SessionsController : ControllerBase
public class SessionsController : Controller
{
private readonly MqttServerService _mqttServerService;
@@ -1,43 +1,43 @@
using System;
using MQTTnet.Diagnostics;
//using MQTTnet.Diagnostics;
//using System;
namespace MQTTnet.Server.Logging
{
public class MqttNetChildLoggerWrapper : IMqttNetChildLogger
{
private readonly MqttNetLoggerWrapper _logger;
private readonly string _source;
//namespace MQTTnet.Server.Logging
//{
// public class MqttNetChildLoggerWrapper : IMqttNetChildLogger
// {
// private readonly MqttNetLoggerWrapper _logger;
// private readonly string _source;
public MqttNetChildLoggerWrapper(string source, MqttNetLoggerWrapper logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
// public MqttNetChildLoggerWrapper(string source, MqttNetLoggerWrapper logger)
// {
// _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_source = source;
}
// _source = source;
// }
public IMqttNetChildLogger CreateChildLogger(string source = null)
{
return _logger.CreateChildLogger(source);
}
// public IMqttNetLogger CreateChildLogger(string source = null)
// {
// return _logger.CreateChildLogger(source);
// }
public void Verbose(string message, params object[] parameters)
{
_logger.Publish(MqttNetLogLevel.Verbose, _source, message, parameters, null);
}
// public void Verbose(string message, params object[] parameters)
// {
// _logger.Publish(MqttNetLogLevel.Verbose, _source, message, parameters, null);
// }
public void Info(string message, params object[] parameters)
{
_logger.Publish(MqttNetLogLevel.Info, _source, message, parameters, null);
}
// public void Info(string message, params object[] parameters)
// {
// _logger.Publish(MqttNetLogLevel.Info, _source, message, parameters, null);
// }
public void Warning(Exception exception, string message, params object[] parameters)
{
_logger.Publish(MqttNetLogLevel.Warning, _source, message, parameters, exception);
}
// public void Warning(Exception exception, string message, params object[] parameters)
// {
// _logger.Publish(MqttNetLogLevel.Warning, _source, message, parameters, exception);
// }
public void Error(Exception exception, string message, params object[] parameters)
{
_logger.Publish(MqttNetLogLevel.Error, _source, message, parameters, exception);
}
}
}
// public void Error(Exception exception, string message, params object[] parameters)
// {
// _logger.Publish(MqttNetLogLevel.Error, _source, message, parameters, exception);
// }
// }
//}
@@ -1,13 +1,13 @@
using System;
using System.Threading;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using MQTTnet.Diagnostics;
using System;
using System.Threading;
namespace MQTTnet.Server.Logging
{
public class MqttNetLoggerWrapper : IMqttNetLogger
public sealed class MqttNetLoggerWrapper : IMqttNetLogger
{
private readonly ILogger<MqttServer> _logger;
readonly ILogger<MqttServer> _logger;
public MqttNetLoggerWrapper(ILogger<MqttServer> logger)
{
@@ -16,25 +16,39 @@ namespace MQTTnet.Server.Logging
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
public IMqttNetChildLogger CreateChildLogger(string source = null)
public IMqttNetScopedLogger CreateScopedLogger(string source)
{
return new MqttNetChildLoggerWrapper(source, this);
return new MqttNetScopedLogger(this, source);
}
public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception)
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
{
var convertedLogLevel = ConvertLogLevel(logLevel);
var convertedLogLevel = ConvertLogLevel(level);
_logger.Log(convertedLogLevel, exception, message, parameters);
var logMessagePublishedEvent = LogMessagePublished;
if (logMessagePublishedEvent != null)
{
var logMessage = new MqttNetLogMessage(null, DateTime.UtcNow, Thread.CurrentThread.ManagedThreadId, source, logLevel, message, exception);
var logMessage = new MqttNetLogMessage
{
Timestamp = DateTime.UtcNow,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source,
Level = level,
Message = message,
Exception = exception
};
logMessagePublishedEvent.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
}
}
private static LogLevel ConvertLogLevel(MqttNetLogLevel logLevel)
public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception)
{
Publish(logLevel, null, message, parameters, exception);
}
static LogLevel ConvertLogLevel(MqttNetLogLevel logLevel)
{
switch (logLevel)
{
+30 -21
View File
@@ -1,26 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFrameworks>net5.0</TargetFrameworks>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<AssemblyName>MQTTnet.Server</AssemblyName>
<RootNamespace>MQTTnet.Server</RootNamespace>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Company />
<Product>MQTTnet</Product>
<Description />
<Authors />
<Description>Standalone MQTT server with Python scripting backend.</Description>
<Authors>The authors of MQTTnet.Server.</Authors>
<PackageId />
<SignAssembly>false</SignAssembly>
<DelaySign>false</DelaySign>
<LangVersion>latest</LangVersion>
<Version>1.0.0</Version>
<Version>3.0.11</Version>
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
</PropertyGroup>
<PropertyGroup>
<StartupObject></StartupObject>
<StartupObject>MQTTnet.Server.Program</StartupObject>
<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 Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -29,13 +32,6 @@
<NoWarn>1701;1702</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="wwwroot\**" />
<Content Remove="wwwroot\**" />
<EmbeddedResource Remove="wwwroot\**" />
<None Remove="wwwroot\**" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -43,14 +39,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronPython" Version="2.7.9" />
<PackageReference Include="IronPython.StdLib" Version="2.7.9" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0-rc2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.0.0-rc2" />
<PackageReference Include="IronPython" Version="2.7.11" />
<PackageReference Include="IronPython.StdLib" Version="2.7.11" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.6.3" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net5.0'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.5" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
@@ -74,11 +75,19 @@
<None Update="Web\authorization_handler.py">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</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>
<Folder Include="Properties\PublishProfiles\" />
<Folder Include="Web\wwwroot\" />
</ItemGroup>
</Project>
@@ -22,14 +22,18 @@ namespace MQTTnet.Server.Mqtt
{
try
{
// This might be not set when a message was published by the server instead of a client.
context.SessionItems.TryGetValue(MqttServerConnectionValidator.WrappedSessionItemsKey, out var sessionItems);
var pythonContext = new PythonDictionary
{
{ "client_id", context.ClientId },
{ "session_items", sessionItems },
{ "retain", context.ApplicationMessage.Retain },
{ "accept_publish", context.AcceptPublish },
{ "close_connection", context.CloseConnection },
{ "client_id", context.ClientId },
{ "topic", context.ApplicationMessage.Topic },
{ "qos", (int)context.ApplicationMessage.QualityOfServiceLevel },
{ "retain", context.ApplicationMessage.Retain }
{ "qos", (int)context.ApplicationMessage.QualityOfServiceLevel }
};
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_application_message", pythonContext);
@@ -47,4 +51,4 @@ namespace MQTTnet.Server.Mqtt
return Task.CompletedTask;
}
}
}
}
@@ -9,6 +9,8 @@ namespace MQTTnet.Server.Mqtt
{
public class MqttServerConnectionValidator : IMqttServerConnectionValidator
{
public const string WrappedSessionItemsKey = "WRAPPED_ITEMS";
private readonly PythonScriptHostService _pythonScriptHostService;
private readonly ILogger _logger;
@@ -22,6 +24,8 @@ namespace MQTTnet.Server.Mqtt
{
try
{
var sessionItems = new PythonDictionary();
var pythonContext = new PythonDictionary
{
{ "endpoint", context.Endpoint },
@@ -33,6 +37,7 @@ namespace MQTTnet.Server.Mqtt
{ "clean_session", context.CleanSession},
{ "authentication_method", context.AuthenticationMethod},
{ "authentication_data", new Bytes(context.AuthenticationData ?? new byte[0]) },
{ "session_items", sessionItems },
{ "result", PythonConvert.Pythonfy(context.ReasonCode) }
};
@@ -40,6 +45,8 @@ namespace MQTTnet.Server.Mqtt
_pythonScriptHostService.InvokeOptionalFunction("on_validate_client_connection", pythonContext);
context.ReasonCode = PythonConvert.ParseEnum<MqttConnectReasonCode>((string)pythonContext["result"]);
context.SessionItems[WrappedSessionItemsKey] = sessionItems;
}
catch (Exception exception)
{
+53 -29
View File
@@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using IronPython.Runtime;
using IronPython.Runtime;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MQTTnet.Adapter;
@@ -16,25 +9,33 @@ using MQTTnet.Protocol;
using MQTTnet.Server.Configuration;
using MQTTnet.Server.Scripting;
using MQTTnet.Server.Status;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
namespace MQTTnet.Server.Mqtt
{
public class MqttServerService
{
private readonly ILogger<MqttServerService> _logger;
readonly ILogger<MqttServerService> _logger;
private readonly MqttSettingsModel _settings;
private readonly MqttApplicationMessageInterceptor _mqttApplicationMessageInterceptor;
private readonly MqttServerStorage _mqttServerStorage;
private readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
private readonly MqttServerConnectionValidator _mqttConnectionValidator;
private readonly IMqttServer _mqttServer;
private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
private readonly PythonScriptHostService _pythonScriptHostService;
private readonly MqttWebSocketServerAdapter _webSocketServerAdapter;
readonly MqttSettingsModel _settings;
readonly MqttApplicationMessageInterceptor _mqttApplicationMessageInterceptor;
readonly MqttServerStorage _mqttServerStorage;
readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
readonly MqttServerConnectionValidator _mqttConnectionValidator;
readonly IMqttServer _mqttServer;
readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
readonly MqttUnsubscriptionInterceptor _mqttUnsubscriptionInterceptor;
readonly PythonScriptHostService _pythonScriptHostService;
readonly MqttWebSocketServerAdapter _webSocketServerAdapter;
public MqttServerService(
MqttSettingsModel mqttSettings,
@@ -45,9 +46,10 @@ namespace MQTTnet.Server.Mqtt
MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
MqttServerConnectionValidator mqttConnectionValidator,
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
MqttUnsubscriptionInterceptor mqttUnsubscriptionInterceptor,
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
MqttServerStorage mqttServerStorage,
PythonScriptHostService pythonScriptHostService,
PythonScriptHostService pythonScriptHostService,
ILogger<MqttServerService> logger)
{
_settings = mqttSettings ?? throw new ArgumentNullException(nameof(mqttSettings));
@@ -57,16 +59,17 @@ namespace MQTTnet.Server.Mqtt
_mqttClientUnsubscribedTopicHandler = mqttClientUnsubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientUnsubscribedTopicHandler));
_mqttConnectionValidator = mqttConnectionValidator ?? throw new ArgumentNullException(nameof(mqttConnectionValidator));
_mqttSubscriptionInterceptor = mqttSubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttSubscriptionInterceptor));
_mqttUnsubscriptionInterceptor = mqttUnsubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttUnsubscriptionInterceptor));
_mqttApplicationMessageInterceptor = mqttApplicationMessageInterceptor ?? throw new ArgumentNullException(nameof(mqttApplicationMessageInterceptor));
_mqttServerStorage = mqttServerStorage ?? throw new ArgumentNullException(nameof(mqttServerStorage));
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_webSocketServerAdapter = new MqttWebSocketServerAdapter(mqttFactory.Logger.CreateChildLogger());
_webSocketServerAdapter = new MqttWebSocketServerAdapter(mqttFactory.Logger);
var adapters = new List<IMqttServerAdapter>
{
new MqttTcpServerAdapter(mqttFactory.Logger.CreateChildLogger())
new MqttTcpServerAdapter(mqttFactory.Logger)
{
TreatSocketOpeningErrorAsWarning = true // Opening other ports than for HTTP is not allows in Azure App Services.
},
@@ -124,7 +127,7 @@ namespace MQTTnet.Server.Mqtt
return _mqttServer.PublishAsync(applicationMessage);
}
private void Publish(PythonDictionary parameters)
void Publish(PythonDictionary parameters)
{
try
{
@@ -170,7 +173,7 @@ namespace MQTTnet.Server.Mqtt
}
}
private IMqttServerOptions CreateMqttServerOptions()
IMqttServerOptions CreateMqttServerOptions()
{
var options = new MqttServerOptionsBuilder()
.WithMaxPendingMessagesPerClient(_settings.MaxPendingMessagesPerClient)
@@ -178,8 +181,9 @@ namespace MQTTnet.Server.Mqtt
.WithConnectionValidator(_mqttConnectionValidator)
.WithApplicationMessageInterceptor(_mqttApplicationMessageInterceptor)
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
.WithUnsubscriptionInterceptor(_mqttUnsubscriptionInterceptor)
.WithStorage(_mqttServerStorage);
// Configure unencrypted connections
if (_settings.TcpEndPoint.Enabled)
{
@@ -208,10 +212,30 @@ namespace MQTTnet.Server.Mqtt
// Configure encrypted connections
if (_settings.EncryptedTcpEndPoint.Enabled)
{
#if NETCOREAPP3_1 || NET5_0
options
.WithEncryptedEndpoint()
.WithEncryptionSslProtocol(SslProtocols.Tls12)
.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.ReadCertificate());
.WithEncryptionSslProtocol(SslProtocols.Tls13);
#else
options
.WithEncryptedEndpoint()
.WithEncryptionSslProtocol(SslProtocols.Tls12);
#endif
if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Path))
{
IMqttServerCertificateCredentials certificateCredentials = null;
if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Password))
{
certificateCredentials = new MqttServerCertificateCredentials
{
Password = _settings.EncryptedTcpEndPoint.Certificate.Password
};
}
options.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.Certificate.ReadCertificate(), certificateCredentials);
}
if (_settings.EncryptedTcpEndPoint.TryReadIPv4(out var address4))
{
@@ -21,14 +21,16 @@ namespace MQTTnet.Server.Mqtt
{
try
{
var sessionItems = (PythonDictionary)context.SessionItems[MqttServerConnectionValidator.WrappedSessionItemsKey];
var pythonContext = new PythonDictionary
{
{ "accept_subscription", context.AcceptSubscription },
{ "close_connection", context.CloseConnection },
{ "client_id", context.ClientId },
{ "session_items", sessionItems },
{ "topic", context.TopicFilter.Topic },
{ "qos", (int)context.TopicFilter.QualityOfServiceLevel }
{ "qos", (int)context.TopicFilter.QualityOfServiceLevel },
{ "accept_subscription", context.AcceptSubscription },
{ "close_connection", context.CloseConnection }
};
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_subscription", pythonContext);
@@ -0,0 +1,48 @@
using System;
using System.Threading.Tasks;
using IronPython.Runtime;
using Microsoft.Extensions.Logging;
using MQTTnet.Server.Scripting;
namespace MQTTnet.Server.Mqtt
{
public class MqttUnsubscriptionInterceptor : IMqttServerUnsubscriptionInterceptor
{
private readonly PythonScriptHostService _pythonScriptHostService;
private readonly ILogger _logger;
public MqttUnsubscriptionInterceptor(PythonScriptHostService pythonScriptHostService, ILogger<MqttUnsubscriptionInterceptor> logger)
{
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context)
{
try
{
var sessionItems = (PythonDictionary)context.SessionItems[MqttServerConnectionValidator.WrappedSessionItemsKey];
var pythonContext = new PythonDictionary
{
{ "client_id", context.ClientId },
{ "session_items", sessionItems },
{ "topic", context.Topic },
{ "accept_unsubscription", context.AcceptUnsubscription },
{ "close_connection", context.CloseConnection }
};
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_unsubscription", pythonContext);
context.AcceptUnsubscription = (bool)pythonContext["accept_unsubscription"];
context.CloseConnection = (bool)pythonContext["close_connection"];
}
catch (Exception exception)
{
_logger.LogError(exception, "Error while intercepting unsubscription.");
}
return Task.CompletedTask;
}
}
}
+21 -8
View File
@@ -1,8 +1,10 @@
using System;
using System.Reflection;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using MQTTnet.Server.Web;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
namespace MQTTnet.Server
{
@@ -14,7 +16,15 @@ namespace MQTTnet.Server
{
PrintLogo();
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build().Run();
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
})
.UseWebRoot(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot"))
.UseStartup<Startup>();
}).Build().Run();
return 0;
}
@@ -25,7 +35,7 @@ namespace MQTTnet.Server
}
}
private static void PrintLogo()
static void PrintLogo()
{
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.Red;
@@ -46,12 +56,15 @@ namespace MQTTnet.Server
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("The official MQTT server implementation of MQTTnet");
Console.WriteLine("Copyright (c) 2017-2019 The MQTTnet Team");
Console.WriteLine("Copyright (c) 2017-2020 The MQTTnet Team");
Console.WriteLine(@"https://github.com/chkr1011/MQTTnet");
Console.ForegroundColor = ConsoleColor.White;
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
Console.WriteLine($@"
Version: {Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}
Version: {fileVersion.ProductVersion}
License: MIT (read LICENSE file)
Sponsoring: https://opencollective.com/mqttnet
Support: https://github.com/chkr1011/MQTTnet/issues
@@ -1,14 +1,14 @@
using System;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace MQTTnet.Server.Scripting.DataSharing
{
public class DataSharingService
{
private readonly Dictionary<string, object> _storage = new Dictionary<string, object>();
private readonly PythonScriptHostService _pythonScriptHostService;
private readonly ILogger<DataSharingService> _logger;
readonly Dictionary<string, object> _storage = new Dictionary<string, object>();
readonly PythonScriptHostService _pythonScriptHostService;
readonly ILogger<DataSharingService> _logger;
public DataSharingService(PythonScriptHostService pythonScriptHostService, ILogger<DataSharingService> logger)
{
@@ -1,14 +1,14 @@
using System;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Text;
using Microsoft.Extensions.Logging;
namespace MQTTnet.Server.Scripting
{
public class PythonIOStream : Stream
{
private readonly ILogger _logger;
private readonly Encoding _encoder = Encoding.UTF8;
readonly ILogger _logger;
readonly Encoding _encoder = Encoding.UTF8;
public PythonIOStream(ILogger<PythonIOStream> logger)
{
@@ -1,4 +1,8 @@
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using MQTTnet.Server.Configuration;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
@@ -6,22 +10,18 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using MQTTnet.Server.Configuration;
namespace MQTTnet.Server.Scripting
{
public class PythonScriptHostService
{
private readonly IDictionary<string, object> _proxyObjects = new ExpandoObject();
private readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>();
private readonly string _scriptsPath;
private readonly ScriptingSettingsModel _scriptingSettings;
private readonly ILogger<PythonScriptHostService> _logger;
private readonly ScriptEngine _scriptEngine;
readonly IDictionary<string, object> _proxyObjects = new ExpandoObject();
readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>();
readonly string _scriptsPath;
readonly ScriptingSettingsModel _scriptingSettings;
readonly ILogger<PythonScriptHostService> _logger;
readonly ScriptEngine _scriptEngine;
public PythonScriptHostService(ScriptingSettingsModel scriptingSettings, PythonIOStream pythonIOStream, ILogger<PythonScriptHostService> logger)
{
_scriptingSettings = scriptingSettings ?? throw new ArgumentNullException(nameof(scriptingSettings));
@@ -139,7 +139,7 @@ namespace MQTTnet.Server.Scripting
}
}
private async Task TryInitializeScriptAsync(string path)
async Task TryInitializeScriptAsync(string path)
{
var uid = new FileInfo(path).Name.Replace(".py", string.Empty, StringComparison.OrdinalIgnoreCase);
@@ -155,7 +155,7 @@ namespace MQTTnet.Server.Scripting
{
_scriptInstances.Add(scriptInstance);
}
_logger.LogInformation($"Initialized script '{uid}'.");
}
catch (Exception exception)
@@ -164,7 +164,7 @@ namespace MQTTnet.Server.Scripting
}
}
private PythonScriptInstance CreateScriptInstance(string uid, string path, string code)
PythonScriptInstance CreateScriptInstance(string uid, string path, string code)
{
var scriptScope = _scriptEngine.CreateScope();
@@ -173,11 +173,11 @@ namespace MQTTnet.Server.Scripting
scriptScope.SetVariable("mqtt_net_server", _proxyObjects);
compiledCode.Execute(scriptScope);
return new PythonScriptInstance(uid, path, scriptScope);
}
private void AddSearchPaths(ScriptEngine scriptEngine)
void AddSearchPaths(ScriptEngine scriptEngine)
{
if (_scriptingSettings.IncludePaths?.Any() != true)
{
@@ -1,12 +1,12 @@
using System;
using IronPython.Runtime;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting;
using System;
namespace MQTTnet.Server.Scripting
{
public class PythonScriptInstance
{
private readonly ScriptScope _scriptScope;
readonly ScriptScope _scriptScope;
public PythonScriptInstance(string uid, string path, ScriptScope scriptScope)
{
+41 -34
View File
@@ -1,22 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
using Microsoft.OpenApi.Models;
using Microsoft.Scripting.Utils;
using MQTTnet.AspNetCore;
using MQTTnet.Server.Configuration;
using MQTTnet.Server.Logging;
using MQTTnet.Server.Mqtt;
using MQTTnet.Server.Scripting;
using MQTTnet.Server.Scripting.DataSharing;
using Newtonsoft.Json.Converters;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace MQTTnet.Server.Web
{
@@ -35,33 +36,28 @@ namespace MQTTnet.Server.Web
public void Configure(
IApplicationBuilder application,
IHostingEnvironment environment,
MqttServerService mqttServerService,
PythonScriptHostService pythonScriptHostService,
DataSharingService dataSharingService,
MqttSettingsModel mqttSettings)
{
if (environment.IsDevelopment())
{
application.UseDeveloperExceptionPage();
}
else
{
application.UseHsts();
}
application.UseDefaultFiles();
application.UseStaticFiles();
application.UseHsts();
application.UseRouting();
application.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
.AllowAnyHeader());
application.UseAuthentication();
application.UseStaticFiles();
application.UseHttpsRedirection();
application.UseMvc();
application.UseAuthorization();
application.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
ConfigureWebSocketEndpoint(application, mqttServerService, mqttSettings);
@@ -87,11 +83,13 @@ namespace MQTTnet.Server.Web
{
services.AddCors();
services.AddControllers();
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options =>
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(o =>
{
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
o.SerializerSettings.Converters.Add(new StringEnumConverter());
});
ReadMqttSettings(services);
@@ -111,18 +109,22 @@ namespace MQTTnet.Server.Web
services.AddSingleton<MqttClientUnsubscribedTopicHandler>();
services.AddSingleton<MqttServerConnectionValidator>();
services.AddSingleton<MqttSubscriptionInterceptor>();
services.AddSingleton<MqttUnsubscriptionInterceptor>();
services.AddSingleton<MqttApplicationMessageInterceptor>();
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
var securityScheme = new OpenApiSecurityScheme
{
Scheme = "Basic",
Scheme = "basic",
Name = HeaderNames.Authorization,
Type = SecuritySchemeType.Http,
In = ParameterLocation.Header
In = ParameterLocation.Header,
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Swagger"
}
};
c.AddSecurityDefinition("Swagger", securityScheme);
@@ -156,7 +158,7 @@ namespace MQTTnet.Server.Web
.AddCookie();
}
private void ReadMqttSettings(IServiceCollection services)
void ReadMqttSettings(IServiceCollection services)
{
var mqttSettings = new MqttSettingsModel();
Configuration.Bind("MQTT", mqttSettings);
@@ -167,7 +169,7 @@ namespace MQTTnet.Server.Web
services.AddSingleton(scriptingSettings);
}
private static void ConfigureWebSocketEndpoint(
static void ConfigureWebSocketEndpoint(
IApplicationBuilder application,
MqttServerService mqttServerService,
MqttSettingsModel mqttSettings)
@@ -184,8 +186,7 @@ namespace MQTTnet.Server.Web
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromSeconds(mqttSettings.WebSocketEndPoint.KeepAliveInterval),
ReceiveBufferSize = mqttSettings.WebSocketEndPoint.ReceiveBufferSize
KeepAliveInterval = TimeSpan.FromSeconds(mqttSettings.WebSocketEndPoint.KeepAliveInterval)
};
if (mqttSettings.WebSocketEndPoint.AllowedOrigins?.Any() == true)
@@ -201,7 +202,13 @@ namespace MQTTnet.Server.Web
{
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);
}
@@ -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>
+6 -7
View File
@@ -27,7 +27,10 @@
"IPv4": "*",
"IPv6": "*",
"Port": 8883,
"CertificatePath": "/absolute/path/to/pfx"
"Certificate": {
"Path": "/absolute/path/to/pfx",
"Password": ""
}
},
"WebSocketEndPoint": {
"Enabled": true,
@@ -49,11 +52,7 @@
},
"Scripting": {
"ScriptsPath": "Scripts",
"IncludePaths": [
"Lib",
"/usr/lib/python2.7",
"C:\\Python27\\Lib"
]
"IncludePaths": []
},
"Logging": {
"LogLevel": {
@@ -63,4 +62,4 @@
}
},
"AllowedHosts": "*"
}
}
-12
View File
@@ -1,12 +0,0 @@
{
"version": "1.0.0",
"name": "mqtt.test",
"private": true,
"devDependencies": {},
"dependencies": {
"@types/node": "^8.0.46",
"mqtt": "^2.15.1",
"systemjs": "^0.20.19",
"typescript": "^2.3.4"
}
}
@@ -21,17 +21,15 @@ namespace MQTTnet.Adapter
long BytesReceived { get; }
Action ReadingPacketStartedCallback { get; set; }
Action ReadingPacketCompletedCallback { get; set; }
bool IsReadingPacket { get; }
Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken);
Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken);
Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken);
Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken);
Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken);
Task<MqttBasePacket> ReceivePacketAsync(CancellationToken cancellationToken);
void ResetStatistics();
}
@@ -1,10 +1,9 @@
using MQTTnet.Client.Options;
using MQTTnet.Diagnostics;
namespace MQTTnet.Adapter
{
public interface IMqttClientAdapterFactory
{
IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger);
IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options);
}
}
+205 -98
View File
@@ -1,3 +1,9 @@
using MQTTnet.Channel;
using MQTTnet.Diagnostics;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Packets;
using System;
using System.IO;
using System.Net.Sockets;
@@ -5,43 +11,36 @@ using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Channel;
using MQTTnet.Diagnostics;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Diagnostics.PacketInspection;
namespace MQTTnet.Adapter
{
public class MqttChannelAdapter : IMqttChannelAdapter
public sealed class MqttChannelAdapter : Disposable, IMqttChannelAdapter
{
private const uint ErrorOperationAborted = 0x800703E3;
private const int ReadBufferSize = 4096; // TODO: Move buffer size to config
const uint ErrorOperationAborted = 0x800703E3;
const int ReadBufferSize = 4096;
private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
readonly byte[] _singleByteBuffer = new byte[1];
readonly byte[] _fixedHeaderBuffer = new byte[2];
private readonly IMqttNetChildLogger _logger;
private readonly IMqttChannel _channel;
private readonly MqttPacketReader _packetReader;
readonly MqttPacketInspectorHandler _packetInspectorHandler;
readonly IMqttNetScopedLogger _logger;
readonly IMqttChannel _channel;
private readonly byte[] _fixedHeaderBuffer = new byte[2];
readonly AsyncLock _syncRoot = new AsyncLock();
private bool _isDisposed;
long _bytesReceived;
long _bytesSent;
private long _bytesReceived;
private long _bytesSent;
public MqttChannelAdapter(IMqttChannel channel, MqttPacketFormatterAdapter packetFormatterAdapter, IMqttNetChildLogger logger)
public MqttChannelAdapter(IMqttChannel channel, MqttPacketFormatterAdapter packetFormatterAdapter, IMqttPacketInspector packetInspector, IMqttNetLogger logger)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
_channel = channel ?? throw new ArgumentNullException(nameof(channel));
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
_packetReader = new MqttPacketReader(_channel);
_packetInspectorHandler = new MqttPacketInspectorHandler(packetInspector, logger);
_logger = logger.CreateChildLogger(nameof(MqttChannelAdapter));
if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger.CreateScopedLogger(nameof(MqttChannelAdapter));
}
public string Endpoint => _channel.Endpoint;
@@ -53,13 +52,14 @@ namespace MQTTnet.Adapter
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
public long BytesSent => Interlocked.Read(ref _bytesSent);
public long BytesReceived => Interlocked.Read(ref _bytesReceived);
public Action ReadingPacketStartedCallback { get; set; }
public Action ReadingPacketCompletedCallback { get; set; }
public bool IsReadingPacket { get; private set; }
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
try
@@ -80,12 +80,13 @@ namespace MQTTnet.Adapter
throw;
}
WrapException(exception);
WrapAndThrowException(exception);
}
}
public async Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
try
@@ -107,89 +108,87 @@ namespace MQTTnet.Adapter
throw;
}
WrapException(exception);
WrapAndThrowException(exception);
}
}
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
public async Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
{
await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var packetData = PacketFormatterAdapter.Encode(packet);
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (timeout == TimeSpan.Zero)
using (await _syncRoot.WaitAsync(cancellationToken).ConfigureAwait(false))
{
// Check for cancellation here again because "WaitAsync" might take some time.
cancellationToken.ThrowIfCancellationRequested();
try
{
var packetData = PacketFormatterAdapter.Encode(packet);
_packetInspectorHandler.BeginSendPacket(packetData);
await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false);
Interlocked.Add(ref _bytesReceived, packetData.Count);
_logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet);
}
else
catch (Exception exception)
{
await MqttTaskTimeout.WaitAsync(
t => _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, t), timeout, cancellationToken).ConfigureAwait(false);
if (IsWrappedException(exception))
{
throw;
}
WrapAndThrowException(exception);
}
Interlocked.Add(ref _bytesReceived, packetData.Count);
PacketFormatterAdapter.FreeBuffer();
_logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet);
}
catch (Exception exception)
{
if (IsWrappedException(exception))
finally
{
throw;
PacketFormatterAdapter.FreeBuffer();
}
WrapException(exception);
}
finally
{
_writerSemaphore.Release();
}
}
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
public async Task<MqttBasePacket> ReceivePacketAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
try
{
ReceivedMqttPacket receivedMqttPacket;
if (timeout == TimeSpan.Zero)
{
receivedMqttPacket = await ReceiveAsync(cancellationToken).ConfigureAwait(false);
}
else
{
receivedMqttPacket = await MqttTaskTimeout.WaitAsync(ReceiveAsync, timeout, cancellationToken).ConfigureAwait(false);
}
_packetInspectorHandler.BeginReceivePacket();
if (receivedMqttPacket == null || cancellationToken.IsCancellationRequested)
var receivedPacket = await ReceiveAsync(cancellationToken).ConfigureAwait(false);
if (receivedPacket == null || cancellationToken.IsCancellationRequested)
{
return null;
}
Interlocked.Add(ref _bytesSent, receivedMqttPacket.TotalLength);
_packetInspectorHandler.EndReceivePacket();
Interlocked.Add(ref _bytesSent, receivedPacket.TotalLength);
if (PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.Unknown)
{
PacketFormatterAdapter.DetectProtocolVersion(receivedMqttPacket);
PacketFormatterAdapter.DetectProtocolVersion(receivedPacket);
}
var packet = PacketFormatterAdapter.Decode(receivedMqttPacket);
var packet = PacketFormatterAdapter.Decode(receivedPacket);
if (packet == null)
{
throw new MqttProtocolViolationException("Received malformed packet.");
}
_logger.Verbose("RX ({0} bytes) <<< {1}", receivedMqttPacket.TotalLength, packet);
_logger.Verbose("RX ({0} bytes) <<< {1}", receivedPacket.TotalLength, packet);
return packet;
}
catch (OperationCanceledException)
{
}
catch (ObjectDisposedException)
{
}
catch (Exception exception)
{
if (IsWrappedException(exception))
@@ -197,7 +196,7 @@ namespace MQTTnet.Adapter
throw;
}
WrapException(exception);
WrapAndThrowException(exception);
}
return null;
@@ -209,33 +208,51 @@ namespace MQTTnet.Adapter
Interlocked.Exchange(ref _bytesSent, 0L);
}
private async Task<ReceivedMqttPacket> ReceiveAsync(CancellationToken cancellationToken)
protected override void Dispose(bool disposing)
{
var readFixedHeaderResult = await _packetReader.ReadFixedHeaderAsync(_fixedHeaderBuffer, cancellationToken).ConfigureAwait(false);
if (disposing)
{
_channel.Dispose();
_syncRoot.Dispose();
}
base.Dispose(disposing);
}
async Task<ReceivedMqttPacket> ReceiveAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return null;
}
var readFixedHeaderResult = await ReadFixedHeaderAsync(cancellationToken).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return null;
}
if (readFixedHeaderResult.ConnectionClosed)
{
return null;
}
try
{
if (readFixedHeaderResult.ConnectionClosed)
{
return null;
}
ReadingPacketStartedCallback?.Invoke();
IsReadingPacket = true;
var fixedHeader = readFixedHeaderResult.FixedHeader;
if (fixedHeader.RemainingLength == 0)
{
return new ReceivedMqttPacket(fixedHeader.Flags, null, 2);
return new ReceivedMqttPacket(fixedHeader.Flags, new MqttPacketBodyReader(new byte[0], 0, 0), 2);
}
var body = new byte[fixedHeader.RemainingLength];
var bodyLength = fixedHeader.RemainingLength;
var body = new byte[bodyLength];
var bodyOffset = 0;
var chunkSize = Math.Min(ReadBufferSize, fixedHeader.RemainingLength);
var chunkSize = Math.Min(ReadBufferSize, bodyLength);
do
{
@@ -258,40 +275,126 @@ namespace MQTTnet.Adapter
}
bodyOffset += readBytes;
} while (bodyOffset < body.Length);
} while (bodyOffset < bodyLength);
var bodyReader = new MqttPacketBodyReader(body, 0, body.Length);
_packetInspectorHandler.FillReceiveBuffer(body);
var bodyReader = new MqttPacketBodyReader(body, 0, bodyLength);
return new ReceivedMqttPacket(fixedHeader.Flags, bodyReader, fixedHeader.TotalLength);
}
finally
{
ReadingPacketCompletedCallback?.Invoke();
IsReadingPacket = false;
}
}
public void Dispose()
async Task<ReadFixedHeaderResult> ReadFixedHeaderAsync(CancellationToken cancellationToken)
{
_isDisposed = true;
// The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
// So in all cases at least 2 bytes must be read for a complete MQTT packet.
var buffer = _fixedHeaderBuffer;
var totalBytesRead = 0;
_channel?.Dispose();
}
private void ThrowIfDisposed()
{
if (_isDisposed)
while (totalBytesRead < buffer.Length)
{
throw new ObjectDisposedException(nameof(MqttChannelAdapter));
var bytesRead = await _channel.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead, cancellationToken).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return null;
}
if (bytesRead == 0)
{
return new ReadFixedHeaderResult
{
ConnectionClosed = true
};
}
totalBytesRead += bytesRead;
}
_packetInspectorHandler.FillReceiveBuffer(buffer);
var hasRemainingLength = buffer[1] != 0;
if (!hasRemainingLength)
{
return new ReadFixedHeaderResult
{
FixedHeader = new MqttFixedHeader(buffer[0], 0, totalBytesRead)
};
}
var bodyLength = await ReadBodyLengthAsync(buffer[1], cancellationToken).ConfigureAwait(false);
if (!bodyLength.HasValue)
{
return new ReadFixedHeaderResult
{
ConnectionClosed = true
};
}
totalBytesRead += bodyLength.Value;
return new ReadFixedHeaderResult
{
FixedHeader = new MqttFixedHeader(buffer[0], bodyLength.Value, totalBytesRead)
};
}
private static bool IsWrappedException(Exception exception)
async Task<int?> ReadBodyLengthAsync(byte initialEncodedByte, CancellationToken cancellationToken)
{
var offset = 0;
var multiplier = 128;
var value = initialEncodedByte & 127;
int encodedByte = initialEncodedByte;
while ((encodedByte & 128) != 0)
{
offset++;
if (offset > 3)
{
throw new MqttProtocolViolationException("Remaining length is invalid.");
}
if (cancellationToken.IsCancellationRequested)
{
return null;
}
var readCount = await _channel.ReadAsync(_singleByteBuffer, 0, 1, cancellationToken).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return null;
}
if (readCount == 0)
{
return null;
}
_packetInspectorHandler.FillReceiveBuffer(_singleByteBuffer);
encodedByte = _singleByteBuffer[0];
value += (encodedByte & 127) * multiplier;
multiplier *= 128;
}
return value;
}
static bool IsWrappedException(Exception exception)
{
return exception is OperationCanceledException ||
exception is MqttCommunicationTimedOutException ||
exception is MqttCommunicationException;
exception is MqttCommunicationException ||
exception is MqttProtocolViolationException;
}
private static void WrapException(Exception exception)
static void WrapAndThrowException(Exception exception)
{
if (exception is IOException && exception.InnerException is SocketException innerException)
{
@@ -300,11 +403,15 @@ namespace MQTTnet.Adapter
if (exception is SocketException socketException)
{
if (socketException.SocketErrorCode == SocketError.ConnectionAborted ||
socketException.SocketErrorCode == SocketError.OperationAborted)
if (socketException.SocketErrorCode == SocketError.OperationAborted)
{
throw new OperationCanceledException();
}
if (socketException.SocketErrorCode == SocketError.ConnectionAborted)
{
throw new MqttCommunicationException(socketException);
}
}
if (exception is COMException comException)
@@ -5,12 +5,13 @@ namespace MQTTnet.Adapter
{
public class MqttConnectingFailedException : MqttCommunicationException
{
public MqttConnectingFailedException(MqttClientConnectResultCode resultCode)
: base($"Connecting with MQTT server failed ({resultCode.ToString()}).")
public MqttConnectingFailedException(MqttClientAuthenticateResult result)
: base($"Connecting with MQTT server failed ({result.ResultCode.ToString()}).")
{
ResultCode = resultCode;
Result = result;
}
public MqttClientConnectResultCode ResultCode { get; }
public MqttClientAuthenticateResult Result { get; }
public MqttClientConnectResultCode ResultCode => Result.ResultCode;
}
}
@@ -0,0 +1,84 @@
using System;
using System.IO;
using System.Linq;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.PacketInspection;
namespace MQTTnet.Adapter
{
public sealed class MqttPacketInspectorHandler
{
readonly MemoryStream _receivedPacketBuffer;
readonly IMqttPacketInspector _packetInspector;
readonly IMqttNetScopedLogger _logger;
public MqttPacketInspectorHandler(IMqttPacketInspector packetInspector, IMqttNetLogger logger)
{
_packetInspector = packetInspector;
if (packetInspector != null)
{
_receivedPacketBuffer = new MemoryStream();
}
if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger.CreateScopedLogger(nameof(MqttPacketInspectorHandler));
}
public void BeginReceivePacket()
{
_receivedPacketBuffer?.SetLength(0);
}
public void EndReceivePacket()
{
if (_packetInspector == null)
{
return;
}
var buffer = _receivedPacketBuffer.ToArray();
_receivedPacketBuffer.SetLength(0);
InspectPacket(buffer, MqttPacketFlowDirection.Inbound);
}
public void BeginSendPacket(ArraySegment<byte> buffer)
{
if (_packetInspector == null)
{
return;
}
// Create a copy of the actual packet so that the inspector gets no access
// to the internal buffers. This is waste of memory but this feature is only
// intended for debugging etc. so that this is OK.
var bufferCopy = buffer.ToArray();
InspectPacket(bufferCopy, MqttPacketFlowDirection.Outbound);
}
public void FillReceiveBuffer(byte[] buffer)
{
_receivedPacketBuffer?.Write(buffer, 0, buffer.Length);
}
void InspectPacket(byte[] buffer, MqttPacketFlowDirection direction)
{
try
{
var context = new ProcessMqttPacketContext
{
Buffer = buffer,
Direction = direction
};
_packetInspector.ProcessMqttPacket(context);
}
catch (Exception exception)
{
_logger.Error(exception, "Error while inspecting packet.");
}
}
}
}
+7 -6
View File
@@ -1,19 +1,20 @@
using MQTTnet.Formatter;
using System;
using MQTTnet.Formatter;
namespace MQTTnet.Adapter
{
public class ReceivedMqttPacket
public sealed class ReceivedMqttPacket
{
public ReceivedMqttPacket(byte fixedHeader, IMqttPacketBodyReader body, int totalLength)
public ReceivedMqttPacket(byte fixedHeader, IMqttPacketBodyReader bodyReader, int totalLength)
{
FixedHeader = fixedHeader;
Body = body;
BodyReader = bodyReader ?? throw new ArgumentNullException(nameof(bodyReader));
TotalLength = totalLength;
}
public byte FixedHeader { get; set; }
public byte FixedHeader { get; }
public IMqttPacketBodyReader Body { get; }
public IMqttPacketBodyReader BodyReader { get; }
public int TotalLength { get; }
}
@@ -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();
}
}

Some files were not shown because too many files have changed in this diff Show More