Compare commits

...
739 Commits
Author SHA1 Message Date
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
Christian Kratky f66da92299 Merge branch 'develop' 2019-06-27 10:02:59 +02:00
Christian Kratky 979df5f17e Fix broken nuget builds. 2019-06-27 10:02:47 +02:00
Christian Kratky d50c8153b2 Merge branch 'master' into develop 2019-06-26 11:42:44 +02:00
Christian Kratky b3ab7a1069 Set socket options to allow reusing address. 2019-06-24 13:46:51 +02:00
Christian Kratky 6af58ad90d Fix MQTTnet.Server startup colors. 2019-06-24 13:46:27 +02:00
Christian 5c36a2d402 Merge pull request #671 from SeppPenner/patch-1
Added dependents and MIT license badge to the readme.
2019-06-24 13:40:26 +02:00
HansM 6df70cc5ed Added dependents and MIT license badge to the readme. 2019-06-24 11:21:24 +02:00
Christian Kratky d5b0893e90 Merge branch 'master' into develop 2019-06-23 21:50:42 +02:00
Christian Kratky 2ed8e55394 Fix upload script. 2019-06-23 21:46:06 +02:00
Christian Kratky c5b6ca204d Merge branch 'develop' 2019-06-23 21:37:35 +02:00
Christian Kratky 7a767c7d2f Improve logging and exception handling when stopping the server. 2019-06-23 15:58:21 +02:00
Christian Kratky dd96cf98a8 Make storage update for managed client async. 2019-06-23 15:57:48 +02:00
Christian Kratky 6ee3d1640f Improve logging. 2019-06-23 15:57:12 +02:00
Christian Kratky 6f8272210c Fix MQTTnet.Server app settings to allow external connections. 2019-06-23 15:39:50 +02:00
Christian Kratky ce05cc9936 Fix MQTTnet.Server connection validation. 2019-06-23 15:39:07 +02:00
Christian Kratky 985c3084a8 Performance refactoring. 2019-06-23 12:37:55 +02:00
Christian Kratky 7b3be3a64f Update docs. 2019-06-23 12:37:41 +02:00
Christian Kratky c50fb740fc Add UnitTests. 2019-06-23 12:37:33 +02:00
Christian Kratky 5895a73f85 Merge remote-tracking branch 'origin/develop' into develop 2019-06-23 11:32:11 +02:00
Christian Kratky 961a497798 Performance refactoring. 2019-06-23 11:32:09 +02:00
Christian 6a90864c44 Merge pull request #666 from vbBerni/develop
fix Managed Client removes failed messages from message queue but not from storage manager
2019-06-23 11:30:31 +02:00
vbBerni a9017b8795 handle storage manager null 2019-06-22 22:31:48 +02:00
vbBerni f76e130283 fix for failed publishing messages get removed from the message queue but not from the storage manager 2019-06-19 16:33:54 +02:00
Christian Kratky 5a48b146b4 Merge branch 'master' into develop 2019-06-14 20:53:24 +02:00
Christian Kratky 1d1def3275 Remove nuget binary from repo. 2019-06-14 20:52:56 +02:00
Christian Kratky bd75a2440e Merge branch 'master' into develop 2019-06-14 20:43:33 +02:00
Christian Kratky 7a642802ed Merge branch 'develop' 2019-06-14 20:43:18 +02:00
Christian Kratky a8f8601bc5 Update docs. 2019-06-14 20:38:44 +02:00
Christian Kratky 0c7a5a992b Expose more properties of the connection validator context in MQTTnet.Server. Migrate return code to reason code. 2019-06-14 20:38:07 +02:00
Christian Kratky bd665c3d56 Expose more properties to connection validator context. 2019-06-14 20:37:06 +02:00
Christian Kratky 7e7b36aadf Update docs. 2019-06-14 20:35:45 +02:00
Christian Kratky a79c2484b3 Add MQTTnet.Server build for ARM. 2019-06-14 20:35:33 +02:00
Christian Kratky e4e46f0094 Add comments. 2019-06-11 20:51:23 +02:00
Christian Kratky 5a4c735b85 Refactor code. 2019-06-11 20:50:11 +02:00
Christian Kratky 42516942ac Update docs. 2019-06-09 14:14:40 +02:00
Christian Kratky 591ccfec29 Update authentication. 2019-06-09 14:13:50 +02:00
Christian Kratky ffc1d950da Add authorization for MQTTnet.Server 2019-06-09 00:10:26 +02:00
Christian Kratky 1c004ead6d Add support for altering the TopicFilter in subscription interceptor. 2019-06-07 20:40:24 +02:00
Christian Kratky b0ad6bda70 Add support for reset of connection statistics. Refactor keep alive monitor. 2019-06-06 21:12:32 +02:00
Christian Kratky 6262a16504 Add version to MQTTnet.Server. 2019-06-06 21:11:47 +02:00
Christian Kratky 0de683979d Fix versions in build script. 2019-06-06 21:11:20 +02:00
Christian Kratky 0a6f564446 Add self contained builds in build script. 2019-06-06 20:26:41 +02:00
Christian Kratky f0be3ef0cf Add UnitTests. 2019-06-06 20:26:21 +02:00
Christian Kratky f79eebdf64 Update docs. 2019-06-06 19:32:06 +02:00
Christian Kratky c3c0dcf313 Execute disconnected handler in new task. 2019-06-06 19:32:00 +02:00
Christian Kratky 60c6074953 Expose client certificate at MQTT connection validator. Make DualMode optional. 2019-06-06 19:31:43 +02:00
Christian Kratky 2b9b22def6 Expose new options in server TLS options. 2019-06-06 19:27:25 +02:00
Christian Kratky 5cfb092449 Add UnitTests. 2019-06-06 19:26:43 +02:00
Christian Kratky a450fc4e01 Add UnitTests. 2019-05-31 09:55:23 +02:00
Christian Kratky ffe9c57ae8 Add overload for setting message payload. 2019-05-27 22:45:56 +02:00
Christian Kratky 0257e31910 Add UnitTests. 2019-05-27 20:06:51 +02:00
Christian Kratky 7fe5f521dc Update docs. 2019-05-27 20:02:30 +02:00
Christian Kratky 2d03c267e4 Expose binary password to MqttConnectionValidatorContext. 2019-05-27 19:57:36 +02:00
Christian Kratky ccfe67e6a6 Fix wrong password handling (string -> byte[]) 2019-05-27 00:21:55 +02:00
Christian Kratky 98e17903ea Merge remote-tracking branch 'origin/develop' into develop 2019-05-26 23:53:19 +02:00
Christian c7d56a78f3 Merge pull request #628 from hezlog/develop
Fixed MQTTnet.noUWP.sln build issue.
2019-05-26 23:53:07 +02:00
Christian Kratky b491c74228 Merge remote-tracking branch 'origin/develop' into develop 2019-05-26 23:45:02 +02:00
Christian Kratky a2414f48ca Update Wiki samples. 2019-05-26 23:44:50 +02:00
Christian Kratky 396e0e1697 Add connected timestamp to connection status API. 2019-05-26 23:44:50 +02:00
Christian Kratky 01f6c959e1 Update publish profile. 2019-05-26 23:44:50 +02:00
Christian Kratky f425d87562 Add publish profiles. 2019-05-26 23:44:50 +02:00
Christian Kratky 6614b23ab8 Add extension library for WebSocket4Net usage. 2019-05-26 23:44:50 +02:00
Christian Kratky 02c9133a1c Update splash screen for MQTTnet.Server. 2019-05-26 23:44:50 +02:00
Christian Kratky 913afa3977 Add connack properties to authenticate result. 2019-05-26 23:44:50 +02:00
Christian Kratky e068286f15 Add subscribe options builder. 2019-05-26 23:44:50 +02:00
Christian Kratky 373fe8c72c Add connack properties to connect result. 2019-05-26 23:44:50 +02:00
Christian Kratky 396f040aae Add support for extended authentication exchange. 2019-05-26 23:44:50 +02:00
Christian Kratky c90b5f6fb2 Update UnitTests. 2019-05-26 23:44:50 +02:00
Christian Kratky 744b1b302b Create MQTTnet.Server package from publish output instead build files. 2019-05-26 23:44:50 +02:00
Christian Kratky 78e504dc2c Update Wiki samples. 2019-05-26 23:44:42 +02:00
Christian 79518d4a35 Merge pull request #634 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2019-05-23 19:04:55 +02:00
The Gitter Badger a50fb2a320 Add Gitter badge 2019-05-22 08:19:32 +00:00
hezlog 9fa9d22097 Fixed MQTTnet.noUWP.sln build issue. 2019-05-20 23:17:32 +08:00
Christian Kratky e4351b73bd Add connected timestamp to connection status API. 2019-05-19 22:23:10 +02:00
Christian Kratky 2d3fdd4faf Update publish profile. 2019-05-18 20:51:19 +02:00
Christian Kratky 0a509fd685 Add publish profiles. 2019-05-18 20:50:29 +02:00
Christian Kratky d1a17314ef Add extension library for WebSocket4Net usage. 2019-05-18 09:48:44 +02:00
Christian Kratky e96b66e9f8 Update splash screen for MQTTnet.Server. 2019-05-17 20:57:56 +02:00
Christian Kratky 80b05a8944 Add connack properties to authenticate result. 2019-05-17 20:57:40 +02:00
Christian Kratky ab3df2ba65 Add subscribe options builder. 2019-05-17 20:57:15 +02:00
Christian Kratky f169aaa79b Add connack properties to connect result. 2019-05-17 20:56:58 +02:00
Christian Kratky 231001850a Add support for extended authentication exchange. 2019-05-14 20:45:45 +02:00
Christian Kratky 6839970d41 Update UnitTests. 2019-05-14 20:40:58 +02:00
Christian Kratky 4df29be155 Create MQTTnet.Server package from publish output instead build files. 2019-05-14 20:40:44 +02:00
Christian Kratky c5cfede231 Merge branch 'master' into develop 2019-05-13 07:25:56 +02:00
Christian Kratky c22b6033e3 Accept multiple SubscriptionIdentifiers for PUBLISH packets. 2019-05-12 17:26:36 +02:00
Christian Kratky 27476a9194 Merge remote-tracking branch 'origin/master' 2019-05-12 00:18:54 +02:00
Christian Kratky 12973a4179 Fix issues in MQTTv5 packet encoding and decoding. 2019-05-12 00:18:48 +02:00
Christian 01b437dc08 Set theme jekyll-theme-hacker 2019-05-11 09:50:41 +02:00
Christian Kratky ac88f0a05a Merge branch 'develop' 2019-05-11 09:47:31 +02:00
Christian Kratky b02f30844c Add new options for _MqttClientOptionsBuilder_. 2019-05-10 21:55:46 +02:00
Christian Kratky 1a8bcae47c Add authentication result to disconnected handler. 2019-05-09 22:08:56 +02:00
Christian Kratky 664549ab93 Fix message encoding bugs. 2019-05-08 00:12:27 +02:00
Christian 914d2b641f Update appveyor.yml 2019-05-06 21:14:51 +02:00
Christian 0cc0fcf5d9 Update appveyor.yml 2019-05-06 21:07:46 +02:00
Christian Kratky 5980cbd944 Fix build scripts to use 4.6 binaries. 2019-05-06 20:27:33 +02:00
Christian Kratky 3ef7f60a18 Fix wrong IsSessionPresent flag. 2019-05-06 20:27:24 +02:00
Christian Kratky efef23e3f5 Merge branch 'develop' 2019-05-06 20:24:12 +02:00
Christian Kratky 53ab2ac140 Add Wiki Code. 2019-05-06 20:22:41 +02:00
Christian Kratky 2ecbd83d06 Add UnitTests. 2019-05-06 20:22:20 +02:00
Christian Kratky a278b6189b Refactor empty payload detection for retained messages. 2019-05-01 19:41:34 +02:00
Christian Kratky cdbdfdec6d Add UnitTests. 2019-05-01 19:39:10 +02:00
Christian Kratky 808c2da5f6 Add PacketIdentifier for QoS 2. 2019-04-28 23:03:54 +02:00
Christian Kratky 6ed3b0cedd Add ClientId for application messages published by the server. 2019-04-24 21:37:29 +02:00
Christian Kratky 9da3377aa7 Fix credential generation. 2019-04-24 20:19:55 +02:00
Christian Kratky 0cac2aa1bc Fix broken log message. 2019-04-24 20:19:46 +02:00
Christian Kratky 2d59b5c1ac Refactoring. 2019-04-23 14:49:19 +02:00
Christian Kratky 9dfa0b32e4 Add extension methods for server. 2019-04-23 14:49:12 +02:00
Christian Kratky 20a7579156 Fix issues in ApplicationMessageInterceptor. 2019-04-23 14:48:51 +02:00
Christian Kratky c7409c2ff4 Fix missing endpoint in client status. 2019-04-23 14:48:38 +02:00
Christian Kratky d4c6fb44c9 Expose PacketIdentifier in PublishResult. 2019-04-23 14:47:42 +02:00
Christian Kratky e6cf23aebd Add API controllers for MQTTnet.Server. 2019-04-23 14:46:13 +02:00
Christian Kratky 0fec860b25 Add UnitTests. 2019-04-23 14:46:02 +02:00
Christian Kratky 2c927c5995 Cleanup. 2019-04-22 10:59:39 +02:00
Christian Kratky 6399172582 Improve connection disposal. 2019-04-22 10:50:47 +02:00
Christian Kratky 5c903e6fbf Improve connection handling. 2019-04-20 21:12:30 +02:00
Christian Kratky f60bbf7dd7 MQTTnet.Server startup cleanup. 2019-04-20 20:59:28 +02:00
Christian Kratky 519bb05aac Fix broken code. 2019-04-18 00:09:19 +02:00
Christian Kratky a8434d1b58 Expose results of publish operations for MQTTv5. 2019-04-18 00:01:22 +02:00
Christian Kratky 420b35e37d Merge remote-tracking branch 'origin/develop' into develop 2019-04-17 21:44:12 +02:00
Christian Kratky a25c8cd4c7 Fix some minor TODOs. 2019-04-17 21:44:09 +02:00
Christian 8ac77558af Merge pull request #593 from JanEggers/fixTodo
fixed todo in MqttConnectionContext
2019-04-17 19:14:00 +02:00
JanEggers 953578eba2 fixed todo in MqttConnectionContext 2019-04-17 09:47:17 +02:00
Christian 527713ccf8 Merge pull request #592 from JanEggers/spanV2
performance improvements span based serializers
2019-04-16 19:28:38 +02:00
JanEggers 477e2d23ab added benchmark option to compare netfx and core runtime 2019-04-15 15:52:51 +02:00
JanEggers 03c61ad82c fixed tests and added testcase for user property serialization 2019-04-15 15:37:15 +02:00
JanEggers 9475ccd0d8 revert accidential change 2019-04-15 15:31:31 +02:00
JanEggers 73b051d159 reuse reader 2019-04-15 15:00:09 +02:00
JanEggers a9944def68 added span based writer 2019-04-15 14:43:49 +02:00
JanEggers aee10ba6fa added netcore 2.1 build 2019-04-15 14:24:27 +02:00
JanEggers cfc1b27950 fixed build and added implementations for new read functions 2019-04-15 14:14:32 +02:00
JanEggers 149d01e173 added tests 2019-04-15 14:09:22 +02:00
JanEggers 888e1797d7 fixed cherry pick 2019-04-15 14:04:21 +02:00
JanEggers f8ade2daf4 slight improvements 2019-04-15 14:04:06 +02:00
JanEggers a85792c392 fixed another issue 2019-04-15 14:00:22 +02:00
JanEggers fbca8a6dc1 span based reader 2019-04-15 14:00:00 +02:00
Christian Kratky 732ea84caa Update build script. 2019-04-13 00:09:10 +02:00
Christian Kratky 65896269da Improve protocol version detection. 2019-04-11 20:13:30 +02:00
Christian Kratky 631f660d5c Add MQTTnet.Server to build script. 2019-04-11 20:13:08 +02:00
Christian Kratky 7f08371532 Update tests. 2019-04-08 22:29:52 +02:00
Christian Kratky 1afd59325f Add validations for client options builder. 2019-04-08 22:29:46 +02:00
Christian Kratky 45c033f401 Improve payload handling and allocation. 2019-04-08 22:29:29 +02:00
Christian Kratky 7855eccb78 Update solution files. 2019-04-07 20:54:16 +02:00
Christian Kratky d51300d32d Update build process. 2019-04-07 20:45:16 +02:00
Christian Kratky 61b10a8b56 Add extension methods. 2019-04-07 19:58:01 +02:00
Christian Kratky dbee941dcc Update nuget packages. 2019-04-04 22:00:40 +02:00
Christian Kratky fd7c98d0d1 Update docs. 2019-04-03 23:46:32 +02:00
Christian Kratky c911797f1b Fix broken config in MQTTnet.Server. 2019-04-03 23:46:26 +02:00
Christian Kratky b5a1d3a69f Add more config values for TCP connections. 2019-04-03 23:46:13 +02:00
Christian Kratky cdeb073bb0 Fix disposal of SSL streams. 2019-04-03 23:45:53 +02:00
Christian Kratky a8db0dd3d6 Rename tests. 2019-04-03 23:44:48 +02:00
Christian Kratky 2267770a72 Make internal message of server async. 2019-04-02 21:51:26 +02:00
Christian Kratky 35ee732045 Remove obsolete files from MQTTnet.Server. 2019-04-02 21:50:49 +02:00
Christian Kratky ad5834dd1f Add long runnings tests for all QoS levels. 2019-04-02 21:50:16 +02:00
Christian Kratky a7204234f6 Update docs. 2019-03-24 10:40:59 +01:00
Christian Kratky e8c33077b7 Update build script. 2019-03-24 10:35:42 +01:00
Christian Kratky bd86dae8a9 Update build script. 2019-03-24 10:19:43 +01:00
Christian Kratky 7188aaf79d Merge branch 'master' into develop 2019-03-24 10:06:09 +01:00
Christian Kratky bafcc81672 Update nuspecs. 2019-03-24 10:05:45 +01:00
Christian Kratky d0f1659eec Remove obsolete methods. 2019-03-24 10:05:38 +01:00
Christian Kratky 11a5b5a080 Add queue with async support to free up threads. 2019-03-22 23:12:37 +01:00
Christian Kratky 7ed5580352 Fix breaking changes. 2019-03-22 21:08:38 +01:00
Christian Kratky efc6f124b4 Merge remote-tracking branch 'origin/develop' into develop 2019-03-22 20:37:16 +01:00
Christian Kratky 7c3d88f62d Add validation for topics before publishing. 2019-03-22 20:37:14 +01:00
Christian b383a54416 Merge pull request #547 from vbBerni/develop
Fix Managed Client should dispose inner mqtt client #527
2019-03-22 20:31:24 +01:00
Christian Kratky 673fc5e20c Add windows startup script. 2019-03-16 09:55:45 +01:00
Christian Kratky f2b9642712 Add linuc startup script. 2019-03-16 09:55:15 +01:00
Christian 4f03f22afb Update README.md 2019-03-13 21:22:24 +01:00
Christian 27a4af6070 Update README.md 2019-03-13 21:20:09 +01:00
Christian 0184ce400c Update README.md 2019-03-13 21:19:55 +01:00
Christian Kratky 653ea8a102 Add MQTTnet debug logging. 2019-03-11 21:32:36 +01:00
Christian Kratky 3450889e84 Refactor settings. 2019-03-11 21:15:02 +01:00
Christian Kratky 1311535eed Added support for persisted retained messages. 2019-03-11 20:15:12 +01:00
Christian Kratky e1799ea6a3 Extend configuration. 2019-03-11 18:43:39 +01:00
Christian Kratky cd76f434e3 Fix breaking changes. 2019-03-10 20:12:04 +01:00
Christian Kratky fd91170aee Merge branch 'master' into develop 2019-03-10 20:00:49 +01:00
Christian Kratky cd1bfc3a10 Auto stash before merge of "develop" and "feature/server-project-bootstrap" 2019-03-10 19:58:02 +01:00
Christian Kratky f074e9ed04 Merge branch 'feature/server-project-bootstrap' into develop 2019-03-10 19:57:32 +01:00
Christian Kratky 562a5304f6 Add flag for secure connections. 2019-03-10 19:52:55 +01:00
Kiarash 1e697a94a1 Add Kesterl Settings into appsettings 2019-03-10 17:18:20 +01:00
Kiarash 0e2c3abd05 Add missing method for setting encrpted IPv6 address.
* Clean up
2019-03-10 16:34:18 +01:00
Kiarash 7321774c45 Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 16:02:45 +01:00
Kiarash 4a65cab769 Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 15:59:35 +01:00
Christian Kratky 510c3bd0bf Move logger into WebSocketServerAdapter instead of creating a new instance. 2019-03-10 15:58:55 +01:00
Kiarash 0c056b511e Fix and clean up 2019-03-10 15:56:11 +01:00
Christian Kratky 2ca6866c5e Remove obsolete code. 2019-03-10 14:55:17 +01:00
Kiarash ebcce9b8be Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 13:58:37 +01:00
Kiarash 9e7c70e649 Add new configuartion model
Added new models for review
2019-03-10 13:58:18 +01:00
Christian Kratky bef0860e53 Add support for WebSocket connections. 2019-03-10 12:10:11 +01:00
Christian Kratky 67c9177731 Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2019-03-10 10:12:26 +01:00
Christian Kratky 007991f073 Update docs. 2019-03-10 10:11:43 +01:00
Christian 532dddeb6c Merge pull request #526 from JohBa/patch-2
Don't cancel token before stop session manager
2019-03-10 10:08:46 +01:00
Christian Kratky 9070087fad Add flag for indicating if application message processing has failed. 2019-03-10 09:51:49 +01:00
Christian Kratky de8bcb7f37 Update docs. 2019-03-09 19:24:04 +01:00
Christian 5090cfb411 Fix memory leak in AsyncAutoResetEvent. 2019-03-09 19:20:34 +01:00
Christian Kratky 6e64d653c5 Hide connect password from logs. 2019-03-08 23:48:49 +01:00
Christian Kratky 461bc6e594 Add MQTTnet.Server to NoUWP solution. 2019-03-08 23:48:28 +01:00
Christian Kratky 0d95dc563c Update documents. 2019-03-08 23:48:07 +01:00
Christian Kratky 03bfc5f00b Refactor event handler namings. 2019-03-08 23:47:51 +01:00
Christian Kratky 8708609498 Add more function mappings for MQTTnet Server. 2019-03-06 22:42:00 +01:00
Christian dffc27c1f4 Migrate events in server to async handlers. 2019-03-05 21:37:30 +01:00
Christian 6f5f507323 Extend MQTTnet.Server application. 2019-03-05 21:37:00 +01:00
Christian 26d6d817cd Fix memory leak in AsyncAutoResetEvent. 2019-03-05 07:47:31 +01:00
Kiarash Ghiaseddin b68247f56d WIP
First draft for MQTTnetServer project
* Basic support for settings
* Nasty code for setting up kestrel from appsettings.json
2019-03-04 21:13:22 +01:00
Christian 3b02a5f6aa Fix NullRefException when cancelling the server. 2019-02-23 10:40:17 +01:00
Christian 09718a00e7 Add handlers to variable before using to avoid NullRefExceptions. 2019-02-23 10:13:12 +01:00
Christian ecc2cd5f0c Merge pull request #555 from BennyM/develop
When no handlers are configured the client should not blow up
2019-02-23 10:07:24 +01:00
Christian 618580dc15 Merge pull request #553 from dpsenner/feature/MqttClient-add-missing-async-extensions
Add extension methods that provide a simpler api for IMqttClient and IManagedMqttClient
2019-02-22 20:28:53 +01:00
BennyM 4860cec6c7 When no handlers are configured the client should not blow up 2019-02-19 21:40:11 +01:00
Dominik Psenner b9e0dbf150 Add extension methods that provide a simpler api for IMqttClient and IManagedMqttClient connect/disconnect when the handlers do not need async/await 2019-02-18 08:02:09 +01:00
vbBerni 2a4eb460da StopAsync now waits until the managed client is stoped and more typical disposing of internal client 2019-02-16 22:23:45 +01:00
Christian 087c622122 Merge pull request #551 from dpsenner/feature/add-async-handlers-for-connected-and-disconnected
Add async handler interfaces for connected and disconnected to allow async code on connect
2019-02-16 19:04:06 +01:00
Dominik Psenner 2000de15e7 Add async handlers for connect and disconnect, too
.. this allows a client to properly async publish on connect.
2019-02-15 17:02:33 +01:00
Dominik Psenner 5e6b902430 Add convenience extensions to the managed client 2019-02-15 16:55:52 +01:00
Dominik Psenner a1f414a06d Add async handler interfaces for connected and disconnected to allow async code to execute on connect 2019-02-15 15:02:15 +01:00
Berni de3a39bdc2 Fix Managed Client should dispose inner mqtt client #527 2019-02-07 16:46:58 +01:00
Christian 6c5c9e5bf2 Merge pull request #540 from vbBerni/develop
fix logger logId not used in ManagedMqttClient
2019-01-31 19:57:09 +01:00
Berni 506873ed5b fix logger logId not used in ManagedMqttClient 2019-01-31 15:50:01 +01:00
Christian Kratky 6a2bded181 Refactor session and connection handling in server. Fix QoS level 2 issues. 2019-01-27 11:15:32 +01:00
Christian Kratky ebf0e91ab8 Refactor subscribe and unsubscribe to support MQTTv5. 2019-01-21 21:38:39 +01:00
Johannes Bäurle 107e96ff7d Don't cancel token before stop session manager 2019-01-07 11:54:10 +01:00
Christian Kratky 0d6e244f84 Refactor UnitTests. 2019-01-06 13:31:27 +01:00
Christian Kratky 96a67579e2 Improve session handling. 2019-01-01 19:18:54 +01:00
Christian Kratky 4cba814716 Cleanup. 2018-12-27 23:10:52 +01:00
Christian Kratky b527059b72 Fix session takeover. 2018-12-27 23:05:57 +01:00
Christian Kratky c0507fcc55 Refactor interceptors etc. to support async. 2018-12-27 22:41:41 +01:00
Christian 38f2453c92 Update README.md 2018-12-22 20:25:53 +01:00
Christian Kratky 058bb65d31 Merge from develop. 2018-12-22 09:40:47 +01:00
Christian Kratky 38b215e9b5 Merge branch 'develop' into feature/MQTTv5 2018-12-22 09:38:12 +01:00
Christian Kratky 45df33c9a5 Update nuspec. 2018-12-22 09:33:44 +01:00
Christian Kratky 89becaa191 Fix build script. 2018-12-22 09:28:51 +01:00
Christian Kratky 6c87e4e039 Replace nuget version with placeholder. 2018-12-22 09:26:52 +01:00
Christian Kratky cbe06d6b87 Merge from master. 2018-12-21 00:21:42 +01:00
Christian 4fed80c2d0 Update appveyor.yml 2018-12-20 21:08:07 +01:00
Christian Kratky 74e4fd8b3f Update test certificate. 2018-12-20 20:54:37 +01:00
Christian Kratky cc113a6c34 Refactor namespaces. 2018-12-20 20:53:29 +01:00
Christian fca9876111 Delete .travis.yml 2018-12-19 00:10:10 +01:00
Christian ac9f6a36f8 Update appveyor.yml 2018-12-19 00:06:51 +01:00
Christian 929b60e044 Update appveyor.yml 2018-12-18 21:32:46 +01:00
Christian acb433dd4c Update appveyor.yml 2018-12-18 20:23:18 +01:00
Christian c4e8bf7f39 Update appveyor.yml 2018-12-18 20:12:09 +01:00
Christian ba4fdfb51c Merge pull request #497 from cquesnel/feature/add-websocket-parameters
Add custom WebSocket parameters
2018-12-14 21:37:04 +01:00
Charles Quesnel dfda916283 Use default parameter instead of overload 2018-12-13 14:54:31 -05:00
Charles Quesnel 40326df9a9 Fix typo in 'Cookie' 2018-12-13 14:08:53 -05:00
Charles Quesnel a94444098a Remove unused usings 2018-12-13 13:01:34 -05:00
Charles Quesnel 0c13e7a504 Add overload to allow passing custom request headers and cookies when connecting with WS 2018-12-13 12:56:47 -05:00
Christian Kratky 0dba57fe75 Cleanup code. 2018-12-09 21:04:14 +01:00
Christian Kratky 6483f896c1 Merge from develop. 2018-12-09 20:48:46 +01:00
Christian Kratky 8fa9943c3d Merge branch 'master' into develop 2018-12-09 19:44:17 +01:00
Christian Kratky 195357835b Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2018-12-09 19:42:03 +01:00
Christian Kratky 28b2562112 Fix client session disposal in server. 2018-12-09 17:35:46 +01:00
Christian Kratky ab24368de1 Update docs. 2018-12-08 13:46:40 +01:00
Christian Kratky 9b51404b4d Add Unit Tests. 2018-12-06 21:35:42 +01:00
Christian Kratky 619eaf284d Add readonly property for client options. 2018-12-03 21:20:11 +01:00
Christian Kratky 86c348df58 Stop existing sessions before takeover from another client. 2018-12-02 21:50:16 +01:00
Christian Kratky fdb2ec897c Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-12-01 11:00:09 +01:00
Christian Kratky b091fee554 Reset the keep alive monitor if a session is being resumed from a different (or same) client. 2018-12-01 11:00:00 +01:00
Christian 14ec6ee793 Merge pull request #484 from fogzot/feature-msbuild-conditions
Feature msbuild conditions
2018-12-01 10:50:39 +01:00
Federico Di Gregorio 0cfef0649a Fixed appveyor configuration to use full solution 2018-11-30 09:38:10 +01:00
Federico Di Gregorio 7292af7db4 Added solution that does not include UWP 2018-11-30 09:26:22 +01:00
Federico Di Gregorio bc1a197c4f Align conditions in dependent project with conditions in MQTTnet 2018-11-30 09:26:02 +01:00
Christian Kratky ccc275902f Fix wrong retain flag when distributing messages. 2018-11-28 21:35:50 +01:00
Christian Kratky 0f5fb8aa3a Add more pacakges. 2018-11-28 21:11:23 +01:00
Christian Kratky 83eca982e9 Update nugets. 2018-11-24 20:21:05 +01:00
Christian Kratky 017f17a6b1 Fix UnitTests. 2018-11-24 20:19:16 +01:00
Christian Kratky b3564e01a4 Update docs. 2018-11-23 22:57:34 +01:00
Christian Kratky 43105f71d8 Refactor removal from blocking queue. 2018-11-23 22:56:10 +01:00
Christian Kratky 40c408a9c0 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-11-23 22:51:07 +01:00
Christian Kratky 7baff7c080 Refactor property definition for packets. 2018-11-23 22:50:44 +01:00
Christian 91a918d30b Merge pull request #479 from PaulFake/patch-1
Fix for two issues with the managed message queue cap
2018-11-23 22:48:40 +01:00
Paul Fake 2a93fc18e4 Made comparison function static 2018-11-21 21:44:26 -05:00
Paul Fake 31de6ee186 Delegate comparison function 2018-11-21 21:39:42 -05:00
Paul Fake 74d59673a8 Delegate for comparisons 2018-11-21 21:38:06 -05:00
Paul Fake d1c3d9b453 Removed unnecessary code 2018-11-21 21:37:01 -05:00
Paul Fake baa9241216 Revert "Changes to this file no longer needed"
This reverts commit 2c6c3ac6a4.
2018-11-21 21:35:15 -05:00
Paul Fake 2c6c3ac6a4 Changes to this file no longer needed 2018-11-21 20:47:12 -05:00
Paul Fake b2c31331b6 Peek-and-publish model
We had been seeing an issue in which the queue could grow larger than the configured cap.  I examined the code and saw that this could happen if _mqttClient.PublishAsync() throws an exception, in which case a message can be re-enqueued without honoring the cap.  Furthermore, I saw that it was possible for the DropOldestQueuedMessage strategy to drop messages that were not actually the oldest ones, because when re-enqueueing the messages in the queue are no longer ordered by the original time they entered the queue.  It made sense to us to peek at the message when publishing rather than dequeue it, so that when re-enqueueing after an exception 1) the cap is still honored and 2) the order of queued messages isn't altered.  It's ok if another thread removes the message that's currently being published from the queue due to the cap, because all we have to do then is check if it's already been removed before removing it ourselves.
2018-11-19 21:20:50 -05:00
Paul Fake 9ff39c1fd9 New functions
This is to support the peek-and-publish model for the managed client
2018-11-19 21:11:47 -05:00
Paul Fake 210d57b254 IEquatable for speed
IEquatable for speed in using EqualityComparer<TItem>.Default.Equals
2018-11-19 21:09:36 -05:00
Christian Kratky 7292cedd2f Encode ConnAck packet. 2018-11-19 00:17:19 +01:00
Christian Kratky 48d5afa799 Refactor namings of serializers etc. 2018-11-19 00:14:15 +01:00
Christian Kratky 3db22eea51 Remove dedicated V3 messages. 2018-11-18 22:04:39 +01:00
Christian Kratky 2fbb44ec66 Add more property implementations. 2018-11-18 21:54:40 +01:00
Christian Kratky d7b98080f5 Refactor unit test for server events. 2018-11-18 11:20:36 +01:00
Christian Kratky 3e7b41e712 Refactor code. 2018-11-17 20:24:23 +01:00
Christian Kratky 5f18f35e02 Refactor task usage in client. 2018-11-17 20:23:52 +01:00
Christian Kratky af39e87703 Refactor code. 2018-11-17 20:23:20 +01:00
Christian Kratky ace25af0e8 Added package properties. 2018-11-16 23:11:26 +01:00
Christian Kratky 8d78455414 Fix breaking changes. 2018-11-16 22:18:59 +01:00
Christian Kratky fed16d7710 Merge from develop. 2018-11-16 22:16:21 +01:00
Christian Kratky fcff3a2c8d Update docs. 2018-11-16 22:12:29 +01:00
Christian 803dd6f64e Merge pull request #476 from PaulFake/patch-1
Check for pending disconnect in ThrowIfNotConnected
2018-11-16 22:08:49 +01:00
Paul Fake a1e258eb24 Check for pending disconnect in ThrowIfNotConnected
This might be a little controversial, but it worked for us to correct a problem in which messages get stuck in the managed client storage queue (and are thrown out of the regular message queue without being published!) in the case of a failed connection.  What we were seeing was that ManagedMqttClient.TryPublishQueuedMessage() was discarding a dequeued message without ever removing it from the storage queue because of an OperationCancelledException thrown by MqttClient.PublishAsync().  Tracing the code back, we found that when the connection is interrupted, after the timeout period MqttClient.InitiateDisconnect() would set the cancellation token, and the managed client would continue to try to publish, eventually calling through to MqttClient.SendAndReceiveAsync(), which would throw because the cancellation token is set.  Looking back over the code, we saw that MqttClient.PublishAsync() has a call to ThrowIfNotConnected() at the top, which told us that the intent was to not allow this function to be called after a disconnect.  But the disconnect was still pending, and the function wasn't behaving correctly in this state, so we reasoned that it's best to throw if the disconnect is pending.
2018-11-14 11:25:12 -05:00
Christian Kratky e9df698a1f Update nuget versions. 2018-11-05 22:40:48 +01:00
Christian Kratky bddcbf6999 Refactor code. 2018-11-05 22:39:56 +01:00
Christian be22e2551d Merge pull request #471 from JanEggers/develop
updated nuget spec according to csproj
2018-11-05 22:24:31 +01:00
Jan Eggers 4e01c7f13d updated nuget spec according to csproj 2018-11-05 06:45:40 +01:00
Christian Kratky 7181813f12 Fix pending messages overflow strategy issue. 2018-11-04 20:33:44 +01:00
Christian Kratky 6fc9f12c34 Refactor task await. 2018-11-04 13:18:42 +01:00
Christian cc4e37fa40 Merge pull request #469 from JanEggers/fixedConcurrentWrites
fixed parallel writes
2018-11-04 13:16:18 +01:00
JanEggers ccadd4e41a updated release notes 2018-11-04 11:44:25 +01:00
JanEggers a5caab62f8 fixed parallel writes 2018-11-04 11:39:12 +01:00
Christian Kratky 2bff218806 Update docs. 2018-10-29 21:49:01 +01:00
Christian Kratky 95c30a2843 Update docs. 2018-10-29 21:48:12 +01:00
Christian Kratky 28efbcdb3d Add max pending messages options for ManagedClient. 2018-10-29 21:45:01 +01:00
Christian Kratky ca7952ab33 Remove wrong setter. 2018-10-29 20:35:22 +01:00
Christian Kratky 62693af196 Merge from master. 2018-10-20 00:34:28 +02:00
Christian Kratky 5abee2512f Update nuget packages. 2018-10-20 00:32:53 +02:00
Christian Kratky c9a6155834 Update docs. 2018-10-19 23:57:09 +02:00
Christian Kratky aad3ab903f Expose retained messages to server interface. 2018-10-19 23:56:32 +02:00
Christian Kratky 4c76a898b6 Add new UnitTests. 2018-10-19 23:55:02 +02:00
Christian d273148bc5 Update README.md
Reorder references alphabetically.
2018-10-14 12:05:08 +02:00
Christian 5314f5c67a Merge pull request #444 from keesschollaart81/patch-1
Referencing the MQTT Bindings for Azure Functions
2018-10-14 12:03:07 +02:00
Kees Schollaart 22aab44d49 Referencing my MQTT Bindings for Azure Functions
Hi, if you're interested, hereby a reference to my work on MQTT Bindings for Azure Functions where I used this library. Thanks for the excellent work. More background [over here](http://case.schollaart.net/2018/09/22/mqtt-and-azure-functions.html)
2018-10-14 11:46:32 +02:00
Christian b819746165 Merge pull request #430 from JanEggers/fix#421
fixed #421
2018-10-07 15:52:17 +02:00
JanEggers 73d33e2200 fixed #421 2018-10-07 15:20:13 +02:00
Christian 740bc3aa30 Merge pull request #429 from JanEggers/supportTlsProtolOptionOnServer
added ability to specify tls protocol version
2018-10-07 15:03:17 +02:00
JanEggers 583b32f17a updated release notes 2018-10-07 13:24:07 +02:00
JanEggers b7ab29473b added ability to specify tls protocol version 2018-10-07 12:10:26 +02:00
Christian Kratky ffc4f1408a Merge develop. 2018-10-06 13:13:40 +02:00
Christian Kratky c8b3066883 Update docs. 2018-10-06 13:12:15 +02:00
Christian Kratky fb4f89b412 Replace TaskCompletionSource in Client with Interlocked gate. 2018-10-04 22:30:03 +02:00
Christian Kratky 6bee6a0469 Update docs. 2018-10-04 20:58:15 +02:00
Christian Kratky 0c2ab9b231 Fix a deadlock when an exception is fired while connecting. 2018-10-04 20:53:02 +02:00
Christian Kratky 03bef4c15d Fix revocation checks in certificate validator. 2018-10-01 21:50:54 +02:00
Christian Kratky ba62ca7306 Update docs. 2018-10-01 21:36:15 +02:00
Christian Kratky 56a1530cee Add a method for clearing all retained messages at the server. 2018-09-29 11:49:02 +02:00
Christian Kratky 699cd5fc23 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-09-28 22:51:27 +02:00
Christian Kratky 381c59d1e5 Update readme. 2018-09-28 22:51:16 +02:00
Christian Kratky 70f4dc9e10 Change log level of retained message changes. 2018-09-28 22:51:05 +02:00
Christian 0367ad31f1 Merge pull request #422 from ifit/client-cancel-task
Client cancel task
2018-09-28 22:49:11 +02:00
Christian 5c6bcdbca6 Merge branch 'develop' into client-cancel-task 2018-09-28 22:49:00 +02:00
Andre Crabb 400c0f05ad * Adds false param to Cancel call. 2018-09-28 14:07:04 -04:00
Andre Crabb 00df7c9b7b * More change tabs to spaces. 2018-09-28 11:01:07 -04:00
Andre Crabb a272ed7daa * Change tabs to spaces. 2018-09-28 11:00:18 -04:00
Andre Crabb b2e7a2e370 Change from logging Info to Verbose 2018-09-21 15:44:31 -04:00
Andre Crabb 39bc70cbf0 * Cancel the TokenSource when disposing or nulling it out for the MqttClient 2018-09-20 11:08:33 -04:00
Christian Kratky 682298b69f Fix issue in pending messages handling for managed client. 2018-09-13 09:29:26 +02:00
Christian Kratky 028a39ec25 Update docs. 2018-09-13 09:19:15 +02:00
Christian Kratky 3b104049b4 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-08-25 17:33:58 +02:00
Christian dd83a360b4 Merge pull request #402 from JanEggers/AspNetMqttServerOptionsBuilder
added AspNetMqttServerOptionsBuilder
2018-08-25 16:56:34 +02:00
JanEggers 976c62d9c2 added back the old function and added new overload 2018-08-25 12:08:42 +02:00
JanEggers 4cc9f12a03 added AspNetMqttServerOptionsBuilder 2018-08-21 21:32:03 +02:00
Christian Kratky 0b5a751c56 Add all methods of the factory to the factory interfaces. 2018-08-15 17:48:28 +02:00
Christian Kratky 5a59cd278c Add serializer adapter. 2018-08-06 20:36:15 +02:00
Christian Kratky cdb05e5894 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-08-04 12:30:21 +02:00
Christian Kratky 6c08b5caf3 Update docs. 2018-08-04 12:30:08 +02:00
Christian d5b53f3712 Merge pull request #384 from cstichlberger/managed_client_fix_unsubscription_overtaking_subscription
Prevent unsubscription overtaking later subscription
2018-08-04 12:28:04 +02:00
Christoph Stichlberger 80fbb2f0b2 Prevent unsubscription overtaking later subscription 2018-08-02 16:25:14 +02:00
Christian Kratky b4f90decc7 Fix unit tests to allow release builds. 2018-07-27 17:20:19 +02:00
Christian Kratky 61b324043a Refactoring 2018-07-26 20:02:11 +02:00
Christian Kratky 2ced921008 Refactoring. 2018-07-26 14:48:40 +02:00
Christian 1e2fee0f33 Merge pull request #343 from JanEggers/ServerShutdown
Server shutdown
2018-07-26 14:45:44 +02:00
Christian ac36c9c406 Merge branch 'develop' into ServerShutdown 2018-07-26 14:45:25 +02:00
Christian Kratky f70c79aaf9 Refactor options. 2018-07-26 11:34:24 +02:00
Christian Kratky 0839fa5757 Update docs. 2018-07-26 10:43:40 +02:00
Christian Kratky 60bc4ebcee Refactor proxy usage and support. Refactor TLS parameter usage. 2018-07-26 10:35:52 +02:00
Christian 65e239652d Merge pull request #364 from PitySOFT/webproxy
Add proxy settings for WebSocket connections for .NET 451 and 461 and add option to specify the SSLProtocol and CertificateValidationCallback  in TLS options, SSLProtocol default is TLS1.2
2018-07-26 10:04:52 +02:00
Christian Kratky 6b9015a928 Fix order of ClientConnected and ClientDisconnected events. 2018-07-25 20:18:27 +02:00
Christian Kratky a740c38ee6 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-24 14:06:18 +02:00
Christian Kratky 603639126e Fix issue in processing of server messages. 2018-07-24 13:49:23 +02:00
JanEggers 043cfdb3f9 fixed deadlock and object disposed exception 2018-07-23 17:58:29 +02:00
Christian b0da4b2b2d Merge pull request #372 from jenscski/LogFix
Small fix for inconsistent client name in log
2018-07-22 21:10:05 +02:00
Christian 5402859a30 Merge pull request #368 from jenscski/ClientKeepAliveMonitor
Fix pause/resume of ClientKeepAliveMonitor
2018-07-22 21:09:21 +02:00
Jens-Christian Skibakk 2b10200101 Small fix for inconsistent client name in log 2018-07-22 20:09:37 +02:00
Jens-Christian Skibakk 55e8927ab7 Fix pause/resume of ClientKeepAliveMonitor 2018-07-20 14:13:21 +02:00
JanEggers d30fe61264 fixed missing waits 2018-07-19 21:13:29 +02:00
JanEggers f7ea2d29e1 prove its broken 2018-07-19 21:13:28 +02:00
JanEggers e6cfef5295 fixed disconnect to be triggered just once 2018-07-19 21:13:28 +02:00
JanEggers 0dea9e6a2b changed waiting condition 2018-07-19 21:13:28 +02:00
JanEggers ae80de26ec addressed feedback 2018-07-19 21:13:28 +02:00
JanEggers 53bd2a0960 fixed blocking code in networkstrem and reduced sleep in tests 2018-07-19 21:13:28 +02:00
JanEggers b55f5ff298 event is triggered but something is blocking 2018-07-19 21:13:27 +02:00
JanEggers 21048b51ae prove there is something wrong 2018-07-19 21:13:27 +02:00
Christian Kratky 773fd09166 Merge branch 'master' into develop 2018-07-19 21:02:37 +02:00
Christian 57532a290a Merge pull request #365 from jenscski/DotnetCliBuild
Skip build uap10.0 when using dotnet cli
2018-07-19 18:58:48 +02:00
Jens-Christian Skibakk 740a35b018 Skip build uap10.0 when using dotnet cli 2018-07-18 19:54:07 +02:00
Marius Ruginosu 6e995230a7 Created overload methods for WithTls default values 2018-07-18 16:54:19 +03:00
Marius Ruginosu 65a8b091b9 Add option to specify the SSLProtocol and CertificateValidationCallback in TLS options, SSLProtocol default is TLS1.2 2018-07-18 12:19:09 +03:00
Marius Ruginosu fa34908d82 Add proxy settings for WebSocket connections for .NET 451 and 461 2018-07-18 10:51:45 +03:00
Christian Kratky b09eb1213c Refactor logging. 2018-07-08 22:04:06 +02:00
Christian Kratky 23ae8ab3b5 Fix unit test. 2018-07-08 14:10:25 +02:00
Christian Kratky 0bdb7e9e44 Merge branch 'develop' 2018-07-08 14:02:35 +02:00
Christian Kratky 54e3cd7cb7 Update nuspecs. 2018-07-08 14:01:47 +02:00
Christian Kratky 16ad07cfc9 Add wrapper for WebSocket4Net. 2018-07-08 10:34:46 +02:00
Christian Kratky dee0adcd8c Add new overloads. 2018-07-07 22:46:07 +02:00
Christian Kratky acbf1226ab Fix a bug in the keep alive monitor. 2018-07-07 21:22:08 +02:00
Christian Kratky f002744d87 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-07 21:03:36 +02:00
Christian Kratky 9efee7af21 Refactoring. 2018-07-07 21:03:31 +02:00
Christian 9814b10496 Merge pull request #355 from JanEggers/ConnectionHandlerWithWebsockets
Connection handler with websockets
2018-07-07 21:00:32 +02:00
JanEggers 978694b3c0 set binary mode 2018-07-07 10:52:24 +02:00
JanEggers bc6f155f12 using connectionhandlers with websockets 2018-07-07 10:42:33 +02:00
Christian Kratky d494c2104b Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-05 21:20:14 +02:00
Christian Kratky 8035c6859f Update docs. 2018-07-05 21:20:08 +02:00
Christian Kratky 2f10295022 Fix message handling for UWP. 2018-07-05 21:20:01 +02:00
Christian e5f32730a7 Merge pull request #353 from JanEggers/hideoverloadthatdoesnotprovideoptions
hide overload that does not provide options
2018-07-05 21:13:35 +02:00
JanEggers cd257b4d25 hide overload that does not provide options 2018-07-05 20:31:01 +02:00
Christian Kratky ce534baa75 Move the connection check interval of the ManagedClient to the options. 2018-07-04 22:20:24 +02:00
Christian Kratky 2b420b8e66 Add support for disabling server endpoints (ipv4 or ipv6) 2018-07-04 22:20:02 +02:00
Christian Kratky 35300abfb5 Fix typo. 2018-07-04 22:03:36 +02:00
Christian Kratky 3d0ecc05ff Fix bug which prevents receiving large packets for UWP. 2018-07-04 22:03:19 +02:00
Christian Kratky bfb6ec8856 Update UWP test app. 2018-07-04 22:02:42 +02:00
Christian Kratky bf1d682a85 Update libs 2018-07-04 22:00:48 +02:00
Christian Kratky 7d9326a147 Extend MqttPacketReader constructor to allow more unit tests. 2018-07-04 22:00:34 +02:00
Christian Kratky 7fd09009e7 Update docs. 2018-07-04 21:58:00 +02:00
Christian Kratky 9fa5e2dc1f Add the adapter Endpoint to the connection validator. 2018-07-04 21:57:51 +02:00
510 changed files with 25448 additions and 5443 deletions
+5
View File
@@ -0,0 +1,5 @@
[*.cs]
# CA1031: Do not catch general exception types
dotnet_diagnostic.CA1031.severity = none
+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.
+3 -2
View File
@@ -235,6 +235,7 @@ FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
/*/**/package-lock.json
# Typescript v1 declaration files
typings/
@@ -287,9 +288,9 @@ __pycache__/
*.odx.cs
*.xsd.cs
Build/nuget.exe
*.js
*.map
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
Build/NuGet/
-10
View File
@@ -1,10 +0,0 @@
language: csharp
solution: MQTTnet.sln
matrix:
include:
- dotnet: 2.0.0
mono: none
dist: trusty
env: DOTNETCORE=1 # optional, can be used to take different code paths in your script
- mono: latest
+24 -11
View File
@@ -3,27 +3,40 @@
<metadata>
<id>MQTTnet.AspNetCore</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</authors>
<owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<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>* Updated to MQTTnet 2.8.0.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="2.8.0" />
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="2.1.0" />
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.0.1" />
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="2.0.1" />
<group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="$nugetVersion" />
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.0" />
</group>
<group targetFramework="netcoreapp3.1">
<dependency id="MQTTnet" version="$nugetVersion" />
</group>
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET Standard 2.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>
+19 -11
View File
@@ -3,23 +3,29 @@
<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>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<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>* Updated to MQTTnet 2.8.0.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="2.8.0" />
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\"/>
@@ -32,7 +38,9 @@
<!-- .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\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net472\"/>
<!-- .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\"/>
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
</package>
+19 -11
View File
@@ -3,23 +3,29 @@
<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>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<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>* Updated to MQTTnet 2.8.0.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="2.8.0" />
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\"/>
@@ -32,7 +38,9 @@
<!-- .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\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net462\"/>
<!-- .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\"/>
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
</package>
@@ -0,0 +1,61 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.Extensions.WebSocket4Net</id>
<version>0.0.0</version>
<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>
<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-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="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>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET Standard 1.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\"/>
<!-- Universal Windows -->
<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\"/>
<!-- .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\"/>
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
+40 -42
View File
@@ -3,49 +3,34 @@
<metadata>
<id>MQTTnet</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<authors>The contributors of MQTTnet</authors>
<owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<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>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
<releaseNotes> ** MQTTnet is now available at Open Collective for donations (https://opencollective.com/mqttnet). **
* [Core] Performance optimizations.
* [Core] Due to performance reasons the timestamp of log messages is now in UTC format.
* [Core] Added several packet validations.
* [Core] Log messages now contain the complete source path including parent components.
* [Core] The adapter now has an _Endpoint_ definition as string containing remote IP and port.
* [Client] Received messages are now processed completely in the worker thread without creating new Tasks.
* [Client] Fixed wrong calculation for sending keep alive packets (thanks to @cstichlberger)
* [Client] A clean disconnect (via DisconnectAsync) will no longer throw an exception.
* [Client] Added new overloads for quick message publishing.
* [ManagedClient] The managed client is moved to a separate nuget package.
* [ManagedClient] Added an own message format with extended properties like ID (BREAKING CHANGE).
* [ManagedClient] Fixed a loading issue of stored application messages (thanks to @JTrotta).
* [ManagedClient] Added a new event which is fired when a synchronization of the subscriptions has failed.
* [ManagedClient] Added a new event which is fired when a connection attempt has failed.
* [ManagedClient] Exposed a new property which provides the count of not published messages (pending messages count).
* [Server] Added support for other WebSocket sub protocol formats like mqttv-3.1.1 (thanks to @israellot).
* [Server] The takeover of an existing client sessions is now treated as a _clean_ disconnect of the previous client.
* [Server] The pending messages queue per client is now limited to 250 messages. Overflow strategy and count can be changed via options (thanks to @VladimirAkopyan)
* [Server] Keep alive checking is now suspended while large packages are being received (and thus the client is connected). Keep alive checking continues after a large packet is received completely.
* [Server] Rewritten the _ConnectedClients_ API and added new features for disconnecting and Endpoint information (IP etc.).
* [Server] Added settings for disabling persistent sessions and defining a max pending messages queue size per session.
* [Server] Persistent sessions are disabled by default (BREAKING CHANGE!).
* [Server] Added a new interceptor which is invoked before a new message is added to the client queue.
* [Server] Added support for Linux servers by dividing IPv4 and IPv6 support and adding new options (BREAKING CHANGE!).
* [Server] Gracefully closed connections are no longer reported as warnings.
* [Server] Added new overloads for initializing the ASP.NET Core integration.
<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>
* [LowLevelClient] Fixed a null reference exception when connecting to a not existing server (thanks to @SGStino).
* [RcpClient] Adjusted some namespaces (BREAKING CHANGE!).
* [AspNetCore] Adjusted some namespaces (BREAKING CHANGE!).
* [Server] Adjusted some namespaces (BREAKING CHANGE!).
* [Server] Added state checks (throw if not started etc.) for most server APIs.
* [Server] Exposed real X509Certificate2 (instead byte array) to TLS options (thanks to @borigas).
* [Server] Fixed memory leak with TCP sockets (MqttServer is now Disposable!) (BREAKING CHANGE!).
* [Core] Fixed a null reference exception in the MqttTcpChannel with WriteAsync and ReadAsync.
* [Core] Added server interceptor for undelivered messages (thanks to @cshark-inator).
* [nuget] Added support for SourceLink (thanks to @JTOne123).
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<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.1" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="NETStandard.Library" version="2.0.0" />
@@ -53,30 +38,43 @@
<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="uap10.0">
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.1.4" />
</group>
<group targetFramework="net452">
</group>
<group targetFramework="net461">
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.10" />
</group>
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
<!-- .NET Standard 2.1 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard2.1\MQTTnet.*" target="lib\netstandard2.1\"/>
<!-- Universal Windows -->
<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\netstandard2.0\MQTTnet.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net472\"/>
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<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>
+118 -32
View File
@@ -3,45 +3,131 @@ param([string]$assemblyVersion, [string]$nugetVersion)
if ([string]::IsNullOrEmpty($assemblyVersion)) {$assemblyVersion = "0.0.1"}
if ([string]::IsNullOrEmpty($nugetVersion)) {$nugetVersion = "0.0.1"}
$vswhere = ${Env:\ProgramFiles(x86)} + '\Microsoft Visual Studio\Installer\vswhere'
$msbuild = &$vswhere -products * -requires Microsoft.Component.MSBuild -latest -find MSBuild\**\Bin\MSBuild.exe
Write-Host
Write-Host "Assembly version = $assemblyVersion"
Write-Host "Nuget version = $nugetVersion"
Write-Host "MSBuild path = $msbuild"
Write-Host
$vswhere = ${Env:\ProgramFiles(x86)} + '\Microsoft Visual Studio\Installer\vswhere'
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
$path = &$vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath
if ($path) {
$msbuild = join-path $path 'MSBuild\15.0\Bin\MSBuild.exe'
.\nuget.exe restore ..\MQTTnet.sln
# 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="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"
# 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
# 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="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
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 Managed Client extension
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.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.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="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# 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="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
# 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"
New-Item -ItemType Directory -Force -Path .\NuGet
.\nuget.exe pack MQTTnet.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
}
# 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
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.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.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
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.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.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.
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
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
(Get-Content MQTTnet.Extensions.Rpc.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.Rpc.nuspec
Copy-Item MQTTnet.Extensions.ManagedClient.nuspec -Destination MQTTnet.Extensions.ManagedClient.nuspec.old -Force
(Get-Content MQTTnet.Extensions.ManagedClient.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.ManagedClient.nuspec
Copy-Item MQTTnet.Extensions.WebSocket4Net.nuspec -Destination MQTTnet.Extensions.WebSocket4Net.nuspec.old -Force
(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 -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.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
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force
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
$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)
####################################################################
# 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
$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)
####################################################################
# 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
$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)
####################################################################
# 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
$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)
####################################################################
+6 -2
View File
@@ -1,9 +1,13 @@
param([string]$apiKey)
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
$files = Get-ChildItem -Path ".\NuGet" -Filter "*.nupkg"
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
Copyright (c) 2017 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
+260
View File
@@ -0,0 +1,260 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1-B9D6-40BF-81EC-86004D7765B4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
ProjectSection(SolutionItems) = preProject
Build\build.ps1 = Build\build.ps1
Build\MQTTnet.AspNetCore.nuspec = Build\MQTTnet.AspNetCore.nuspec
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
Build\upload.ps1 = Build\upload.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
ProjectSection(SolutionItems) = preProject
.bettercodehub.yml = .bettercodehub.yml
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.TestApp.NetCore", "Tests\MQTTnet.TestApp.NetCore\MQTTnet.TestApp.NetCore.csproj", "{3D283AAD-AAA8-4339-8394-52F80B6304DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.TestApp.AspNetCore2", "Tests\MQTTnet.TestApp.AspNetCore2\MQTTnet.TestApp.AspNetCore2.csproj", "{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore", "Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj", "{F10C4060-F7EE-4A83-919F-FF723E72F94A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{12816BCC-AF9E-44A9-9AE5-C246AF2A0587}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.Rpc", "Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj", "{C444E9C8-95FA-430E-9126-274129DE16CD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Benchmarks", "Tests\MQTTnet.Benchmarks\MQTTnet.Benchmarks.csproj", "{998D04DD-7CB0-45F5-A393-E2495C16399E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.ManagedClient", "Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj", "{C400533A-8EBA-4F0B-BF4D-295C3708604B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore.Tests", "Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj", "{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj", "{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQTTnet.Server\MQTTnet.Server.csproj", "{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.Build.0 = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|ARM.Build.0 = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|x64.ActiveCfg = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|x64.Build.0 = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|x86.ActiveCfg = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Debug|x86.Build.0 = Debug|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|Any CPU.Build.0 = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|ARM.ActiveCfg = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|ARM.Build.0 = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|x64.ActiveCfg = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|x64.Build.0 = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|x86.ActiveCfg = Release|Any CPU
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41}.Release|x86.Build.0 = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|ARM.ActiveCfg = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|ARM.Build.0 = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|x64.ActiveCfg = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|x64.Build.0 = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|x86.ActiveCfg = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Debug|x86.Build.0 = Debug|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|Any CPU.Build.0 = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|ARM.ActiveCfg = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|ARM.Build.0 = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|x64.ActiveCfg = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|x64.Build.0 = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|x86.ActiveCfg = Release|Any CPU
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7}.Release|x86.Build.0 = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|ARM.Build.0 = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|x64.ActiveCfg = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|x64.Build.0 = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|x86.ActiveCfg = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Debug|x86.Build.0 = Debug|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|Any CPU.Build.0 = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|ARM.ActiveCfg = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|ARM.Build.0 = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|x64.ActiveCfg = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|x64.Build.0 = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|x86.ActiveCfg = Release|Any CPU
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{F10C4060-F7EE-4A83-919F-FF723E72F94A} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{C444E9C8-95FA-430E-9126-274129DE16CD} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{9C7106CA-96B8-4ABE-B3B4-9357AB8ACB41} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{DADEA836-5CC3-474C-A2D8-4D0F31118CD7} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{9AE2F8DA-4178-470B-B8C4-88BE1DAE7D5F} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
EndGlobalSection
EndGlobal
+106 -4
View File
@@ -1,9 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1-B9D6-40BF-81EC-86004D7765B4}"
EndProject
@@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1
Build\MQTTnet.AspNetCore.nuspec = Build\MQTTnet.AspNetCore.nuspec
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
Build\upload.ps1 = Build\upload.ps1
EndProjectSection
@@ -26,6 +27,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
@@ -47,6 +49,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.ManagedC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore.Tests", "Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj", "{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQTTnet.Server\MQTTnet.Server.csproj", "{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}"
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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Server", "Tests\MQTTnet.Test.BlazorApp\Server\MQTTnet.Test.BlazorApp.Server.csproj", "{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Client", "Tests\MQTTnet.Test.BlazorApp\Client\MQTTnet.Test.BlazorApp.Client.csproj", "{D260D63D-7902-4C55-9665-84C5CACBBB24}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Test.BlazorApp.Shared", "Tests\MQTTnet.Test.BlazorApp\Shared\MQTTnet.Test.BlazorApp.Shared.csproj", "{DDB069BA-6E1A-48C7-B374-5D903B553CAD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -226,13 +242,93 @@ Global
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.Build.0 = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|ARM.Build.0 = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|x64.ActiveCfg = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|x64.Build.0 = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|x86.ActiveCfg = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Debug|x86.Build.0 = Debug|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|Any CPU.Build.0 = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|ARM.ActiveCfg = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|ARM.Build.0 = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x64.ActiveCfg = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x64.Build.0 = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.ActiveCfg = Release|Any CPU
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.Build.0 = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|ARM.Build.0 = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x64.ActiveCfg = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x64.Build.0 = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x86.ActiveCfg = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x86.Build.0 = Debug|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.Build.0 = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|ARM.ActiveCfg = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|ARM.Build.0 = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.ActiveCfg = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.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}
{FF1F72D6-9524-4422-9497-3CC0002216ED} = {A56E3128-1639-4F31-873A-325E14BB6295}
{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}
@@ -241,6 +337,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} = {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}
+1
View File
@@ -7,6 +7,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<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>
+34 -14
View File
@@ -1,12 +1,14 @@
<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>
[![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/branch/develop)
[![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)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/chkr1011/MQTTnet/master/LICENSE)
# MQTTnet
@@ -18,19 +20,21 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
* Async support
* TLS 1.2 support for client and server (but not UWP servers)
* Extensible communication channels (i.e. In-Memory, TCP, TCP+TLS, WS)
* 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 (~90 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_.
### 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
@@ -46,6 +50,17 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
* WebSockets supported (via ASP.NET Core 2.0, separate nuget)
* A custom message interceptor can be added which allows transforming or extending every received application message
* Validate subscriptions and deny subscribing of certain topics depending on requesting clients
* Connect clients with different protocol versions at the same time.
## MQTTnet Server
_MQTTnet Server_ is a standalone cross platform MQTT server (like mosquitto) basing on this library. It has the following features.
* Running portable (no installation required)
* Runs und Windows, Linux, macOS, Raspberry Pi
* Python scripting support for manipulating messages, validation of clients, building business logic etc.
* Supports WebSocket and TCP (with and without TLS) connections
* Provides a HTTP based API (including Swagger endpoint)
* Extensive configuration parameters and customization supported
## Supported frameworks
@@ -57,10 +72,11 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
* Universal Windows Platform (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU, Windows 10 IoT Core)
* Xamarin.Android 7.5+
* Xamarin.iOS 10.14+
* Blazor WebAssembly 3.2.0
## Supported MQTT versions
* 5.0.0 (planned)
* 5.0.0
* 3.1.1
* 3.1.0
@@ -77,21 +93,25 @@ 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 also listed at 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/)
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
If you use this library and want to see your project here please let me know.
Further projects using this project can be found under https://github.com/chkr1011/MQTTnet/network/dependents.
## MIT License
If you use this library and want to see your project here please create a pull request.
Copyright (c) 2017-2018 Christian Kratky
## License
MIT License
MQTTnet Copyright (c) 2016-2020 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
@@ -0,0 +1,15 @@
using MQTTnet.Server;
using System;
namespace MQTTnet.AspNetCore
{
public class AspNetMqttServerOptionsBuilder : MqttServerOptionsBuilder
{
public AspNetMqttServerOptionsBuilder(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public IServiceProvider ServiceProvider { get; }
}
}
@@ -1,28 +1,28 @@
using System;
using System.Net;
using MQTTnet.Adapter;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Client.Tcp;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Serializer;
using MQTTnet.Client.Options;
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));
var serializer = new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion };
switch (options.ChannelOptions)
{
case MqttClientTcpOptions tcpOptions:
{
var endpoint = new DnsEndPoint(tcpOptions.Server, tcpOptions.GetPort());
var tcpConnection = new TcpConnection(endpoint);
return new MqttConnectionContext(serializer, tcpConnection);
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, writer);
return new MqttConnectionContext(formatter, tcpConnection);
}
default:
{
@@ -5,6 +5,10 @@ using System.Diagnostics;
using System.IO.Pipelines;
using System.Net.Sockets;
#if NETCOREAPP2_1
using System.Runtime.InteropServices;
#endif
namespace MQTTnet.AspNetCore.Client.Tcp
{
public class SocketSender
@@ -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
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
return base.DisposeAsync();
}
#else
return Task.CompletedTask;
}
#endif
public async Task StartAsync()
{
@@ -1,13 +1,13 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using MQTTnet.Server;
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();
@@ -23,17 +23,13 @@ namespace MQTTnet.AspNetCore
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
{
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
subProtocol = requestedSubProtocolValues
.OrderByDescending(p => p.Length)
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
subProtocol = MqttSubProtocolSelector.SelectSubProtocol(requestedSubProtocolValues);
}
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(subProtocol))
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false))
{
var endpoint = $"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort}";
await adapter.RunWebSocketConnectionAsync(webSocket, endpoint);
await adapter.RunWebSocketConnectionAsync(webSocket, context);
}
});
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Connections;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ConnectionBuilderExtensions
{
@@ -0,0 +1,23 @@
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
public static void MapMqtt(this ConnectionsRouteBuilder connection, PathString path)
{
connection.MapConnectionHandler<MqttConnectionHandler>(path, options =>
{
options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol;
});
}
}
}
@@ -0,0 +1,21 @@
#if NETCOREAPP3_1
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
@@ -2,26 +2,36 @@
using System.Buffers;
using MQTTnet.Adapter;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Serializer;
namespace MQTTnet.AspNetCore
namespace MQTTnet.AspNetCore.Extensions
{
public static class ReaderExtensions
{
public static bool TryDeserialize(this IMqttPacketSerializer serializer, in ReadOnlySequence<byte> input, out MqttBasePacket packet, out SequencePosition consumed, out SequencePosition observed)
public static bool TryDecode(this MqttPacketFormatterAdapter formatter,
SpanBasedMqttPacketBodyReader reader,
in ReadOnlySequence<byte> input,
out MqttBasePacket packet,
out SequencePosition consumed,
out SequencePosition observed,
out int bytesRead)
{
if (formatter == null) throw new ArgumentNullException(nameof(formatter));
packet = null;
consumed = input.Start;
observed = input.End;
bytesRead = 0;
var copy = input;
if (copy.Length < 2)
{
return false;
}
var fixedheader = copy.First.Span[0];
if (!TryReadBodyLength(ref copy, out var bodyLength))
if (!TryReadBodyLength(ref copy, out int headerLength, out var bodyLength))
{
return false;
}
@@ -32,33 +42,45 @@ namespace MQTTnet.AspNetCore
}
var bodySlice = copy.Slice(0, bodyLength);
packet = serializer.Deserialize(new ReceivedMqttPacket(fixedheader, new MqttPacketBodyReader(bodySlice.GetArray(), 0)));
var buffer = bodySlice.GetMemory();
reader.SetBuffer(buffer);
var receivedMqttPacket = new ReceivedMqttPacket(fixedheader, reader, buffer.Length + 2);
if (formatter.ProtocolVersion == MqttProtocolVersion.Unknown)
{
formatter.DetectProtocolVersion(receivedMqttPacket);
}
packet = formatter.Decode(receivedMqttPacket);
consumed = bodySlice.End;
observed = bodySlice.End;
bytesRead = headerLength + bodyLength;
return true;
}
private static byte[] GetArray(this in ReadOnlySequence<byte> input)
private static ReadOnlyMemory<byte> GetMemory(this in ReadOnlySequence<byte> input)
{
if (input.IsSingleSegment)
{
return input.First.Span.ToArray();
return input.First;
}
// Should be rare
return input.ToArray();
}
private static bool TryReadBodyLength(ref ReadOnlySequence<byte> input, out int result)
private static bool TryReadBodyLength(ref ReadOnlySequence<byte> input, out int headerLength, out int bodyLength)
{
// Alorithm taken from https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html.
var multiplier = 1;
var value = 0;
byte encodedByte;
var index = 1;
result = 0;
var temp = input.Slice(0, Math.Min(5, input.Length)).GetArray();
headerLength = 0;
bodyLength = 0;
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory().Span;
do
{
@@ -72,7 +94,7 @@ namespace MQTTnet.AspNetCore
value += (byte)(encodedByte & 127) * multiplier;
if (multiplier > 128 * 128 * 128)
{
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", temp.AsSpan(1, index).ToArray())}).");
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", temp.Slice(1, index).ToArray())}).");
}
multiplier *= 128;
@@ -80,7 +102,8 @@ namespace MQTTnet.AspNetCore
input = input.Slice(index);
result = value;
headerLength = index;
bodyLength = value;
return true;
}
}
@@ -3,31 +3,46 @@ 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();
return services;
}
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
{
var builder = new MqttServerOptionsBuilder();
services.AddSingleton<IMqttServerOptions>(s =>
{
var builder = new MqttServerOptionsBuilder();
configure(builder);
return builder.Build();
});
configure(builder);
services.AddSingleton<IMqttServerOptions>(builder.Build());
services.AddHostedMqttServer();
return services;
}
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
{
services.AddSingleton<IMqttServerOptions>(s =>
{
var builder = new AspNetMqttServerOptionsBuilder(s);
configure(builder);
return builder.Build();
});
services.AddHostedMqttServer();
@@ -44,17 +59,15 @@ namespace MQTTnet.AspNetCore
return services;
}
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
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,22 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netcoreapp3.1</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.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.0.1" />
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
@@ -1,44 +1,93 @@
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Connections.Features;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Client.Tcp;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Serializer;
using System;
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
{
public MqttConnectionContext(
IMqttPacketSerializer packetSerializer,
ConnectionContext connection)
readonly AsyncLock _writerLock = new AsyncLock();
readonly SpanBasedMqttPacketBodyReader _reader;
PipeReader _input;
PipeWriter _output;
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
{
PacketSerializer = packetSerializer;
Connection = connection;
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
Connection = connection ?? throw new ArgumentNullException(nameof(connection));
if (Connection.Transport != null)
{
_input = Connection.Transport.Input;
_output = Connection.Transport.Output;
}
_reader = new SpanBasedMqttPacketBodyReader();
}
public string Endpoint => Connection.ConnectionId;
public ConnectionContext Connection { get; }
public IMqttPacketSerializer PacketSerializer { get; }
public event EventHandler ReadingPacketStarted;
public event EventHandler ReadingPacketCompleted;
public string Endpoint
{
get
{
#if NETCOREAPP3_1
if (Connection?.RemoteEndPoint != null)
{
return Connection.RemoteEndPoint.ToString();
}
#endif
var connection = Http?.HttpContext?.Connection;
if (connection == null)
{
return Connection.ConnectionId;
}
public Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
return $"{connection.RemoteIpAddress}:{connection.RemotePort}";
}
}
public bool IsSecureConnection => Http?.HttpContext?.Request?.IsHttps ?? false;
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
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; }
IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
if (Connection is TcpConnection tcp && !tcp.IsConnected)
{
return tcp.StartAsync();
await tcp.StartAsync().ConfigureAwait(false);
}
return Task.CompletedTask;
_input = Connection.Transport.Input;
_output = Connection.Transport.Output;
}
public Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
Connection.Transport.Input.Complete();
Connection.Transport.Output.Complete();
_input?.Complete();
_output?.Complete();
return Task.CompletedTask;
}
@@ -59,7 +108,7 @@ namespace MQTTnet.AspNetCore
}
else
{
readResult = await readTask;
readResult = await readTask.ConfigureAwait(false);
}
var buffer = readResult.Buffer;
@@ -71,19 +120,20 @@ namespace MQTTnet.AspNetCore
{
if (!buffer.IsEmpty)
{
if (PacketSerializer.TryDeserialize(buffer, out var packet, out consumed, out observed))
if (PacketFormatterAdapter.TryDecode(_reader, buffer, out var packet, out consumed, out observed, out var received))
{
BytesReceived += received;
return packet;
}
else
{
// we did receive something but the message is not yet complete
ReadingPacketStarted?.Invoke(this, EventArgs.Empty);
ReadingPacketStartedCallback?.Invoke();
}
}
else if (readResult.IsCompleted)
{
break;
throw new MqttCommunicationException("Connection Aborted");
}
}
finally
@@ -95,19 +145,43 @@ namespace MQTTnet.AspNetCore
}
}
}
catch (Exception e)
{
// completing the cannels makes sure that there is no more data read after a protocol error
_input?.Complete(e);
_output?.Complete(e);
throw;
}
finally
{
ReadingPacketCompleted?.Invoke(this, EventArgs.Empty);
ReadingPacketCompletedCallback?.Invoke();
}
cancellationToken.ThrowIfCancellationRequested();
return null;
}
public Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
public void ResetStatistics()
{
var buffer = PacketSerializer.Serialize(packet);
return Connection.Transport.Output.WriteAsync(buffer.AsMemory(), cancellationToken).AsTask();
BytesReceived = 0;
BytesSent = 0;
}
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
{
var formatter = PacketFormatterAdapter;
using (await _writerLock.WaitAsync(cancellationToken).ConfigureAwait(false))
{
var buffer = formatter.Encode(packet);
var msg = buffer.AsMemory();
var output = _output;
var result = await output.WriteAsync(msg, cancellationToken).ConfigureAwait(false);
if (result.IsCompleted)
{
BytesSent += msg.Length;
}
PacketFormatterAdapter.FreeBuffer();
}
}
public void Dispose()
@@ -1,25 +1,35 @@
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using MQTTnet.Adapter;
using MQTTnet.Serializer;
using MQTTnet.Server;
using System;
using System.Threading.Tasks;
using MQTTnet.Formatter;
namespace MQTTnet.AspNetCore
{
public class MqttConnectionHandler : ConnectionHandler, IMqttServerAdapter
{
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
{
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public override async Task OnConnectedAsync(ConnectionContext connection)
{
var serializer = new MqttPacketSerializer();
using (var adapter = new MqttConnectionContext(serializer, connection))
// required for websocket transport to work
var transferFormatFeature = connection.Features.Get<ITransferFormatFeature>();
if (transferFormatFeature != null)
{
var args = new MqttServerAdapterClientAcceptedEventArgs(adapter);
ClientAccepted?.Invoke(this, args);
transferFormatFeature.ActiveFormat = TransferFormat.Binary;
}
await args.SessionTask;
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(writer);
using (var adapter = new MqttConnectionContext(formatter, connection))
{
var clientHandler = ClientHandler;
if (clientHandler != null)
{
await clientHandler(adapter).ConfigureAwait(false);
}
}
}
@@ -32,7 +42,7 @@ namespace MQTTnet.AspNetCore
{
return Task.CompletedTask;
}
public void Dispose()
{
}
@@ -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,17 +1,25 @@
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Serializer;
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
{
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
readonly IMqttNetLogger _rootLogger;
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
{
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public Task StartAsync(IMqttServerOptions options)
{
@@ -23,24 +31,38 @@ namespace MQTTnet.AspNetCore
return Task.CompletedTask;
}
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, string endpoint)
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, HttpContext httpContext)
{
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
var clientAdapter = new MqttChannelAdapter(new MqttWebSocketChannel(webSocket, endpoint), new MqttPacketSerializer(), new MqttNetLogger().CreateChildLogger(nameof(MqttWebSocketServerAdapter)));
var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}";
var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter);
ClientAccepted?.Invoke(this, eventArgs);
if (eventArgs.SessionTask != null)
var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false);
try
{
await eventArgs.SessionTask.ConfigureAwait(false);
var isSecureConnection = clientCertificate != null;
var clientHandler = ClientHandler;
if (clientHandler != null)
{
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(writer);
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _rootLogger))
{
await clientHandler(channelAdapter).ConfigureAwait(false);
}
}
}
finally
{
clientCertificate?.Dispose();
}
}
public void Dispose()
{
StopAsync().GetAwaiter().GetResult();
}
}
}
@@ -0,0 +1,129 @@
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using System;
using System.Buffers.Binary;
using System.Text;
namespace MQTTnet.AspNetCore
{
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
{
ReadOnlyMemory<byte> _buffer;
int _offset;
public void SetBuffer(ReadOnlyMemory<byte> buffer)
{
_buffer = buffer;
_offset = 0;
}
public int Length => _buffer.Length;
public bool EndOfStream => _buffer.Length.Equals(_offset);
public int Offset => _offset;
public byte ReadByte()
{
return _buffer.Span[_offset++];
}
public byte[] ReadRemainingData()
{
return _buffer.Slice(_offset).ToArray();
}
public byte[] ReadWithLengthPrefix()
{
return ReadSegmentWithLengthPrefix().ToArray();
}
public unsafe string ReadStringWithLengthPrefix()
{
var buffer = ReadSegmentWithLengthPrefix();
if (buffer.Length == 0)
{
return string.Empty;
}
fixed (byte* bytes = &buffer.GetPinnableReference())
{
var result = Encoding.UTF8.GetString(bytes, buffer.Length);
return result;
}
}
public ushort ReadTwoByteInteger()
{
var result = BinaryPrimitives.ReadUInt16BigEndian(_buffer.Span.Slice(_offset));
_offset += 2;
return result;
}
public uint ReadFourByteInteger()
{
var result = BinaryPrimitives.ReadUInt32BigEndian(_buffer.Span.Slice(_offset));
_offset += 4;
return result;
}
public uint ReadVariableLengthInteger()
{
var multiplier = 1;
var value = 0U;
byte encodedByte;
do
{
encodedByte = ReadByte();
value += (uint)((encodedByte & 127) * multiplier);
if (multiplier > 2097152)
{
throw new MqttProtocolViolationException("Variable length integer is invalid.");
}
multiplier *= 128;
} while ((encodedByte & 128) != 0);
return value;
}
public bool ReadBoolean()
{
var buffer = ReadByte();
if (buffer == 0)
{
return false;
}
if (buffer == 1)
{
return true;
}
throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
}
public void Seek(int position)
{
_offset = position;
}
ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
{
var span = _buffer.Span;
var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
if (Length < _offset + length)
{
throw new MqttProtocolViolationException($"Expected at least {_offset + 2 + length} bytes but there are only {Length} bytes");
}
var result = span.Slice(_offset + 2, length);
_offset += 2 + length;
return result;
}
}
}
@@ -0,0 +1,144 @@
using MQTTnet.Formatter;
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Text;
namespace MQTTnet.AspNetCore
{
public class SpanBasedMqttPacketWriter : IMqttPacketWriter
{
readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create();
public SpanBasedMqttPacketWriter()
{
Reset(0);
}
byte[] _buffer;
int _position;
public int Length { get; set; }
public void FreeBuffer()
{
_pool.Return(_buffer);
}
public byte[] GetBuffer()
{
return _buffer;
}
public void Reset(int v)
{
_buffer = _pool.Rent(1500);
Length = v;
_position = v;
}
public void Seek(int v)
{
_position = v;
}
public void Write(byte value)
{
GrowIfNeeded(1);
_buffer[_position] = value;
Commit(1);
}
public void Write(ushort value)
{
GrowIfNeeded(2);
BinaryPrimitives.WriteUInt16BigEndian(_buffer.AsSpan(_position), value);
Commit(2);
}
public void Write(IMqttPacketWriter propertyWriter)
{
if (propertyWriter == null) throw new ArgumentNullException(nameof(propertyWriter));
GrowIfNeeded(propertyWriter.Length);
Write(propertyWriter.GetBuffer(), 0, propertyWriter.Length);
}
public void Write(byte[] payload, int start, int length)
{
GrowIfNeeded(length);
payload.AsSpan(start, length).CopyTo(_buffer.AsSpan(_position));
Commit(length);
}
public void WriteVariableLengthInteger(uint value)
{
GrowIfNeeded(4);
var x = value;
do
{
var encodedByte = x % 128;
x = x / 128;
if (x > 0)
{
encodedByte = encodedByte | 128;
}
_buffer[_position] = (byte)encodedByte;
Commit(1);
} while (x > 0);
}
public void WriteWithLengthPrefix(string value)
{
var bytesLength = Encoding.UTF8.GetByteCount(value ?? string.Empty);
GrowIfNeeded(bytesLength + 2);
Write((ushort)bytesLength);
Encoding.UTF8.GetBytes(value ?? string.Empty, 0, value?.Length ?? 0, _buffer, _position);
Commit(bytesLength);
}
public void WriteWithLengthPrefix(byte[] payload)
{
GrowIfNeeded(payload.Length + 2);
Write((ushort)payload.Length);
payload.CopyTo(_buffer, _position);
Commit(payload.Length);
}
void Commit(int count)
{
if (_position == Length)
{
Length += count;
}
_position += count;
}
void GrowIfNeeded(int requiredAdditional)
{
var requiredTotal = _position + requiredAdditional;
if (_buffer.Length >= requiredTotal)
{
return;
}
var newBufferLength = _buffer.Length;
while (newBufferLength < requiredTotal)
{
newBufferLength *= 2;
}
var newBuffer = _pool.Rent(newBufferLength);
Array.Copy(_buffer, newBuffer, _buffer.Length);
_pool.Return(_buffer);
_buffer = newBuffer;
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public class ApplicationMessageProcessedHandlerDelegate : IApplicationMessageProcessedHandler
{
private readonly Func<ApplicationMessageProcessedEventArgs, Task> _handler;
public ApplicationMessageProcessedHandlerDelegate(Action<ApplicationMessageProcessedEventArgs> handler)
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
_handler = context =>
{
handler(context);
return Task.FromResult(0);
};
}
public ApplicationMessageProcessedHandlerDelegate(Func<ApplicationMessageProcessedEventArgs, Task> handler)
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
}
public Task HandleApplicationMessageProcessedAsync(ApplicationMessageProcessedEventArgs eventArgs)
{
return _handler(eventArgs);
}
}
}
@@ -0,0 +1,14 @@
using System;
namespace MQTTnet.Extensions.ManagedClient
{
public class ApplicationMessageSkippedEventArgs : EventArgs
{
public ApplicationMessageSkippedEventArgs(ManagedMqttApplicationMessage applicationMessage)
{
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
}
public ManagedMqttApplicationMessage ApplicationMessage { get; }
}
}
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public class ApplicationMessageSkippedHandlerDelegate : IApplicationMessageSkippedHandler
{
private readonly Func<ApplicationMessageSkippedEventArgs, Task> _handler;
public ApplicationMessageSkippedHandlerDelegate(Action<ApplicationMessageSkippedEventArgs> handler)
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
_handler = eventArgs =>
{
handler(eventArgs);
return Task.FromResult(0);
};
}
public ApplicationMessageSkippedHandlerDelegate(Func<ApplicationMessageSkippedEventArgs, Task> handler)
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
}
public Task HandleApplicationMessageSkippedAsync(ApplicationMessageSkippedEventArgs eventArgs)
{
return _handler(eventArgs);
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public class ConnectingFailedHandlerDelegate : IConnectingFailedHandler
{
private readonly Func<ManagedProcessFailedEventArgs, Task> _handler;
public ConnectingFailedHandlerDelegate(Action<ManagedProcessFailedEventArgs> handler)
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
_handler = eventArgs =>
{
handler(eventArgs);
return Task.FromResult(0);
};
}
public ConnectingFailedHandlerDelegate(Func<ManagedProcessFailedEventArgs, Task> handler)
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
}
public Task HandleConnectingFailedAsync(ManagedProcessFailedEventArgs eventArgs)
{
return _handler(eventArgs);
}
}
}
@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public interface IApplicationMessageProcessedHandler
{
Task HandleApplicationMessageProcessedAsync(ApplicationMessageProcessedEventArgs eventArgs);
}
}
@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public interface IApplicationMessageSkippedHandler
{
Task HandleApplicationMessageSkippedAsync(ApplicationMessageSkippedEventArgs eventArgs);
}
}
@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public interface IConnectingFailedHandler
{
Task HandleConnectingFailedAsync(ManagedProcessFailedEventArgs eventArgs);
}
}
@@ -1,7 +1,9 @@
using System;
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
{
@@ -10,19 +12,22 @@ namespace MQTTnet.Extensions.ManagedClient
bool IsStarted { get; }
bool IsConnected { get; }
int PendingApplicationMessagesCount { get; }
IManagedMqttClientOptions Options { get; }
event EventHandler<MqttClientConnectedEventArgs> Connected;
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
IMqttClientConnectedHandler ConnectedHandler { get; set; }
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
event EventHandler<ApplicationMessageProcessedEventArgs> ApplicationMessageProcessed;
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
event EventHandler<MqttManagedProcessFailedEventArgs> ConnectingFailed;
event EventHandler<MqttManagedProcessFailedEventArgs> SynchronizingSubscriptionsFailed;
Task StartAsync(IManagedMqttClientOptions options);
Task StopAsync();
Task PingAsync(CancellationToken cancellationToken);
Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters);
Task UnsubscribeAsync(IEnumerable<string> topics);
Task PublishAsync(ManagedMqttApplicationMessage applicationMessages);
@@ -1,5 +1,6 @@
using System;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
namespace MQTTnet.Extensions.ManagedClient
{
@@ -9,6 +10,12 @@ namespace MQTTnet.Extensions.ManagedClient
TimeSpan AutoReconnectDelay { get; }
TimeSpan ConnectionCheckInterval { get; }
IManagedMqttClientStorage Storage { get; }
int MaxPendingMessages { get; }
MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; }
}
}
@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public interface ISynchronizingSubscriptionsFailedHandler
{
Task HandleSynchronizingSubscriptionsFailedAsync(ManagedProcessFailedEventArgs eventArgs);
}
}
@@ -1,18 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;net452;net461;uap10.0</TargetFrameworks>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</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>
@@ -21,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,127 +1,213 @@
using System;
using System.Collections.Concurrent;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Publishing;
using MQTTnet.Client.Receiving;
using MQTTnet.Diagnostics;
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;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Exceptions;
using MQTTnet.Protocol;
namespace MQTTnet.Extensions.ManagedClient
{
public class ManagedMqttClient : IManagedMqttClient
public class ManagedMqttClient : Disposable, IManagedMqttClient
{
private readonly BlockingCollection<ManagedMqttApplicationMessage> _messageQueue = new BlockingCollection<ManagedMqttApplicationMessage>();
private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
/// <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>
private readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
private readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
private readonly HashSet<string> _unsubscriptions = new HashSet<string>();
private readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0);
private readonly IMqttClient _mqttClient;
private readonly IMqttNetChildLogger _logger;
private readonly IMqttNetScopedLogger _logger;
private readonly AsyncLock _messageQueueLock = new AsyncLock();
private CancellationTokenSource _connectionCancellationToken;
private CancellationTokenSource _publishingCancellationToken;
private Task _maintainConnectionTask;
private ManagedMqttClientStorageManager _storageManager;
private IManagedMqttClientOptions _options;
private bool _subscriptionsNotPushed;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
_mqttClient.Connected += OnConnected;
_mqttClient.Disconnected += OnDisconnected;
_mqttClient.ApplicationMessageReceived += OnApplicationMessageReceived;
_logger = logger.CreateChildLogger(nameof(ManagedMqttClient));
if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger.CreateScopedLogger(nameof(ManagedMqttClient));
}
public bool IsConnected => _mqttClient.IsConnected;
public bool IsStarted => _connectionCancellationToken != null;
public int PendingApplicationMessagesCount => _messageQueue.Count;
public IManagedMqttClientOptions Options { get; private set; }
public event EventHandler<MqttClientConnectedEventArgs> Connected;
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
public IMqttClientConnectedHandler ConnectedHandler
{
get => _mqttClient.ConnectedHandler;
set => _mqttClient.ConnectedHandler = value;
}
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
public event EventHandler<ApplicationMessageProcessedEventArgs> ApplicationMessageProcessed;
public IMqttClientDisconnectedHandler DisconnectedHandler
{
get => _mqttClient.DisconnectedHandler;
set => _mqttClient.DisconnectedHandler = value;
}
public event EventHandler<MqttManagedProcessFailedEventArgs> ConnectingFailed;
public event EventHandler<MqttManagedProcessFailedEventArgs> SynchronizingSubscriptionsFailed;
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
{
get => _mqttClient.ApplicationMessageReceivedHandler;
set => _mqttClient.ApplicationMessageReceivedHandler = value;
}
public IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
public IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
public IConnectingFailedHandler ConnectingFailedHandler { get; set; }
public ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
public async Task StartAsync(IManagedMqttClientOptions options)
{
ThrowIfDisposed();
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)
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
Options = options;
if (Options.Storage != null)
{
throw new NotSupportedException("The managed client does not support existing sessions.");
}
if (_connectionCancellationToken != null) throw new InvalidOperationException("The managed client is already started.");
_options = options;
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)
{
_messageQueue.Add(message);
_messageQueue.Enqueue(message);
}
}
_connectionCancellationToken = new CancellationTokenSource();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
_maintainConnectionTask.Forget(_logger);
_logger.Info("Started");
}
public Task StopAsync()
public async Task StopAsync()
{
ThrowIfDisposed();
StopPublishing();
StopMaintainingConnection();
while (_messageQueue.Any())
{
_messageQueue.Take();
}
_messageQueue.Clear();
return Task.FromResult(0);
if (_maintainConnectionTask != null)
{
await Task.WhenAny(_maintainConnectionTask);
_maintainConnectionTask = null;
}
}
public Task PublishAsync(MqttApplicationMessage applicationMessage)
public Task PingAsync(CancellationToken cancellationToken)
{
return _mqttClient.PingAsync(cancellationToken);
}
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
{
ThrowIfDisposed();
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
return PublishAsync(new ManagedMqttApplicationMessageBuilder().WithApplicationMessage(applicationMessage).Build());
await PublishAsync(new ManagedMqttApplicationMessageBuilder().WithApplicationMessage(applicationMessage).Build()).ConfigureAwait(false);
return new MqttClientPublishResult();
}
public async Task PublishAsync(ManagedMqttApplicationMessage applicationMessage)
{
ThrowIfDisposed();
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
if (Options == null) throw new InvalidOperationException("call StartAsync before publishing messages");
if (_storageManager != null)
MqttTopicValidator.ThrowIfInvalid(applicationMessage.ApplicationMessage.Topic);
ManagedMqttApplicationMessage removedMessage = null;
ApplicationMessageSkippedEventArgs applicationMessageSkippedEventArgs = null;
try
{
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
}
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
{
if (_messageQueue.Count >= Options.MaxPendingMessages)
{
if (Options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
{
_logger.Verbose("Skipping publish of new application message because internal queue is full.");
applicationMessageSkippedEventArgs = new ApplicationMessageSkippedEventArgs(applicationMessage);
return;
}
_messageQueue.Add(applicationMessage);
if (Options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
{
removedMessage = _messageQueue.RemoveFirst();
_logger.Verbose("Removed oldest application message from internal queue because it is full.");
applicationMessageSkippedEventArgs = new ApplicationMessageSkippedEventArgs(removedMessage);
}
}
_messageQueue.Enqueue(applicationMessage);
if (_storageManager != null)
{
if (removedMessage != null)
{
await _storageManager.RemoveAsync(removedMessage).ConfigureAwait(false);
}
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
}
}
}
finally
{
if (applicationMessageSkippedEventArgs != null)
{
var applicationMessageSkippedHandler = ApplicationMessageSkippedHandler;
if (applicationMessageSkippedHandler != null)
{
await applicationMessageSkippedHandler.HandleApplicationMessageSkippedAsync(applicationMessageSkippedEventArgs).ConfigureAwait(false);
}
}
}
}
public Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
public Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters)
{
ThrowIfDisposed();
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
lock (_subscriptions)
@@ -129,37 +215,52 @@ 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);
}
public Task UnsubscribeAsync(IEnumerable<string> topics)
{
ThrowIfDisposed();
if (topics == null) throw new ArgumentNullException(nameof(topics));
lock (_subscriptions)
{
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)
{
_messageQueue?.Dispose();
_connectionCancellationToken?.Dispose();
_publishingCancellationToken?.Dispose();
if (disposing)
{
StopPublishing();
StopMaintainingConnection();
if (_maintainConnectionTask != null)
{
_maintainConnectionTask.GetAwaiter().GetResult();
_maintainConnectionTask = null;
}
_messageQueue.Dispose();
_messageQueueLock.Dispose();
_mqttClient.Dispose();
_subscriptionsQueuedSignal.Dispose();
}
base.Dispose(disposing);
}
private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
@@ -176,12 +277,29 @@ namespace MQTTnet.Extensions.ManagedClient
}
catch (Exception exception)
{
_logger.Error(exception, "Unhandled exception while maintaining connection.");
_logger.Error(exception, "Error exception while maintaining connection.");
}
finally
{
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
_logger.Info("Stopped");
if (!IsDisposed)
{
try
{
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.Error(exception, "Error while disconnecting.");
}
_logger.Info("Stopped");
}
_reconnectSubscriptions.Clear();
lock (_subscriptions)
{
_subscriptions.Clear();
_unsubscriptions.Clear();
}
}
}
@@ -193,20 +311,26 @@ namespace MQTTnet.Extensions.ManagedClient
if (connectionState == ReconnectionResult.NotConnected)
{
StopPublishing();
await Task.Delay(_options.AutoReconnectDelay, cancellationToken).ConfigureAwait(false);
await Task.Delay(Options.AutoReconnectDelay, cancellationToken).ConfigureAwait(false);
return;
}
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(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
await PublishSubscriptionsAsync(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
@@ -214,21 +338,29 @@ 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 void PublishQueuedMessages(CancellationToken cancellationToken)
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
while (!cancellationToken.IsCancellationRequested && _mqttClient.IsConnected)
{
var message = _messageQueue.Take(cancellationToken);
// Peek at the message without dequeueing in order to prevent the
// possibility of the queue growing beyond the configured cap.
// Previously, messages could be re-enqueued if there was an
// exception, and this re-enqueueing did not honor the cap.
// Furthermore, because re-enqueueing would shuffle the order
// of the messages, the DropOldestQueuedMessage strategy would
// be unable to know which message is actually the oldest and would
// instead drop the first item in the queue.
var message = _messageQueue.PeekAndWait(cancellationToken);
if (message == null)
{
continue;
@@ -236,7 +368,7 @@ namespace MQTTnet.Extensions.ManagedClient
cancellationToken.ThrowIfCancellationRequested();
TryPublishQueuedMessage(message);
await TryPublishQueuedMessageAsync(message).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
@@ -244,7 +376,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
{
@@ -252,13 +384,28 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
private void TryPublishQueuedMessage(ManagedMqttApplicationMessage message)
private async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
{
Exception transmitException = null;
try
{
_mqttClient.PublishAsync(message.ApplicationMessage).GetAwaiter().GetResult();
_storageManager?.RemoveAsync(message).GetAwaiter().GetResult();
await _mqttClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
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
// with the DropOldestQueuedMessage strategy). If the first item
// in the queue is equal to this message, then it's safe to remove
// it from the queue. If not, that means this.PublishAsync has already
// removed it, in which case we don't want to do anything.
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
}
catch (MqttCommunicationException exception)
{
@@ -266,62 +413,120 @@ namespace MQTTnet.Extensions.ManagedClient
_logger.Warning(exception, $"Publishing application ({message.Id}) message failed.");
if (message.ApplicationMessage.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
if (message.ApplicationMessage.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
_messageQueue.Add(message);
//If QoS 0, we don't want this message to stay on the queue.
//If QoS 1 or 2, it's possible that, when using a cap, this message
//has been booted off the queue by this.PublishAsync, in which case this
//thread will not continue to try to publish it. While this does
//contradict the expected behavior of QoS 1 and 2, that's also true
//for the usage of a message queue cap, so it's still consistent
//with prior behavior in that way.
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);
}
}
}
}
catch (Exception exception)
{
transmitException = exception;
_logger.Error(exception, $"Unhandled exception while publishing application message ({message.Id}).");
_logger.Error(exception, $"Error while publishing application message ({message.Id}).");
}
finally
{
ApplicationMessageProcessed?.Invoke(this, new ApplicationMessageProcessedEventArgs(message, transmitException));
var eventHandler = ApplicationMessageProcessedHandler;
if (eventHandler != null)
{
var eventArguments = new ApplicationMessageProcessedEventArgs(message, transmitException);
await eventHandler.HandleApplicationMessageProcessedAsync(eventArguments).ConfigureAwait(false);
}
}
}
private async Task SynchronizeSubscriptionsAsync()
private async Task PublishSubscriptionsAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
_logger.Info(nameof(ManagedMqttClient), "Synchronizing subscriptions");
List<TopicFilter> subscriptions;
HashSet<string> unsubscriptions;
lock (_subscriptions)
var endTime = DateTime.UtcNow + timeout;
while (await _subscriptionsQueuedSignal.WaitAsync(GetRemainingTime(endTime), cancellationToken).ConfigureAwait(false))
{
subscriptions = _subscriptions.Select(i => new TopicFilter(i.Key, i.Value)).ToList();
List<MqttTopicFilter> subscriptions;
HashSet<string> unsubscriptions;
unsubscriptions = new HashSet<string>(_unsubscriptions);
_unsubscriptions.Clear();
lock (_subscriptions)
{
subscriptions = _subscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
_subscriptions.Clear();
unsubscriptions = new HashSet<string>(_unsubscriptions);
_unsubscriptions.Clear();
}
_subscriptionsNotPushed = false;
if (!subscriptions.Any() && !unsubscriptions.Any())
{
continue;
}
_logger.Verbose($"Publishing subscriptions ({subscriptions.Count} subscriptions and {unsubscriptions.Count} unsubscriptions)");
foreach (var unsubscription in unsubscriptions)
{
_reconnectSubscriptions.Remove(unsubscription);
}
foreach (var subscription in subscriptions)
{
_reconnectSubscriptions[subscription.Topic] = subscription.QualityOfServiceLevel;
}
try
{
if (unsubscriptions.Any())
{
await _mqttClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false);
}
if (subscriptions.Any())
{
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
}
}
catch (Exception exception)
{
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
}
}
}
if (!subscriptions.Any() && !unsubscriptions.Any())
{
return;
}
private async Task PublishReconnectSubscriptionsAsync()
{
_logger.Info("Publishing subscriptions at reconnect");
try
{
if (subscriptions.Any())
if (_reconnectSubscriptions.Any())
{
await _mqttClient.SubscribeAsync(subscriptions).ConfigureAwait(false);
}
if (unsubscriptions.Any())
{
await _mqttClient.UnsubscribeAsync(unsubscriptions).ConfigureAwait(false);
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value });
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
}
}
catch (Exception exception)
{
_logger.Warning(exception, "Synchronizing subscriptions failed.");
_subscriptionsNotPushed = true;
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
}
}
SynchronizingSubscriptionsFailed?.Invoke(this, new MqttManagedProcessFailedEventArgs(exception));
private 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);
}
}
@@ -334,31 +539,21 @@ namespace MQTTnet.Extensions.ManagedClient
try
{
await _mqttClient.ConnectAsync(_options.ClientOptions).ConfigureAwait(false);
return ReconnectionResult.Reconnected;
var result = await _mqttClient.ConnectAsync(Options.ClientOptions).ConfigureAwait(false);
return result.IsSessionPresent ? ReconnectionResult.Recovered : ReconnectionResult.Reconnected;
}
catch (Exception exception)
{
ConnectingFailed?.Invoke(this, new MqttManagedProcessFailedEventArgs(exception));
var connectingFailedHandler = ConnectingFailedHandler;
if (connectingFailedHandler != null)
{
await connectingFailedHandler.HandleConnectingFailedAsync(new ManagedProcessFailedEventArgs(exception)).ConfigureAwait(false);
}
return ReconnectionResult.NotConnected;
}
}
private void OnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs eventArgs)
{
ApplicationMessageReceived?.Invoke(this, eventArgs);
}
private void OnDisconnected(object sender, MqttClientDisconnectedEventArgs eventArgs)
{
Disconnected?.Invoke(this, eventArgs);
}
private void OnConnected(object sender, MqttClientConnectedEventArgs eventArgs)
{
Connected?.Invoke(this, eventArgs);
}
private void StartPublishing()
{
if (_publishingCancellationToken != null)
@@ -367,10 +562,9 @@ namespace MQTTnet.Extensions.ManagedClient
}
var cts = new CancellationTokenSource();
_publishingCancellationToken = cts;
Task.Factory.StartNew(() => PublishQueuedMessages(cts.Token), cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task.Run(() => PublishQueuedMessagesAsync(cts.Token), cts.Token).Forget(_logger);
}
private void StopPublishing()
@@ -386,5 +580,11 @@ namespace MQTTnet.Extensions.ManagedClient
_connectionCancellationToken?.Dispose();
_connectionCancellationToken = null;
}
private TimeSpan GetRemainingTime(DateTime endTime)
{
var remainingTime = endTime - DateTime.UtcNow;
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime;
}
}
}
@@ -1,39 +1,232 @@
using System;
using System.Threading.Tasks;
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
{
public static class ManagedMqttClientExtensions
{
public static Task SubscribeAsync(this IManagedMqttClient managedClient, params TopicFilter[] topicFilters)
public static IManagedMqttClient UseConnectedHandler(this IManagedMqttClient client, Func<MqttClientConnectedEventArgs, Task> handler)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
if (client == null) throw new ArgumentNullException(nameof(client));
return managedClient.SubscribeAsync(topicFilters);
if (handler == null)
{
return client.UseConnectedHandler((IMqttClientConnectedHandler)null);
}
return client.UseConnectedHandler(new MqttClientConnectedHandlerDelegate(handler));
}
public static Task SubscribeAsync(this IManagedMqttClient managedClient, string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
public static IManagedMqttClient UseConnectedHandler(this IManagedMqttClient client, Action<MqttClientConnectedEventArgs> handler)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
if (client == null) throw new ArgumentNullException(nameof(client));
if (handler == null)
{
return client.UseConnectedHandler((IMqttClientConnectedHandler)null);
}
return client.UseConnectedHandler(new MqttClientConnectedHandlerDelegate(handler));
}
public static IManagedMqttClient UseConnectedHandler(this IManagedMqttClient client, IMqttClientConnectedHandler handler)
{
if (client == null) throw new ArgumentNullException(nameof(client));
client.ConnectedHandler = handler;
return client;
}
public static IManagedMqttClient UseDisconnectedHandler(this IManagedMqttClient client, Func<MqttClientDisconnectedEventArgs, Task> handler)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (handler == null)
{
return client.UseDisconnectedHandler((IMqttClientDisconnectedHandler)null);
}
return client.UseDisconnectedHandler(new MqttClientDisconnectedHandlerDelegate(handler));
}
public static IManagedMqttClient UseDisconnectedHandler(this IManagedMqttClient client, Action<MqttClientDisconnectedEventArgs> handler)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (handler == null)
{
return client.UseDisconnectedHandler((IMqttClientDisconnectedHandler)null);
}
return client.UseDisconnectedHandler(new MqttClientDisconnectedHandlerDelegate(handler));
}
public static IManagedMqttClient UseDisconnectedHandler(this IManagedMqttClient client, IMqttClientDisconnectedHandler handler)
{
if (client == null) throw new ArgumentNullException(nameof(client));
client.DisconnectedHandler = handler;
return client;
}
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
where TReceiver : IApplicationMessageReceiver
{
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
if (handler == null)
{
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
}
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
}
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Action<MqttApplicationMessageReceivedEventArgs> handler)
where TReceiver : IApplicationMessageReceiver
{
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
if (handler == null)
{
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
}
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
}
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, IMqttApplicationMessageReceivedHandler handler)
where TReceiver : IApplicationMessageReceiver
{
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
receiver.ApplicationMessageReceivedHandler = handler;
return receiver;
}
public static Task SubscribeAsync(this IManagedMqttClient client, params MqttTopicFilter[] topicFilters)
{
if (client == null) throw new ArgumentNullException(nameof(client));
return client.SubscribeAsync(topicFilters);
}
public static Task SubscribeAsync(this IManagedMqttClient client, string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return managedClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
}
public static Task SubscribeAsync(this IManagedMqttClient managedClient, string topic)
public static Task SubscribeAsync(this IManagedMqttClient client, string topic)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
if (client == null) throw new ArgumentNullException(nameof(client));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return managedClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
}
public static Task UnsubscribeAsync(this IManagedMqttClient managedClient, params string[] topicFilters)
public static Task UnsubscribeAsync(this IManagedMqttClient client, params string[] topicFilters)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
if (client == null) throw new ArgumentNullException(nameof(client));
return managedClient.UnsubscribeAsync(topicFilters);
return client.UnsubscribeAsync(topicFilters);
}
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, IEnumerable<MqttApplicationMessage> applicationMessages)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
foreach (var applicationMessage in applicationMessages)
{
await publisher.PublishAsync(applicationMessage).ConfigureAwait(false);
}
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
return publisher.PublishAsync(applicationMessage, CancellationToken.None);
}
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, params MqttApplicationMessage[] applicationMessages)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
foreach (var applicationMessage in applicationMessages)
{
await publisher.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
}
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return publisher.PublishAsync(builder => builder
.WithTopic(topic));
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.WithPayload(payload));
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel(qualityOfServiceLevel));
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
if (topic == null) throw new ArgumentNullException(nameof(topic));
return publisher.PublishAsync(builder => builder
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel(qualityOfServiceLevel)
.WithRetainFlag(retain));
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
var message = builder(new MqttApplicationMessageBuilder()).Build();
return publisher.PublishAsync(message, cancellationToken);
}
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
{
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
var message = builder(new MqttApplicationMessageBuilder()).Build();
return publisher.PublishAsync(message, CancellationToken.None);
}
}
}
@@ -1,5 +1,7 @@
using System;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
namespace MQTTnet.Extensions.ManagedClient
{
@@ -9,6 +11,12 @@ namespace MQTTnet.Extensions.ManagedClient
public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5);
public TimeSpan ConnectionCheckInterval { get; set; } = TimeSpan.FromSeconds(1);
public IManagedMqttClientStorage Storage { get; set; }
public int MaxPendingMessages { get; set; } = int.MaxValue;
public MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; set; } = MqttPendingMessagesOverflowStrategy.DropNewMessage;
}
}
@@ -1,5 +1,7 @@
using System;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
namespace MQTTnet.Extensions.ManagedClient
{
@@ -8,6 +10,18 @@ namespace MQTTnet.Extensions.ManagedClient
private readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
private MqttClientOptionsBuilder _clientOptionsBuilder;
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
{
_options.MaxPendingMessages = value;
return this;
}
public ManagedMqttClientOptionsBuilder WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy value)
{
_options.PendingMessagesOverflowStrategy = value;
return this;
}
public ManagedMqttClientOptionsBuilder WithAutoReconnectDelay(TimeSpan value)
{
_options.AutoReconnectDelay = value;
@@ -28,7 +28,9 @@ namespace MQTTnet.Extensions.ManagedClient
public async Task AddAsync(ManagedMqttApplicationMessage applicationMessage)
{
using (await _messagesLock.LockAsync(CancellationToken.None).ConfigureAwait(false))
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
using (await _messagesLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
{
_messages.Add(applicationMessage);
await SaveAsync().ConfigureAwait(false);
@@ -37,7 +39,9 @@ namespace MQTTnet.Extensions.ManagedClient
public async Task RemoveAsync(ManagedMqttApplicationMessage applicationMessage)
{
using (await _messagesLock.LockAsync(CancellationToken.None).ConfigureAwait(false))
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
using (await _messagesLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
{
var index = _messages.IndexOf(applicationMessage);
if (index == -1)
@@ -0,0 +1,14 @@
using System;
namespace MQTTnet.Extensions.ManagedClient
{
public class ManagedProcessFailedEventArgs : EventArgs
{
public ManagedProcessFailedEventArgs(Exception exception)
{
Exception = exception ?? throw new ArgumentNullException(nameof(exception));
}
public Exception Exception { get; }
}
}
@@ -1,24 +1,23 @@
using System;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics;
using System;
namespace MQTTnet.Extensions.ManagedClient
{
public static class MqttFactoryExtensions
{
public static IManagedMqttClient CreateManagedMqttClient(this IMqttClientFactory factory)
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
return new ManagedMqttClient(factory.CreateMqttClient(), new MqttNetLogger().CreateChildLogger());
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger);
}
public static IManagedMqttClient CreateManagedMqttClient(this IMqttClientFactory factory, IMqttNetLogger logger)
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory, IMqttNetLogger logger)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
if (logger == null) throw new ArgumentNullException(nameof(logger));
return new ManagedMqttClient(factory.CreateMqttClient(), logger.CreateChildLogger());
return new ManagedMqttClient(factory.CreateMqttClient(logger), logger);
}
}
}
}
@@ -1,14 +0,0 @@
using System;
namespace MQTTnet.Extensions.ManagedClient
{
public class MqttManagedProcessFailedEventArgs : EventArgs
{
public MqttManagedProcessFailedEventArgs(Exception exception)
{
Exception = exception;
}
public Exception Exception { get; }
}
}
@@ -4,6 +4,7 @@
{
StillConnected,
Reconnected,
Recovered,
NotConnected
}
}
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Extensions.ManagedClient
{
public class SynchronizingSubscriptionsFailedHandlerDelegate : ISynchronizingSubscriptionsFailedHandler
{
private readonly Func<ManagedProcessFailedEventArgs, Task> _handler;
public SynchronizingSubscriptionsFailedHandlerDelegate(Action<ManagedProcessFailedEventArgs> handler)
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
_handler = context =>
{
handler(context);
return Task.FromResult(0);
};
}
public SynchronizingSubscriptionsFailedHandlerDelegate(Func<ManagedProcessFailedEventArgs, Task> handler)
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
}
public Task HandleSynchronizingSubscriptionsFailedAsync(ManagedProcessFailedEventArgs eventArgs)
{
return _handler(eventArgs);
}
}
}
@@ -1,18 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;net452;net461;uap10.0</TargetFrameworks>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</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>
@@ -21,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>
+54 -18
View File
@@ -1,24 +1,38 @@
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 : IDisposable
{
private readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
private readonly IMqttClient _mqttClient;
private readonly IMqttRpcClientOptions _options;
private 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));
_mqttClient.ApplicationMessageReceived += OnApplicationMessageReceived;
_applicationMessageReceivedHandler = new RpcAwareApplicationMessageReceivedHandler(
mqttClient.ApplicationMessageReceivedHandler,
HandleApplicationMessageReceivedAsync);
_mqttClient.ApplicationMessageReceivedHandler = _applicationMessageReceivedHandler;
}
public Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
@@ -45,8 +59,31 @@ namespace MQTTnet.Extensions.Rpc
throw new ArgumentException("The method name cannot contain /, + or #.");
}
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{methodName}";
var responseTopic = requestTopic + "/response";
if (!(_mqttClient.ApplicationMessageReceivedHandler is RpcAwareApplicationMessageReceivedHandler))
{
throw new InvalidOperationException("The application message received handler was modified.");
}
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)
@@ -64,7 +101,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))
{
@@ -102,26 +139,25 @@ namespace MQTTnet.Extensions.Rpc
}
}
private void OnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs eventArgs)
private Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
{
if (!_waitingCalls.TryRemove(eventArgs.ApplicationMessage.Topic, out var tcs))
{
return;
}
if (tcs.Task.IsCompleted || tcs.Task.IsCanceled)
{
return;
return Task.FromResult(0);
}
tcs.TrySetResult(eventArgs.ApplicationMessage.Payload);
return Task.FromResult(0);
}
public void Dispose()
{
_mqttClient.ApplicationMessageReceivedHandler = _applicationMessageReceivedHandler.OriginalHandler;
foreach (var tcs in _waitingCalls)
{
tcs.Value.SetCanceled();
tcs.Value.TrySetCanceled();
}
_waitingCalls.Clear();
@@ -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 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 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 class MqttRpcTopicPair
{
public string RequestTopic { get; set; }
public string ResponseTopic { get; set; }
}
}
@@ -0,0 +1,19 @@
using System;
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
{
public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context)
{
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,16 @@
using MQTTnet.Client;
using MQTTnet.Protocol;
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public class TopicGenerationContext
{
public string MethodName { get; set; }
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
public IMqttClient MqttClient { get; set; }
public IMqttRpcClientOptions Options { get; set; }
}
}
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
using MQTTnet.Client.Receiving;
namespace MQTTnet.Extensions.Rpc
{
public class RpcAwareApplicationMessageReceivedHandler : IMqttApplicationMessageReceivedHandler
{
private readonly Func<MqttApplicationMessageReceivedEventArgs, Task> _handleReceivedApplicationMessageAsync;
public RpcAwareApplicationMessageReceivedHandler(
IMqttApplicationMessageReceivedHandler originalHandler,
Func<MqttApplicationMessageReceivedEventArgs, Task> handleReceivedApplicationMessageAsync)
{
OriginalHandler = originalHandler;
_handleReceivedApplicationMessageAsync = handleReceivedApplicationMessageAsync ?? throw new ArgumentNullException(nameof(handleReceivedApplicationMessageAsync));
}
public IMqttApplicationMessageReceivedHandler OriginalHandler { get; }
public async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
{
if (OriginalHandler != null)
{
await OriginalHandler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
}
await _handleReceivedApplicationMessageAsync(eventArgs).ConfigureAwait(false);
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ _mqttClient.subscribe("MQTTnet.RPC/+/ping");
_mqttClient.subscribe("MQTTnet.RPC/+/do_something");
// It is not allowed to change the structure of the topic. Otherwise RPC will not work. So method names can be separated using
// an _ or . but no +, # or . If it is required to distinguish between devices own rules can be defined like the following.
// an _ or . but no +, # or /. If it is required to distinguish between devices own rules can be defined like the following.
_mqttClient.subscribe("MQTTnet.RPC/+/deviceA.ping");
_mqttClient.subscribe("MQTTnet.RPC/+/deviceB.ping");
_mqttClient.subscribe("MQTTnet.RPC/+/deviceC.getTemperature");
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1</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.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
<DefineConstants>$(DefineConstants);WINDOWS_UWP</DefineConstants>
<DefaultLanguage>en</DefaultLanguage>
<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>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,14 @@
using System;
namespace MQTTnet.Extensions.WebSocket4Net
{
public static class MqttFactoryExtensions
{
public static IMqttFactory UseWebSocket4Net(this IMqttFactory mqttFactory)
{
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory(mqttFactory.DefaultLogger));
}
}
}
@@ -0,0 +1,238 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Channel;
using MQTTnet.Client.Options;
using MQTTnet.Exceptions;
using MQTTnet.Internal;
using SuperSocket.ClientEngine;
using WebSocket4Net;
namespace MQTTnet.Extensions.WebSocket4Net
{
public class WebSocket4NetMqttChannel : IMqttChannel
{
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
private readonly IMqttClientOptions _clientOptions;
private readonly MqttClientWebSocketOptions _webSocketOptions;
private WebSocket _webSocket;
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions, MqttClientWebSocketOptions webSocketOptions)
{
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions));
_webSocketOptions = webSocketOptions ?? throw new ArgumentNullException(nameof(webSocketOptions));
}
public string Endpoint => _webSocketOptions.Uri;
public bool IsSecureConnection { get; private set; }
public X509Certificate2 ClientCertificate { get; }
public async Task ConnectAsync(CancellationToken cancellationToken)
{
var uri = _webSocketOptions.Uri;
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase) && !uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase))
{
if (_webSocketOptions.TlsOptions?.UseTls == false)
{
uri = "ws://" + uri;
}
else
{
uri = "wss://" + uri;
}
}
var sslProtocols = _webSocketOptions?.TlsOptions?.SslProtocol ?? SslProtocols.None;
var subProtocol = _webSocketOptions.SubProtocols.FirstOrDefault() ?? string.Empty;
var cookies = new List<KeyValuePair<string, string>>();
if (_webSocketOptions.CookieContainer != null)
{
throw new NotSupportedException("Cookies are not supported.");
}
List<KeyValuePair<string, string>> customHeaders = null;
if (_webSocketOptions.RequestHeaders != null)
{
customHeaders = _webSocketOptions.RequestHeaders.Select(i => new KeyValuePair<string, string>(i.Key, i.Value)).ToList();
}
EndPoint proxy = null;
if (_webSocketOptions.ProxyOptions != null)
{
throw new NotSupportedException("Proxies are not supported.");
}
// The user agent can be empty always because it is just added to the custom headers as "User-Agent".
var userAgent = string.Empty;
var origin = string.Empty;
var webSocketVersion = WebSocketVersion.None;
var receiveBufferSize = 0;
var certificates = new X509CertificateCollection();
if (_webSocketOptions?.TlsOptions?.Certificates != null)
{
foreach (var certificate in _webSocketOptions.TlsOptions.Certificates)
{
#if WINDOWS_UWP
certificates.Add(new X509Certificate(certificate));
#else
certificates.Add(certificate);
#endif
}
}
_webSocket = new WebSocket(uri, subProtocol, cookies, customHeaders, userAgent, origin, webSocketVersion, proxy, sslProtocols, receiveBufferSize)
{
NoDelay = true,
Security =
{
AllowUnstrustedCertificate = _webSocketOptions?.TlsOptions?.AllowUntrustedCertificates == true,
AllowCertificateChainErrors = _webSocketOptions?.TlsOptions?.IgnoreCertificateChainErrors == true,
Certificates = certificates
}
};
await ConnectInternalAsync(cancellationToken).ConfigureAwait(false);
IsSecureConnection = uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase);
}
public Task DisconnectAsync(CancellationToken cancellationToken)
{
if (_webSocket != null && _webSocket.State == WebSocketState.Open)
{
_webSocket.Close();
}
return Task.FromResult(0);
}
public Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
var readBytes = 0;
while (count > 0 && !cancellationToken.IsCancellationRequested)
{
if (!_receiveBuffer.TryTake(out var @byte))
{
if (readBytes == 0)
{
// Block until at least one byte was received.
@byte = _receiveBuffer.Take(cancellationToken);
}
else
{
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)
{
return;
}
_webSocket.DataReceived -= OnDataReceived;
_webSocket.Error -= OnError;
_webSocket.Dispose();
_webSocket = null;
}
private void OnError(object sender, ErrorEventArgs e)
{
System.Diagnostics.Debug.Write(e.Exception.ToString());
}
private void OnDataReceived(object sender, DataReceivedEventArgs e)
{
foreach (var @byte in e.Data)
{
_receiveBuffer.Add(@byte);
}
}
private async Task ConnectInternalAsync(CancellationToken cancellationToken)
{
_webSocket.Error += OnError;
_webSocket.DataReceived += OnDataReceived;
var taskCompletionSource = new TaskCompletionSource<Exception>();
void ErrorHandler(object sender, ErrorEventArgs e)
{
taskCompletionSource.TrySetResult(e.Exception);
}
void SuccessHandler(object sender, EventArgs e)
{
taskCompletionSource.TrySetResult(null);
}
try
{
_webSocket.Opened += SuccessHandler;
_webSocket.Error += ErrorHandler;
_webSocket.Open();
var exception = await MqttTaskTimeout.WaitAsync(c =>
{
c.Register(() => taskCompletionSource.TrySetCanceled());
return taskCompletionSource.Task;
}, _clientOptions.CommunicationTimeout, cancellationToken).ConfigureAwait(false);
if (exception != null)
{
if (exception is AuthenticationException authenticationException)
{
throw new MqttCommunicationException(authenticationException.InnerException);
}
if (exception is OperationCanceledException)
{
throw new MqttCommunicationTimedOutException();
}
throw new MqttCommunicationException(exception);
}
}
catch (OperationCanceledException)
{
throw new MqttCommunicationTimedOutException();
}
finally
{
_webSocket.Opened -= SuccessHandler;
_webSocket.Error -= ErrorHandler;
}
}
}
}
@@ -0,0 +1,42 @@
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
{
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));
switch (options.ChannelOptions)
{
case MqttClientTcpOptions _:
{
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), _logger);
}
case MqttClientWebSocketOptions webSocketOptions:
{
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options, webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), _logger);
}
default:
{
throw new NotSupportedException();
}
}
}
}
}
@@ -0,0 +1,134 @@
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);
}
}
}
@@ -0,0 +1,53 @@
namespace MQTTnet.Server.Configuration
{
/// <summary>
/// MQTT settings Model
/// </summary>
public class MqttSettingsModel
{
/// <summary>
/// Set default connection timeout in seconds
/// </summary>
public int CommunicationTimeout { get; set; } = 15;
/// <summary>
/// Set 0 to disable connection backlogging
/// </summary>
public int ConnectionBacklog { get; set; }
/// <summary>
/// Enable support for persistent sessions
/// </summary>
public bool EnablePersistentSessions { get; set; } = false;
/// <summary>
/// Listen Settings
/// </summary>
public TcpEndPointModel TcpEndPoint { get; set; } = new TcpEndPointModel();
/// <summary>
/// Encryption Listen Settings
/// </summary>
public TcpEndPointModel EncryptedTcpEndPoint { get; set; } = new TcpEndPointModel();
/// <summary>
/// Settings for the Web Socket endpoint.
/// </summary>
public WebSocketEndPointModel WebSocketEndPoint { get; set; } = new WebSocketEndPointModel();
/// <summary>
/// Set limit for max pending messages per client
/// </summary>
public int MaxPendingMessagesPerClient { get; set; } = 250;
/// <summary>
/// The settings for retained messages.
/// </summary>
public RetainedApplicationMessagesModel RetainedApplicationMessages { get; set; } = new RetainedApplicationMessagesModel();
/// <summary>
/// Enables or disables the MQTTnet internal logging.
/// </summary>
public bool EnableDebugLogging { get; set; } = false;
}
}
@@ -0,0 +1,24 @@
using System;
using System.IO;
namespace MQTTnet.Server.Configuration
{
public static class PathHelper
{
public static string ExpandPath(string path)
{
if (path == null)
{
return null;
}
var uri = new Uri(path, UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri)
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
}
return path;
}
}
}
@@ -0,0 +1,11 @@
namespace MQTTnet.Server.Configuration
{
public class RetainedApplicationMessagesModel
{
public bool Persist { get; set; } = false;
public int WriteInterval { get; set; } = 10;
public string Path { get; set; }
}
}
@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace MQTTnet.Server.Configuration
{
public class ScriptingSettingsModel
{
public string ScriptsPath { get; set; }
public List<string> IncludePaths { get; set; }
}
}
@@ -0,0 +1,102 @@
using System.IO;
using System.Net;
namespace MQTTnet.Server.Configuration
{
/// <summary>
/// Listen Entry Settings Model
/// </summary>
public class TcpEndPointModel
{
/// <summary>
/// Certificate settings.
/// </summary>
public CertificateSettingsModel Certificate { get; set; }
/// <summary>
/// Enabled / Disable
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// Listen Address
/// </summary>
public string IPv4 { get; set; }
/// <summary>
/// Listen Address
/// </summary>
public string IPv6 { get; set; }
/// <summary>
/// Listen Port
/// </summary>
public int Port { get; set; } = 1883;
/// <summary>
/// Read IPv4
/// </summary>
/// <returns></returns>
public bool TryReadIPv4(out IPAddress address)
{
if (IPv4 == "*")
{
address = IPAddress.Any;
return true;
}
if (IPv4 == "localhost")
{
address = IPAddress.Loopback;
return true;
}
if (IPv4 == "disable")
{
address = IPAddress.None;
return true;
}
if (IPAddress.TryParse(IPv4, out var ip))
{
address = ip;
return true;
}
throw new System.Exception($"Could not parse IPv4 address: {IPv4}");
}
/// <summary>
/// Read IPv6
/// </summary>
/// <returns></returns>
public bool TryReadIPv6(out IPAddress address)
{
if (IPv6 == "*")
{
address = IPAddress.IPv6Any;
return true;
}
if (IPv6 == "localhost")
{
address = IPAddress.IPv6Loopback;
return true;
}
if (IPv6 == "disable")
{
address = IPAddress.None;
return true;
}
if (IPAddress.TryParse(IPv6, out var ip))
{
address = ip;
return true;
}
throw new System.Exception($"Could not parse IPv6 address: {IPv6}");
}
}
}
@@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace MQTTnet.Server.Configuration
{
public class WebSocketEndPointModel
{
public bool Enabled { get; set; } = true;
public string Path { get; set; } = "/mqtt";
public int ReceiveBufferSize { get; set; } = 4096;
public int KeepAliveInterval { get; set; } = 120;
public List<string> AllowedOrigins { get; set; }
}
}
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MQTTnet.Server.Mqtt;
using MQTTnet.Server.Status;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class ClientsController : Controller
{
private readonly MqttServerService _mqttServerService;
public ClientsController(MqttServerService mqttServerService)
{
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService));
}
[Route("api/v1/clients")]
[HttpGet]
public async Task<ActionResult<IList<IMqttClientStatus>>> GetClients()
{
return new ObjectResult(await _mqttServerService.GetClientStatusAsync());
}
[Route("api/v1/clients/{clientId}")]
[HttpGet]
public async Task<ActionResult<IMqttClientStatus>> GetClient(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var client = (await _mqttServerService.GetClientStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (client == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
return new ObjectResult(client);
}
[Route("api/v1/clients/{clientId}")]
[HttpDelete]
public async Task<ActionResult> DeleteClient(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var client = (await _mqttServerService.GetClientStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (client == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
await client.DisconnectAsync();
return StatusCode((int)HttpStatusCode.NoContent);
}
[Route("api/v1/clients/{clientId}/statistics")]
[HttpDelete]
public async Task<ActionResult> DeleteClientStatistics(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var client = (await _mqttServerService.GetClientStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (client == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
client.ResetStatistics();
return StatusCode((int)HttpStatusCode.NoContent);
}
}
}
@@ -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);
}
}
}
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MQTTnet.Server.Mqtt;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class RetainedApplicationMessagesController : Controller
{
private readonly MqttServerService _mqttServerService;
public RetainedApplicationMessagesController(MqttServerService mqttServerService)
{
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService));
}
[Route("api/v1/retainedApplicationMessages")]
[HttpGet]
public async Task<ActionResult<IList<MqttApplicationMessage>>> GetRetainedApplicationMessages()
{
return new ObjectResult(await _mqttServerService.GetRetainedApplicationMessagesAsync());
}
[Route("api/v1/retainedApplicationMessages/{topic}")]
[HttpGet]
public async Task<ActionResult<MqttApplicationMessage>> GetRetainedApplicationMessage(string topic)
{
topic = HttpUtility.UrlDecode(topic);
var applicationMessage = (await _mqttServerService.GetRetainedApplicationMessagesAsync()).FirstOrDefault(c => c.Topic == topic);
if (applicationMessage == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
return new ObjectResult(applicationMessage);
}
[Route("api/v1/retainedApplicationMessages")]
[HttpDelete]
public async Task<ActionResult> DeleteRetainedApplicationMessages()
{
await _mqttServerService.ClearRetainedApplicationMessagesAsync();
return StatusCode((int)HttpStatusCode.NoContent);
}
[Route("api/v1/retainedApplicationMessages/{topic}")]
[HttpDelete]
public async Task<ActionResult> DeleteRetainedApplicationMessage(string topic)
{
topic = HttpUtility.UrlDecode(topic);
await _mqttServerService.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithRetainFlag().Build());
return StatusCode((int)HttpStatusCode.NoContent);
}
}
}
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MQTTnet.Server.Scripting;
using MQTTnet.Server.Web;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class ScriptsController : Controller
{
private readonly PythonScriptHostService _pythonScriptHostService;
public ScriptsController(PythonScriptHostService pythonScriptHostService)
{
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
}
[Route("api/v1/scripts")]
[HttpGet]
public ActionResult<List<string>> GetScriptUids()
{
return _pythonScriptHostService.GetScriptUids();
}
[Route("api/v1/scripts/uid")]
[HttpGet]
public async Task<ActionResult<string>> GetScript(string uid)
{
var script = await _pythonScriptHostService.ReadScriptAsync(uid, HttpContext.RequestAborted);
if (script == null)
{
return NotFound();
}
return Content(script);
}
[Route("api/v1/scripts/uid")]
[HttpPost]
public Task PostScript(string uid)
{
var code = HttpContext.Request.ReadBodyAsString();
return _pythonScriptHostService.WriteScriptAsync(uid, code, CancellationToken.None);
}
[Route("api/v1/scripts/uid")]
[HttpDelete]
public Task DeleteScript(string uid)
{
return _pythonScriptHostService.DeleteScriptAsync(uid);
}
[Route("api/v1/scripts/initialize")]
[HttpPost]
public Task PostInitializeScripts()
{
return _pythonScriptHostService.TryInitializeScriptsAsync();
}
}
}
@@ -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();
}
}
}
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MQTTnet.Server.Mqtt;
using MQTTnet.Server.Status;
namespace MQTTnet.Server.Controllers
{
[Authorize]
[ApiController]
public class SessionsController : Controller
{
private readonly MqttServerService _mqttServerService;
public SessionsController(MqttServerService mqttServerService)
{
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService));
}
[Route("api/v1/sessions")]
[HttpGet]
public async Task<ActionResult<IList<IMqttSessionStatus>>> GetSessions()
{
return new ObjectResult(await _mqttServerService.GetSessionStatusAsync());
}
[Route("api/v1/sessions/{clientId}")]
[HttpGet]
public async Task<ActionResult<IMqttClientStatus>> GetSession(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (session == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
return new ObjectResult(session);
}
[Route("api/v1/sessions/{clientId}")]
[HttpDelete]
public async Task<ActionResult> DeleteSession(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (session == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
await session.DeleteAsync();
return StatusCode((int)HttpStatusCode.NoContent);
}
[Route("api/v1/sessions/{clientId}/pendingApplicationMessages")]
[HttpDelete]
public async Task<ActionResult> DeletePendingApplicationMessages(string clientId)
{
clientId = HttpUtility.UrlDecode(clientId);
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId);
if (session == null)
{
return new StatusCodeResult((int)HttpStatusCode.NotFound);
}
await session.ClearPendingApplicationMessagesAsync();
return StatusCode((int)HttpStatusCode.NoContent);
}
}
}
+97
View File
@@ -0,0 +1,97 @@
# MQTTnet
MIT License
Copyright (c) 2019 MQTTnet Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Swashbuckle
Copyright (c) 2013, Richard Morris
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
# IronPython
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
@@ -0,0 +1,43 @@
//using MQTTnet.Diagnostics;
//using System;
//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));
// _source = 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 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 Error(Exception exception, string message, params object[] parameters)
// {
// _logger.Publish(MqttNetLogLevel.Error, _source, message, parameters, exception);
// }
// }
//}
@@ -0,0 +1,64 @@
using Microsoft.Extensions.Logging;
using MQTTnet.Diagnostics;
using System;
using System.Threading;
namespace MQTTnet.Server.Logging
{
public sealed class MqttNetLoggerWrapper : IMqttNetLogger
{
readonly ILogger<MqttServer> _logger;
public MqttNetLoggerWrapper(ILogger<MqttServer> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
public IMqttNetScopedLogger CreateScopedLogger(string source)
{
return new MqttNetScopedLogger(this, source);
}
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
{
var convertedLogLevel = ConvertLogLevel(level);
_logger.Log(convertedLogLevel, exception, message, parameters);
var logMessagePublishedEvent = LogMessagePublished;
if (logMessagePublishedEvent != null)
{
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));
}
}
public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception)
{
Publish(logLevel, null, message, parameters, exception);
}
static LogLevel ConvertLogLevel(MqttNetLogLevel logLevel)
{
switch (logLevel)
{
case MqttNetLogLevel.Error: return LogLevel.Error;
case MqttNetLogLevel.Warning: return LogLevel.Warning;
case MqttNetLogLevel.Info: return LogLevel.Information;
case MqttNetLogLevel.Verbose: return LogLevel.Debug;
}
return LogLevel.Debug;
}
}
}
@@ -0,0 +1,86 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<AssemblyName>MQTTnet.Server</AssemblyName>
<RootNamespace>MQTTnet.Server</RootNamespace>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Company />
<Product>MQTTnet</Product>
<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>3.0.11</Version>
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
</PropertyGroup>
<PropertyGroup>
<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'">
<DocumentationFile></DocumentationFile>
<WarningsAsErrors>NU1605</WarningsAsErrors>
<NoWarn>1701;1702</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronPython" Version="2.7.10" />
<PackageReference Include="IronPython.StdLib" Version="2.7.10" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.5" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="LICENSE">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="README.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Scripts\README.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Scripts\00_sample.py">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<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\" />
</ItemGroup>
</Project>

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