Compare commits

...
Author SHA1 Message Date
Christian 25b42df85c Refactor code 2023-01-19 20:53:57 +01:00
Christian f8d614e71f Merge branch 'master' into Managed-Client-V2 2023-01-19 20:50:34 +01:00
Christian 2aa4219838 Expose server session items (#1638)
* Expose server session items

* Add support for custom session items for injected application messages
2023-01-19 20:15:15 +01:00
Günther Foidl b98417ab39 Avoid some full memory barriers (#1590)
* Avoid some full memory barriers

* Reset in stats itself

* Updated MqttClientStatistics

* Fixed order of members as artifact from merge-conflict
2023-01-19 20:08:51 +01:00
Christian 7bb29d3c92 Merge master 2022-12-28 14:15:27 +01:00
Christian 4d81d3f3d9 Merge branch 'master' into Managed-Client-V2 2022-12-28 14:15:21 +01:00
Christian ead58dd606 Update ci.yml 2022-12-28 13:59:05 +01:00
Christian a93e935585 Update ci.yml 2022-12-28 09:37:01 +01:00
Christian aeb07e880e Update ReleaseNotes.md 2022-12-28 09:25:33 +01:00
Jeffery Michael e0ce1f309e dotnet 7 packages (#1636)
* Added dotnet 7 support/builds.

* Added NETCOREAPP_3_1_OR_GREATER where applicable.
2022-12-28 09:20:11 +01:00
Christian d74c81c3d1 Fix unit tests 2022-12-23 20:01:13 +01:00
Christian 2fa7200fb3 1544 add underlying socketoption of tcp keepalive into the server option (#1606)
* Expose TCP keep alive options to options builder

* Update ReleaseNotes.md
2022-12-23 17:15:49 +01:00
Christian 9f7d15e1b1 Update ReleaseNotes.md 2022-12-23 17:13:25 +01:00
Christian fdf00f1b18 More options for disconnect (#1557)
* Expose more options in disconnect options.

* Expose more options in disconnect API.

* Refactor code.

* Expose user properties in disconnected event.

* Expose more disconnect options in server.

* Fix build errors

* Add new samples.

* Fix client cleanup

* Fix merge conflicts
2022-12-23 17:09:02 +01:00
ghord abe7bbda15 Pass correct clientId to Unsubscribe interceptor (#1631) 2022-12-23 17:02:03 +01:00
ChristianandHansM 795139d78f Add feature validations (#1527)
* Add feature validation.

* Update ReleaseNotes.md

* Add validators or subscribe and unsubscribe.

* Add feature validation for disconnect.

* Fix build errors.

* Fix build errors

Co-authored-by: HansM <HansM2013@gmx.de>
2022-12-23 16:56:11 +01:00
Christian c7390ef0d7 Update verison 2022-12-23 16:51:13 +01:00
老九andGünther Foidl 8a926a3db3 Performance optimization of SendPacketAsync (#1624)
* performance optimization of SendPacketAsync

* Update Source/MQTTnet.AspnetCore/MqttConnectionContext.cs

Co-authored-by: Günther Foidl <gue@korporal.at>

Co-authored-by: Günther Foidl <gue@korporal.at>
2022-12-16 17:13:11 +01:00
soyoo 7d5e49b44c A typo in comment. (#1628) 2022-12-16 17:12:46 +01:00
Christian 555c3eac7a Reset release notes 2022-12-13 17:15:43 +01:00
Christian f79649d71b 1612 mqttserver subscription to similar base and subtopic with wildcards fails (#1622) 2022-12-07 20:59:52 +01:00
dependabot[bot] c9c27b9f01 Bump Newtonsoft.Json from 13.0.1 to 13.0.2 in /Source/MQTTnet.TestApp (#1621)
Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 13.0.1 to 13.0.2.
- [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases)
- [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/13.0.1...13.0.2)

---
updated-dependencies:
- dependency-name: Newtonsoft.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 20:57:29 +01:00
Christian 0bc47cf853 Improve unit tests 2022-12-07 20:50:34 +01:00
Christian 5649328bc5 Update release notes 2022-12-07 20:44:30 +01:00
Christian 726dd15c5a Cleanup projects 2022-12-07 20:44:23 +01:00
Christian d513c6f85c Refactor code 2022-12-07 19:43:10 +01:00
老九 c1c17ba162 MqttConnectionContext: Adapting mqtt over tcp (#1616)
Adapting mqtt over tcp.
2022-12-07 19:36:13 +01:00
soyoo f8aa686557 A typo in comment. (#1618) 2022-12-07 17:08:15 +01:00
Christian d7eb4bbe6e Allow interception of will messages (#1613) 2022-12-06 20:28:01 +01:00
Christian c17a350796 1595 object disposed exception in unit test handle parallel connection attempts (#1610) 2022-12-05 19:22:18 +01:00
Christian bb106f8c6e Refactor code 2022-12-05 19:21:08 +01:00
老九 09e47fb5eb Avoid a split MqttPacketBuffer transfer caused by triggering PipeWriter.WriteAsync twice. (#1609)
Avoid a split MqttPacketBuffer transfer caused by triggering PipeWriter.FlushAsync twice.
2022-12-05 19:19:31 +01:00
Christian 099209fff2 Update README.md 2022-12-04 14:10:54 +01:00
Christian d572490a67 Use the net452 supporting async task completion source (#1607) 2022-12-04 13:39:50 +01:00
Christian 180e7f79d4 Update ci.yml 2022-12-03 14:50:30 +01:00
Christian d9da7cc92e Refactor code 2022-12-03 14:09:27 +01:00
Christian c2ce2044cc Merge branch 'master' of https://github.com/dotnet/MQTTnet 2022-12-03 13:19:38 +01:00
Christian e400bfb79e Update ci.yml 2022-12-03 13:19:37 +01:00
老九andChristian 3d32faa8f9 Avoid copying buffer from ReadOnlySequence as ReceivedMqttPacket body (#1596)
* Avoid copying buffer from ReadOnlySequence as  ReceivedMqttPacket body

* Use ReadOnlySequence.FirstSpan if possible.

* add ReaderExtensionsBenchmark

* update benchmark

* fix fixedHeader incorrect read

Co-authored-by: Christian <6939810+chkr1011@users.noreply.github.com>
2022-12-03 13:18:30 +01:00
老九andChristian 862d76471b Implement buffer copy using different policies (#1599)
use Memory-Copy

Co-authored-by: Christian <6939810+chkr1011@users.noreply.github.com>
2022-12-03 13:17:02 +01:00
老九 27f2474876 fix MqttBufferReader #1597 (#1598) 2022-12-03 13:14:07 +01:00
Christian 01a5aeeb58 Refactor benchmarks (#1601) 2022-11-30 18:09:34 +01:00
老九 47df131e7f Avoid to check the type of propertyWriter parameter (#1600)
Refactor code of MqttBufferWriter
2022-11-30 17:56:05 +01:00
Christian 56750adfe4 1592 bug of mqttbufferreader (#1593) 2022-11-29 20:23:20 +01:00
Christian 11e64ef018 Update ReleaseNotes.md 2022-11-28 21:10:46 +01:00
Christian 9b20e0a430 Refactor code 2022-11-28 21:10:42 +01:00
老九 41df2ec5da Optimize SendPacketAsync method for MQTTnet.AspNetCore (#1582)
* Avoid to call MqttPacketBuffer.Join() when SendPacketAsync

* Safely cleanup the PacketFormatterAdapter

* Keep buffer.Join when mqtt over webSocket

* null checking for IHttpContextFeature.HttpContext
2022-11-28 21:02:13 +01:00
Christian e45b207375 Update ReleaseNotes.md 2022-11-26 14:53:03 +01:00
Christian c37866e534 Refactor code and update release notes 2022-11-26 14:51:36 +01:00
老九 bda4ab7025 Set string.Empty as default value for SenderClientId (#1583) 2022-11-26 14:50:08 +01:00
Christian 32cc1ff7b1 Refactor code and update release notes 2022-11-26 14:49:28 +01:00
Dalibor Kundrat b5952a590a Extend server client ResetStatistics() to reset all client statistics not only channel... (#1587)
Extend reset client statistic to reset all stats
2022-11-26 14:47:17 +01:00
Christian 581a024ceb Improve allocations for AsyncSignal. 2022-11-26 14:45:34 +01:00
Mario ZelgerandMario Zelger c45cb8b04e Dispose the AsyncSignalWaiter before setting it to null (#1586)
dispose the AsyncSignalWaiter before setting it to null to prevent memory leak

Co-authored-by: Mario Zelger <mario.zelger@confer.ch>
2022-11-26 14:19:51 +01:00
Christian a5e1a4d6dd Update version 2022-11-26 14:16:37 +01:00
Christian 3937aa76e3 Fix merge conflicts 2022-11-13 18:41:28 +01:00
Christian 2090b08547 Merge branch 'master' into Managed-Client-V2 2022-11-13 18:13:23 +01:00
Christian e88b280eb0 Reset release notes 2022-11-12 12:53:54 +01:00
Christian e4b07f2b8c Fix build errors 2022-11-12 09:43:55 +01:00
Christian 4eb6e77eb5 Fix build errors due to merge conflicts 2022-11-11 14:41:28 +01:00
Christian db1fc7625d 1546 possible bug in server repeatedly sending the same message to client subscribed with cleansession=false (#1569) 2022-11-11 08:14:15 +01:00
Christian bfec9dc5ad 802 client isnt being notified if message is not delivered (#1568) 2022-11-09 21:14:53 +01:00
Christian 56f0a2c31c Fix validation of topic in managed client (#1567) 2022-11-09 20:13:59 +01:00
Christian 5ee0bb4b65 1565 high cpu load from asyncsignal (#1566) 2022-11-09 19:56:29 +01:00
Christian 5c74728387 Fix client session takeover 2022-11-06 13:28:41 +01:00
Christian 97c46bea0f Update ReleaseNotes.md 2022-11-06 10:50:32 +01:00
Christian e6c1ab4e4c Fail all waiting tasks when the client connection gets closed (#1563) 2022-11-06 10:50:04 +01:00
Christian 6e1ec266a7 Update ReleaseNotes.md 2022-11-06 10:49:19 +01:00
Christian 3fc6982e9a Fix upgrading and downgrading of retained messages QoS for subscriptions (#1564) 2022-11-06 10:35:59 +01:00
SilverFox 5b1cc7d713 Also cleanup MqttClientSessionsManager._subscriberSessions when session is taken over by a new one with CleanSession=true, fix #1552 (#1553) 2022-11-06 10:35:15 +01:00
Christian 2842f27522 1552 mqttnetservermqttclientsessionsmanager subscribersessions is not proper removed on special case (#1562) 2022-11-06 10:34:20 +01:00
Christian 7ef137e26e No longer fire _ClientAcknowledgedPublishPacketEvent_ for PUBREC packets (#1550) (#1551) 2022-11-06 10:29:49 +01:00
Christian b1a336eb62 Reset release notes, update version 2022-11-06 10:24:58 +01:00
Christian d481e93832 Add new samples. 2022-10-25 17:29:45 +02:00
Christian 8cf5537043 Improve unit tests 2022-10-23 08:45:16 +02:00
Christian d2ce9d607a Fix freezes in _AsyncLock_ (#1549) 2022-10-23 08:16:45 +02:00
Christian 36736914bc Fix Xamarin connect freeze (#1545) 2022-10-23 07:51:19 +02:00
Christian 7823d8342e Update version. 2022-10-23 07:43:31 +02:00
Christian 431142471f Add samples. 2022-10-16 11:12:08 +02:00
Christian a3227a444a Reset release notes. 2022-10-01 16:51:11 +02:00
Christian f74af45fba Add new samples. 2022-10-01 11:32:14 +02:00
Christian 7c3fad6147 Implement new managed client. 2022-09-29 18:38:29 +02:00
Christian e050e2d61e Improve async lock (#1520) 2022-09-25 10:26:18 +02:00
Christian ef85ef676a Update README.md 2022-09-16 08:24:52 +02:00
Christian e977546297 Fix cross access to async events. (#1515)
fix cross access to async events.
2022-09-16 08:20:42 +02:00
Rido ae92b0ed33 Add Extensions.MultiCloud to references (#1517) 2022-09-15 09:21:39 +02:00
Christian 7e686d9aa5 Refactor code. 2022-09-15 09:09:08 +02:00
Christian d23bbf7bf3 Improve PingAsync timeout handling. 2022-09-14 14:17:59 +02:00
Christian d4dad4860a Fix and improve session takeover process handling. 2022-09-14 14:15:35 +02:00
Christian c009cbef76 Update comments, release notes, version. 2022-09-13 09:07:02 +02:00
logicaloud 37e60c73ae Send DISCONNECT packets to MQTT5 clients only (#1506) 2022-09-13 09:00:21 +02:00
Christian 3ab095a568 Set web socket boundaries correctly (#1514) 2022-09-13 08:50:02 +02:00
Christian f5d9b65139 Add samples. 2022-08-23 20:58:46 +02:00
Christian 31e5b40459 Revert "Update ci.yml"
This reverts commit 8fb55d75fe.
2022-08-23 20:49:40 +02:00
Christian 8fb55d75fe Update ci.yml 2022-08-14 13:06:32 +02:00
Christian 420222511b Update ReleaseNotes.md 2022-08-13 12:56:05 +02:00
Stan WijckmansandStan Wijckmans c5cec60809 Apply timeout to automatic ping. (#1495)
Co-authored-by: Stan Wijckmans <stanw@aviobook.aero>
2022-08-13 12:53:55 +02:00
Christian 12dd815421 Fix wrong package references in Benchmark project. 2022-08-13 12:45:02 +02:00
Christian f36f49cb3e Add parameter validations. 2022-08-13 12:38:36 +02:00
Christian 9152fe637e Reset release notes. 2022-08-07 09:56:25 +02:00
Christian b976e9c177 Fix build errors. 2022-08-03 20:44:58 +02:00
Christian 262a4681ad Merge branch '1291-access-client-status-in-client-disconnected-handler' 2022-08-03 20:40:53 +02:00
Christian ad546adafe Fix removal of event handlers from async event. 2022-08-03 20:27:53 +02:00
Christian 29a9941d86 Fix breaking changes. 2022-07-31 11:10:38 +02:00
Christian 5a21939e29 Squashed commit of the following:
commit 469caf656e
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sun Jul 31 10:55:40 2022 +0200

    Fix build errors.

commit 42402fba04
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sun Jul 31 10:22:23 2022 +0200

    Allow interception of injected application messages.

commit a0dc8ab0d7
Author: William Lee <31092948+william19821101@users.noreply.github.com>
Date:   Sun Jul 31 15:50:14 2022 +0800

    Update Server_Simple_Samples.cs (#1474)

    Change e.UserName to e.Username
2022-07-31 11:09:39 +02:00
Christian 469caf656e Fix build errors. 2022-07-31 10:55:40 +02:00
Christian 42402fba04 Allow interception of injected application messages. 2022-07-31 10:22:23 +02:00
William Lee a0dc8ab0d7 Update Server_Simple_Samples.cs (#1474)
Change e.UserName to e.Username
2022-07-31 09:50:14 +02:00
Christian 02ede5a2d8 Update MqttClient.cs 2022-07-24 10:44:27 +02:00
Christian cef61900df Merge branch 'master' into 1291-access-client-status-in-client-disconnected-handler 2022-07-23 18:09:05 +02:00
Christian 09385b1b36 Pass session item to several more event handers. 2022-07-23 18:07:49 +02:00
Christian cbf413f04e Squashed commit of the following: 1125-expose-http-context-in-validateconnectionasync
commit 353c9671a04a273798b0b3775be5f0764bfd7edf
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 23 15:33:01 2022 +0200

    Remove usage of obsolete stuff.

commit 1f3c35685c7a65453c37a37e8c54a2ca4305ff6d
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 23 15:30:54 2022 +0200

    Update ValidatingConnectionEventArgs.cs

commit a5e1b8938974b5b57e95ec41d74634ca130a8ad5
Merge: 8878efee 11249d00
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 23 15:30:30 2022 +0200

    Merge branch 'master' into 1125-expose-http-context-in-validateconnectionasync

commit 8878efee0da3c67d90bb7fb6946453f62329cd8e
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 23 15:30:03 2022 +0200

    Expose channel adapter when validating connections.
2022-07-23 15:33:53 +02:00
Christian 11249d006f Add samples. 2022-07-23 15:10:20 +02:00
Christian 0d7b020994 Squashed commit of the following: 487-any-way-to-generate-events-on-receipt-of-puback-or-pubrec-packets
commit 3f2f8d4b0a31b20734eca3fff86c43bd1ac3e3ad
Merge: 34babbf2 d71ff3d6
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 23 11:06:22 2022 +0200

    Merge branch 'master' into 487-any-way-to-generate-events-on-receipt-of-puback-or-pubrec-packets

commit 34babbf2714b742bc4f3802804a1a07159d38e22
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Mon Jul 11 22:56:01 2022 +0200

    Fix typo.

commit add6277458f528fc03bf4a1ba228a55c5a8d1a80
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jul 2 12:50:13 2022 +0200

    Add new event for client acknowledges.
2022-07-23 11:08:53 +02:00
Christian d71ff3d615 Update ReleaseNotes.md 2022-07-23 11:05:14 +02:00
Christian 57745e8324 Merge branch 'master' into 1311-how-does-mqttclient-specify-the-network-card-to-send-data 2022-07-23 11:03:06 +02:00
Christian a94776eeea Update version information. 2022-07-23 11:02:00 +02:00
Christian d3848d8cb0 Add comments. 2022-07-23 11:00:21 +02:00
Alexander Köpke 6c29ea56fc Add PackageIdentifier to MqttApplicationMessageReceivedEventArgs (#1466)
Provide `PackageIdentifier` as read only property in `MqttApplicationMessageReceivedEventArgs`
2022-07-23 10:37:57 +02:00
Christian ed7c150cc5 Add new options. 2022-07-19 20:47:16 +02:00
Christian 13762eedd4 Update Server_Asp_Net_Samples.cs 2022-07-19 17:33:01 +02:00
Christian e33495010e Update samples. 2022-07-13 15:29:26 +02:00
Christian b0d1fcd161 Refactor code. 2022-07-12 16:37:32 +02:00
Christian f7a739e162 Fix check for skipped application messages. 2022-07-12 12:02:00 +02:00
Christian 422945929e Merge branch 'Fix-high-CPU-usage' 2022-07-12 11:57:03 +02:00
Christian 76e54dc49b Update ReleaseNotes.md 2022-07-12 11:56:50 +02:00
Christian b10a69a0ae Update release notes. 2022-07-01 17:03:33 +02:00
Torstein Lundervold Nesheim 4b1c7cf772 Use IgnoreCertificateChainErrors option in TcpChannel (#1447) 2022-07-01 17:00:13 +02:00
Christian 3f67df007b Remove obsolete files etc. 2022-07-01 16:55:13 +02:00
Christian 36b1ed06f0 Update MqttClient.cs 2022-07-01 16:54:53 +02:00
Christian 4a982ea228 Add Tests. 2022-06-29 18:58:02 +02:00
Christian 9fe5073186 Use TopicFilter instead of QoS only. 2022-06-29 18:17:48 +02:00
Christian 305c552474 Squashed commit of the following:
commit 0cbf50427ca6fb343cfa22ccbcd06aad5ea2b4c2
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Mon Jun 20 21:02:50 2022 +0200

    Fix firing of _ClientSubscribedTopicAsync_ event.
2022-06-27 20:41:34 +02:00
Christian f632fbb447 Squashed commit of the following:
commit c3ca0ef7da4bcc2103cda2bb175ea3c5a49da2e6
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sat Jun 25 22:58:18 2022 +0200

    Update nugets and fix breaking changes.
2022-06-27 20:40:37 +02:00
Christian 8231d62f9f Squashed commit of the following:
commit 9f289152736a682a8c31fbe7720dade37dbb1cb5
Author: Christian <6939810+chkr1011@users.noreply.github.com>
Date:   Sun Jun 26 13:38:35 2022 +0200

    Fix message storage.
2022-06-27 20:39:53 +02:00
Christian a52a717965 Update ReleaseNotes.md 2022-06-26 13:40:21 +02:00
Christian 2b653f2379 Update ReleaseNotes.md 2022-06-25 23:00:16 +02:00
Christian 725cfb643f Set MaximumQoS properly. 2022-06-24 18:52:50 +02:00
Christian 29ec6edbf4 Update Server_Simple_Samples.cs 2022-06-24 18:46:38 +02:00
Christian f3ef2dbf7c Add samples. 2022-06-18 11:56:19 +02:00
Christian 14eb202873 Add new samples. 2022-06-18 11:38:36 +02:00
Christian a3c7f9a22c Fix handling of retained messages with QoS > 0. 2022-06-15 21:56:13 +02:00
Christian 41e0a25fc8 Fix wrong event args types. 2022-06-14 21:10:53 +02:00
Christian 772cd3cd12 Update release notes. 2022-06-10 23:29:52 +02:00
Christian 42cf9f73c2 Merge branch 'master' into 1413-protocol-version-132-mqtt-311-bridge-support 2022-06-10 23:27:00 +02:00
Christian ec2e08668f Add support for MQTT 3.1.1 Bridge flag. 2022-06-10 23:07:00 +02:00
Christian e9e8583d1a Merge branch 'master' of https://github.com/dotnet/MQTTnet 2022-06-10 17:10:14 +02:00
Christian f68b109471 Switch to license expression. (#1408) 2022-06-10 17:09:17 +02:00
Christian dd1e155ff4 Add missing "WithWill..." methods. 2022-06-09 21:52:05 +02:00
Christian cf6369d63f Update version. 2022-06-09 21:27:14 +02:00
Christian 3049fc6608 Update ReleaseNotes.md 2022-06-09 21:27:08 +02:00
Christian b75076a1c5 Skip adding default message expiry interval. 2022-06-09 21:23:34 +02:00
Christian ae8e2ec7c9 Merge branch 'master' of https://github.com/dotnet/MQTTnet 2022-06-09 20:13:19 +02:00
Christian e7e6a080e0 Update copyright information. 2022-06-09 20:13:17 +02:00
SeppPenner dc9afa6c3a Samples, Github template: Fixed small typos. 2022-06-08 09:19:14 +02:00
HansM 02b17f277d Merge pull request #1421 from soyoo/patch-1
Update RcpClient_Samples.cs
2022-06-08 08:58:22 +02:00
soyoo b9d9ea2d4d Update RcpClient_Samples.cs
typo
2022-06-07 21:54:08 +08:00
Christian c9cc6c9c0f Update ReleaseNotes.md 2022-05-08 13:45:00 +02:00
Andres OlivaresandAndres Olivares 967c964111 Added MqttClientTlsOptions to control RevocationMode for clients with limited Internet access (defaults to Online) (#1396)
Co-authored-by: Andres Olivares <andres.olivares@ncr.com>
2022-05-08 14:31:14 +02:00
johannesmeyer 80aaca63f9 Update README.md (#1402) 2022-04-30 10:55:14 +02:00
Christian eeeb479db2 Update ReleaseNotes.md 2022-04-21 21:06:01 +02:00
Tim 9e47a0985b Allow to change cipher suite (#1381)
* Allow to change the used Cipher Suite

* Also added cipher suite to the mqtt client part

* Added ConfigureAwait
2022-04-21 21:02:39 +02:00
Christian 2d9ae0576b Fix wrong value for graceful socket close handling. 2022-04-21 20:49:09 +02:00
Christian fcf276dd1a Improve Server packet management. 2022-04-21 20:48:52 +02:00
Christian 920728e77a Migrate handlers to events in ManagedClient. 2022-04-21 20:47:53 +02:00
Christian 1d4794b071 Configure build warnings. 2022-04-21 20:47:24 +02:00
Christian 626baa7bb5 Update nuget settings
Documentation is now also part of the nuget packages.
2022-04-09 10:53:27 +02:00
Gui.H 810746b56b Update MQTTnet.csproj (#1385) 2022-04-09 10:49:03 +02:00
Christian 7cf454952f Restore interfaces. 2022-04-05 20:00:49 +02:00
Christian cf2974cd34 Update Subscribe_Tests.cs 2022-03-20 15:25:38 +01:00
Christian 7d95c238c3 Code cleanup. 2022-03-06 12:47:48 +01:00
Christian 9a94b0465d Add Unit Tests. 2022-03-06 11:32:05 +01:00
Christian 1d8b6e387d Update README.md 2022-02-23 18:59:57 +01:00
Christian 73d681bc1f Update README.md 2022-02-20 21:32:01 +01:00
Christian 2ce9b94ec9 v4.0.0 (#1357) 2022-02-20 21:10:46 +01:00
HansM 47e674e4d3 Adjusted default value for the supported Net frameworks versions where "None" is incompatible. (#1348) 2022-02-17 20:00:57 +01:00
Christian d5691346a9 Update MQTTnet.nuspec 2022-01-27 20:22:51 +01:00
HansM 0730f21d29 Merge pull request #1338 from alvin1221/public_broker_test
Thank you, this is indeed a bug.
2022-01-12 17:57:33 +01:00
alvin1221 6dfa7f0769 Fix incorrect TLS port of broker.emqx.io 2022-01-12 11:29:15 +08:00
Christian 27592f1643 Update MQTTnet.nuspec 2022-01-08 15:36:35 +01:00
Christian c6f4b59438 Increase delay for Keep Alive checks to decrease CPU load. 2022-01-08 15:35:47 +01:00
Christian b362b2afc2 Make logger parameters generic. 2022-01-08 14:35:25 +01:00
Christian 7a72a8d562 Update MQTTnet.nuspec 2022-01-08 14:07:57 +01:00
Günther Foidl bd40e10a66 Elide repeated Action-delegate allocation by caching it (#1324)
* Elide repeated Action-delegate allocation by caching it

Here C# compiler has too little knowledge about the usage of the delegate, we know better so cache it on our own to avoid the repeated allocation.

* Use conditional compilation
2022-01-08 14:00:39 +01:00
Christian 4b44a2b2b1 Remove appveyor. 2022-01-07 18:01:03 +01:00
Christian 215f24a95b Create CODE-OF-CONDUCT.md 2022-01-07 17:52:16 +01:00
Christian 72f9acdc20 Update CI 2022-01-06 20:55:20 +01:00
Christian 1e5390679f Update ci.yml 2022-01-06 20:41:18 +01:00
Christian 5cafce4345 Update ci.yml 2022-01-06 20:40:06 +01:00
Christian dfaf3dc31f Update ci.yml 2022-01-06 20:37:24 +01:00
Christian 3a9397c793 Update CI. 2022-01-06 20:36:12 +01:00
Christian 1cf4a7d6be Update ci.yml 2022-01-06 20:26:11 +01:00
Christian 180588c3a4 Update ci.yml 2022-01-06 20:18:04 +01:00
Christian bc4c86bebd Update ci.yml 2022-01-06 20:13:11 +01:00
Christian ea88a8c0de Update CI. 2022-01-06 20:10:42 +01:00
Günther Foidl d98129481a Fixed latent bug in MqttApplicationMessageBuilder.WithPayload stream overload (#1322) 2022-01-04 19:25:26 +01:00
Christian 5e5818d7df Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2021-11-28 14:45:27 +01:00
Christian 72c7a8959c Update MQTTnet.nuspec 2021-11-28 12:57:22 +01:00
patagona 39e637795e improve exception message when handling connection errors (#1302) 2021-11-28 12:56:32 +01:00
logicaloud 731c89d2e9 Fix MQTT5 'IsPersisted' session flag handling (#1300) 2021-11-28 12:51:29 +01:00
Michi 25ddfc83a8 MqttRpcClient now adds ResponseTopic to MqttApplicationMessage when using MQTT v5 (#1295)
* MqttRpcClient now adds ResponseTopic to MqttApplicationMessage when using MQTT v5

* No need for conditional protocol check (ResponseTopic property won't be added by PacketFormatter in <MQTT v5)

* Cleanup: Remove using
2021-11-28 12:41:56 +01:00
Christian 2d94abdde3 Update MQTTnet.nuspec
Update docs.
2021-11-13 10:09:59 +01:00
logicaloud f0ea13c07f Fix MQTT 3.1.1 session persistence when CleanSession=1 (#1294) 2021-11-13 10:05:54 +01:00
Volker Milbrandt 47cd5aa3cd test ResultCode for invalid credentials (no userName but password) (#1270)
fix order of parameters in exceptions AreEqual(expected, actual)
2021-11-13 10:02:55 +01:00
HansM 258df6bb14 Removed IDisposable from MqttClientConnection class. (#1288) 2021-11-11 20:10:35 +01:00
SeppPenner 85c3c0b352 MQTTnet.noUWP.sln: Removed no longer present MQTTnet.Server project. 2021-11-08 08:50:59 +01:00
Christian 8020e66f41 Fix UWP build errors. 2021-11-01 12:28:39 +01:00
Christian bd004ec327 Update docs. 2021-10-30 10:21:50 +02:00
logicaloud 1e68c2e815 Fixes #1276 timestamp check in server keep-alive monitor (#1277)
* Fix timestamp check in server keep-alive monitor

* Retain the original client statistics property name
- add comments to clarify meaning
- add separate public "received" timestamp property

* fix comment
2021-10-30 10:12:57 +02:00
Christian d7e1c89d62 Update docs. 2021-10-27 22:20:55 +02:00
patagona b779d04636 let the OS choose the supported TLS ptotocols when connecting to a MQTT broker (#1271) 2021-10-23 10:31:44 +02:00
logicaloud 623d8cafaa Fix #1263 - Set IsSessionPresent in CONNACK if client session exists (#1268)
* Set IsSessionPresent in CONNACK if client session exists

* Set IsSessionPresent in CONNACK if client session exists;
- restore white space differences to make comparison easier
2021-10-23 10:28:08 +02:00
Christian 0920c86d37 Refactor logger. (#1247) 2021-09-26 11:05:00 +02:00
Christian c756a4092f Feature/mqttv5 subscriptions server (#1246)
* Add support for RetainHandling.

* Add support for No Local.

* Add support for _SubscriptionIdentifier_.

* Add more Unit Tests.

* Update docs.
2021-09-23 20:30:43 +02:00
Christian feb53e78c6 Update docs. 2021-09-19 13:02:15 +02:00
Ablfzl Edgelolliandablfzl dd0aba0640 Process all queued message before server stops (#1234)
* process all queued message befor server stops

* fix an issue

Co-authored-by: ablfzl <ablfzl21@outlook.com>
2021-09-19 13:01:47 +02:00
Christian 68f1043ef5 Refactor sub/unsub management in managed client. 2021-09-19 12:59:32 +02:00
scottbrogden-iheartmedia d01d859227 Added option for how many subscriptions to send in a single call to t… (#1209)
* Added option for how many subscriptions to send in a single call to the server.  aws iotcore limits this to 8

* Split subscription messages up to 8 at a time when reconnecting
2021-09-19 12:41:33 +02:00
Marc Sallin fcab0d5cf0 Add Silverback to references in readme (#1238) 2021-09-19 12:35:19 +02:00
HansM b66a18f8dd Merge pull request #1241 from soyoo/master
Update README.md
2021-09-15 19:33:13 +02:00
zhengshuyuan 8e1e93c00f Update README.md
fix typo
2021-09-15 21:10:49 +08:00
Christian cd8940f9b7 Improve internal server connection management. (#1232) 2021-09-08 18:01:56 +02:00
Jacky Jiang 9d9077f17c Update MqttApplicationMessageBuilder.cs (#1230)
update function WithMessageExpiryInterval description
2021-09-08 15:45:18 +02:00
Christian fa6859d68a Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2021-09-05 13:32:50 +02:00
Christian 4f14373117 Add Unit Tests. 2021-09-05 13:32:46 +02:00
Christian 90ec39f2a4 Refactor code. 2021-09-05 13:31:36 +02:00
Christian 2aa4d1b77a Add low level client to test environment. 2021-09-05 13:31:23 +02:00
Christian aa9f8d8ef3 Update release notes. 2021-09-05 13:30:39 +02:00
Nikita Senkov 50381637af Updated _ReconnectAsync_ extension methods to retrieve authentication result (#1202) 2021-09-05 11:49:52 +02:00
Harry Kakoulidis 8905b612c9 Updated tests with public servers. (#1223)
* Updated tests with public servers.

* Separated tests with TLS12 and TLS13.
2021-09-05 11:45:30 +02:00
HansM 3cdf6d1261 [MQTTnet, MQTTnet.Extensions.ManagedClient] Fixed bug that allowed invalid subscriptions (Thanks to @marcelwinh). (#1226) 2021-09-05 11:42:42 +02:00
Christian d1c883ebae Move MQTTnet.Server to dedicated repo. 2021-06-29 20:18:20 +02:00
Christian ed5e6ee897 Update project files. 2021-06-28 20:39:10 +02:00
Christian 2e019f372c Update docs. 2021-06-27 17:02:04 +02:00
Christian cc9bc2d3a0 Merge remote-tracking branch 'origin/master' 2021-06-27 16:53:54 +02:00
Christian 306bce5a58 Refactor code. 2021-06-27 16:53:44 +02:00
Ramon Smits 6fe7ce7a0c FIxed MqttNetLogLevel.Verbose incorrectly mapped to LogLevel.Debug (#1170)
Based on https://github.com/chkr1011/MQTTnet/issues/1138#issuecomment-846649937
2021-05-30 22:01:38 +02:00
Christian 8f1d4e3c22 Remove client disconnected handler from wrong implementation location. 2021-04-11 20:34:35 +02:00
Christian 77338527b4 Refactor code. 2021-04-05 12:50:42 +02:00
Christian 962622a9f7 Merge pull request #1134 from yyjdelete/issue996
Disallow to call MqttClient.ConnectAsync while Disconnect is pending.
2021-04-05 11:19:20 +02:00
SilverFox 899ed7b1da Rename MqttClient.ConnectState to MqttClientConnectionStatus 2021-04-03 13:19:50 +08:00
Christian 10f7d809f2 Merge pull request #1132 from qzwzqty/master
Passes the Endpoint of the client before it disconnected
2021-04-02 16:18:15 +02:00
Christian 324fb7e48c Merge pull request #1136 from yyjdelete/framework
Fix UWP support broken in #1135
2021-04-02 16:17:13 +02:00
SilverFox d913d4402e Convert MqttClient._connectState to enum 2021-04-02 21:01:49 +08:00
SilverFox df262b5588 Fix UWP support broken in #1135 2021-04-02 19:58:03 +08:00
Christian 27daf37ba4 Update MQTTnet.nuspec 2021-04-02 12:49:31 +02:00
Christian e5e10eee6d Merge pull request #1135 from yyjdelete/framework
Add more checks for NET5_0
2021-04-02 12:48:43 +02:00
SilverFox e174546b5a Add more checks for NET5_0 2021-04-02 18:03:44 +08:00
SilverFox f99daee4d1 Fix Session_Tests.Manage_Session_MaxParallel 2021-04-02 17:54:41 +08:00
SilverFox 9b10eadb24 Fix broken tests 2021-04-02 17:54:41 +08:00
SilverFox c39da42ef2 Disallow to call MqttClient.ConnectAsync while Disconnect is pending.
Fix #996
Fix #1010
2021-04-01 22:00:01 +08:00
Wang Chunlong 85b339e6f0 rename 2021-03-31 11:56:58 +08:00
Christian fbb5cd45a0 Refactor deferred ACK of publish packets. 2021-03-30 21:06:44 +02:00
Christian d430ca0250 Merge pull request #1075 from tkurucsai/feature/pending-appmsg-acknowledge
Feature/pending appmsg acknowledge
2021-03-30 14:34:43 +02:00
Wang Chunlong cf8ea872d3 Disconnected Endpoint 2021-03-29 16:00:37 +08:00
Christian d4440f3be1 Merge remote-tracking branch 'origin/master' 2021-03-21 20:42:25 +01:00
Christian b97d01b78b Fix wrong data validation (#342). 2021-03-21 20:42:09 +01:00
Christian 375ee5c4ac Merge pull request #1121 from asymetrixs/master
Added workflow to  build debian/ubuntu packages
2021-03-21 20:29:02 +01:00
tamas.kurucsai 90b37a1e2d reimplemented delayed acknowledgement using a property to switch off automatic acknowledgement and a new method Acknowledge() in the event handler 2021-03-20 10:36:44 +01:00
Damian 0978f6cc75 Merge pull request #7 from asymetrixs/deb-packaging
Deb packaging
2021-03-12 18:04:25 +01:00
Damian Wolgast e7c51e8dbc Extraction of Version from project file. 2021-03-12 18:03:32 +01:00
Damian Wolgast aab4448980 Debugging 2021-03-12 18:01:31 +01:00
Damian Wolgast 52139c6a99 Debugging 2021-03-12 17:56:34 +01:00
Damian Wolgast f3d121120b Debugging 2021-03-12 17:51:18 +01:00
Damian Wolgast 413c68de44 Debugging 2021-03-12 17:47:53 +01:00
Damian Wolgast f0919487f2 Debugging 2021-03-12 17:44:26 +01:00
Damian ffa7c51899 Merge pull request #6 from asymetrixs/deb-packaging
Deb packaging
2021-03-12 17:38:07 +01:00
Damian Wolgast 493cad087f Fixed syntax 2021-03-12 17:36:41 +01:00
Damian Wolgast 4d94e1a318 Debugging 2021-03-12 17:32:03 +01:00
Damian 28ff08ceb9 Merge pull request #5 from asymetrixs/deb-packaging
Read version from MQTTnet.Server project file
2021-03-12 17:28:03 +01:00
Damian Wolgast 0f3d461c37 Read version from MQTTnet.Server project file 2021-03-12 17:27:18 +01:00
Damian 4285169108 Merge pull request #4 from asymetrixs/deb-packaging
Added dependency to libssl
2021-03-12 15:44:58 +01:00
Damian Wolgast 1b1f2db1e6 Added dependency to libssl 2021-03-12 15:44:22 +01:00
Damian d7248c0f64 Merge pull request #3 from asymetrixs/deb-packaging
Added check for availability of setcap
2021-03-12 15:20:08 +01:00
Damian Wolgast d2e1b12186 Added check for availability of setcap 2021-03-12 15:18:13 +01:00
Damian dafcfb47d2 Merge pull request #2 from asymetrixs/deb-packaging
Docker support
2021-03-12 14:41:38 +01:00
Damian Wolgast 897f0f36d1 Fixed spelling 2021-03-12 14:40:21 +01:00
Damian Wolgast 9cb12ac2ce Docker, check if systemctl exists before using it 2021-03-12 14:39:51 +01:00
Damian 312fb2bb3c Merge pull request #1 from asymetrixs/deb-packaging
Fixed user creation to not copy skel-files
2021-03-12 14:19:24 +01:00
Damian Wolgast 3ee785c781 Fixed user creation to not copy skel-files 2021-03-12 14:17:38 +01:00
Damian Wolgast 0ea4ae7501 Fix, forgot to rename file. 2021-03-12 12:40:02 +01:00
Damian Wolgast 7e764c7f0f Added revision (assuming 1) and architecture 2021-03-12 12:36:14 +01:00
Damian Wolgast 5c2879029b Added command to stop service before uninstalling 2021-03-12 12:26:04 +01:00
Damian Wolgast 6cbb8d42e3 Added prerm to revoke service permissions 2021-03-12 12:15:49 +01:00
Damian Wolgast d8d50f6dcb Added workflow to build debian/ubuntu packages 2021-03-11 18:19:25 +01:00
Christian a01dc9fef8 Add new overload for server options builder. 2021-03-05 13:01:14 +01:00
tamas.kurucsai 3427d82efc Merge branch 'master' of https://github.com/chkr1011/MQTTnet into feature/pending-appmsg-acknowledge
# Conflicts:
#	Source/MQTTnet/Client/MqttClient.cs
2021-03-05 12:10:01 +01:00
Christian 5915285522 Fix TLS parameter options builder (#1104). 2021-03-02 10:00:34 +01:00
tamas.kurucsai 23c5270c3f Merge branch 'master' of https://github.com/chkr1011/MQTTnet into feature/pending-appmsg-acknowledge
# Conflicts:
#	Source/MQTTnet/Client/MqttClient.cs
#	Source/MQTTnet/MqttApplicationMessageReceivedEventArgs.cs
2021-02-20 12:55:28 +01:00
tamas.kurucsai fbf7d9bb5c corrected thread safety of ping timers after adding delayed acknowledgement 2021-01-29 07:03:56 +01:00
tamas.kurucsai 822f582e41 added test for delayed message acknowledgement 2021-01-29 07:03:19 +01:00
tamas.kurucsai fcbe2e32f6 corrected name of response sender method 2021-01-18 17:58:49 +01:00
tamas.kurucsai f955b4a3e6 implemented delayed message acknowledgement 2021-01-18 10:47:21 +01:00
745 changed files with 34445 additions and 25573 deletions
-3
View File
@@ -1,3 +0,0 @@
component_depth: 2
languages:
- csharp
+1 -63
View File
@@ -1,63 +1 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
* text=auto
+16 -5
View File
@@ -7,16 +7,25 @@ assignees: ''
---
### Verification
Before opening a bug make sure that the following conditions are met.
<!-- Remove this chapter when all conditions are met. -->
1. Performance issues are also appearing in RELEASE mode of your application.
2. An increased memory consumption or high CPU load also happens when your application runs in RELEASE mode AND logging is DISABLED.
3. Client issues with not received messages, connection drops etc. can be reproduced via another client application like "MQTTnetApp" (https://github.com/chkr1011/MQTTnetApp) or similar.
4. The bug also appears in the VERY LATEST version of this library. There is no support for older version (due to limited resources) but pull requests for older versions are welcome.
### 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 -->
### Which component is your bug related to?
<!-- Remove the items which don't apply from the following list. -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- RpcClient
- Server
- Generic
### To Reproduce
Steps to reproduce the behavior:
@@ -39,7 +48,9 @@ Include debugging or logging information here:
\\ 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.
Please provide full code examples below where possible to make it easier for the developers to check your issues.
**Ideally a Unit Test (which shows the error) is provided so that the behavior can be reproduced easily.**
```csharp
\\ Put your code here.
-1
View File
@@ -14,6 +14,5 @@ A clear and concise description of what you want to know.
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic
@@ -15,7 +15,6 @@ A clear and concise description of what the problem is. Example. I'm am trying t
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic
+8
View File
@@ -0,0 +1,8 @@
* [Core] Added net7.0 builds (#1635, thanks to @YAJeff).
* [Client] Added support for passing MQTT v5 options (User properties etc.) for disconnects.
* [Client] An internal exception is no longer caught silently when calling _DisconnectAsync_ to indicate that the disconnect is not clean (BREAKING CHANGE).
* [Client] MQTTv5 features are now checked and an exception is thrown if they are used when using protocol version 3.1.1 and lower. These checks can be disabled in client options. (BREAKING CHANGE!).
* [Server] Exposed MQTT v5 sent properties from the affected client in _ClientDisconnectedAsync_ event.
* [Server] Fixed wrong client ID passed to _InterceptingUnsubscriptionEventArgs_ (#1631, thanks to @ghord).
* [Server] Exposed socket settings for TCP keep alive in TCP options (#1544).
* [Server] Exposed server session items at server level and allow custom session items for injected application messages (#1638).
+64
View File
@@ -0,0 +1,64 @@
name: CI
on: [push, pull_request]
env:
VERSION: "4.2.0.${{github.run_number}}"
jobs:
build:
runs-on: windows-2022
steps:
- name: Setup Windows SDK
uses: GuillaumeFalourd/setup-windows10-sdk-action@v1
with:
sdk-version: 18362
- name: Setup .NET SDK
uses: actions/setup-dotnet@v1.9.0
with:
dotnet-version: |
3.1.x
6.0.x
7.0.x
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.1
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Signing Certificate
run: |
$secret = '${{ secrets.SNC_BASE64 }}'
$decoded = [System.Convert]::FromBase64CharArray($secret, 0, $secret.Length)
Set-Content -Path ${{ github.workspace }}\certificate.snk -Value $decoded -AsByteStream
- name: Restore nuget packages
run: msbuild MQTTnet.sln /t:Restore /p:Configuration="Release" /verbosity:m
- name: Build solution
run: msbuild MQTTnet.sln /t:Build /p:Configuration="Release" /verbosity:m /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.VERSION }} /p:PackageVersion=${{ env.VERSION }} /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=${{ github.workspace }}\certificate.snk
- name: Collect nuget Packages
uses: actions/upload-artifact@v2
with:
name: nuget Packages
path: |
**\*.nupkg
**\*.snupkg
- name: Setup VSTest
uses: darenm/Setup-VSTest@v1
- name: Core Tests
run: vstest.console.exe Source\MQTTnet.Tests\bin\Release\net6.0\MQTTnet.Tests.dll
- name: ASP.NET Tests
run: vstest.console.exe Source\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.Tests.dll
- name: Publish MyGet nugets
if: ${{ github.event_name == 'push' }}
run: dotnet nuget push **/*.nupkg -k ${{ secrets.MYGET_API_KEY }} -s https://www.myget.org/F/mqttnet/api/v3/index.json --skip-duplicate
-67
View File
@@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '23 9 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'csharp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+2
View File
@@ -294,3 +294,5 @@ __pycache__/
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
Build/NuGet/
Build/nuget.exe
-49
View File
@@ -1,49 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.AspNetCore</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 a support library to integrate MQTTnet into AspNetCore.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-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="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>
<group targetFramework="net5.0">
<dependency id="MQTTnet" version="$nugetVersion" />
</group>
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\net5.0\MQTTnet.AspNetCore.*" target="lib\net5.0\" />
<!-- .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>
@@ -1,52 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.Extensions.ManagedClient</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 provides a managed MQTT client with additional features using MQTTnet.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net5.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.0\" />
<!-- .NET Standard 2.1 -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.1\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.1\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\uap10.0\MQTTnet.Extensions.ManagedClient.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net452\MQTTnet.Extensions.ManagedClient.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net461\MQTTnet.Extensions.ManagedClient.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
-52
View File
@@ -1,52 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.Extensions.Rpc</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 executing synchronous device calls including a response using MQTTnet.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net5.0\MQTTnet.Extensions.Rpc.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.0\" />
<!-- .NET Standard 2.1 -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.1\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.1\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\uap10.0\MQTTnet.Extensions.Rpc.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net452\MQTTnet.Extensions.Rpc.*" target="lib\net452\" />
<!-- .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>
@@ -1,53 +0,0 @@
<?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>
<dependency id="MQTTnet" version="$nugetVersion" />
<dependency id="WebSocket4Net" version="0.15.2" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- Images -->
<file src="..\Images\Logo_128x128.png" target="images\" />
<!-- .NET 5.0 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net5.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\" />
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\" />
<!-- .NET Standard 2.1 -->
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.1\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.1\" />
<!-- 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>
-79
View File
@@ -1,79 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet</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>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
<releaseNotes>
* [Core] Fixed some issues in nuget packages.
* [Client] Changed exception types so that proper exceptions are thrown when connecting (#1082).
* [Client] Exposed Dup flag in application messages.
* [Client] Improved keep alive message sending.
* [RpcClient] Fixed an issue when using a custom application message reveived handler (#1093).
* [RpcClient] Fixed a race condition when using timeout and cancellation token at the same time (BREAKING CHANGE!).
* [Server] Improved keep alive message sending.
Git commit: $gitCommit
</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="net452" />
<group targetFramework="net461" />
<group targetFramework="netstandard1.3">
<dependency id="NETStandard.Library" version="1.6.1" />
<dependency id="System.Net.Security" version="4.3.2" />
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="netstandard2.0" />
<group targetFramework="netstandard2.1" />
<group targetFramework="netcoreapp3.1" />
<group targetFramework="net5.0" />
<group targetFramework="uap10.0">
<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 5.0 -->
<file src="..\Source\MQTTnet\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\" />
<!-- .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\" />
<!-- .NET Standard 3.1 -->
<file src="..\Source\MQTTnet\bin\Release\netcoreapp3.1\MQTTnet.*" target="lib\netcoreapp3.1\" />
<!-- Universal Windows -->
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\" />
<!-- .NET Framework -->
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\" />
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
<file src="..\Source\MQTTnet\bin\Release\net461\MQTTnet.*" target="lib\net461\" />
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
</files>
</package>
-144
View File
@@ -1,144 +0,0 @@
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
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
.\nuget.exe restore ..\MQTTnet.sln
# Build and execute tests
&$msbuild ..\Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
&$msbuild ..\Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
vstest.console.exe ..\Tests\MQTTnet.Core.Tests\bin\Release\netcoreapp3.1\MQTTnet.Tests.dll
vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.Tests.dll
# Build the core library
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# Build the ASP.NET Core 2.0 extension
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# Build the RPC extension
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.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"
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.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"
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.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
$gitCommit = git log -1 --format=%h
Copy-Item MQTTnet.nuspec -Destination MQTTnet.nuspec.old -Force
(Get-Content MQTTnet.nuspec) -replace '\$gitCommit', $gitCommit | Set-Content MQTTnet.nuspec
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
(Get-Content MQTTnet.AspNetCore.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.AspNetCore.nuspec
Copy-Item MQTTnet.Extensions.Rpc.nuspec -Destination MQTTnet.Extensions.Rpc.nuspec.old -Force
(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.nuspec.old -Destination MQTTnet.nuspec -Force
Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force
Move-Item MQTTnet.Extensions.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force
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 --framework net5.0
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\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 --framework net5.0
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\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 --framework net5.0
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\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 --framework net5.0
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\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)
####################################################################
Binary file not shown.
-13
View File
@@ -1,13 +0,0 @@
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 -Source https://api.nuget.org/v3/index.json
}
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
+6
View File
@@ -0,0 +1,6 @@
# Code of Conduct
This project has adopted the code of conduct defined by the Contributor Covenant
to clarify expected behavior in our community.
For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
-9
View File
@@ -1,9 +0,0 @@
# 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_62CA73019ED23333
The container name may be different.
# Check if the assembly has a strong name
sn -vf MQTTnet.dll
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

+3 -2
View File
@@ -1,6 +1,7 @@
MIT License
The MIT License (MIT)
Copyright (c) 2016-2019 Christian Kratky
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
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
@@ -1,260 +0,0 @@
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
+34 -264
View File
@@ -1,322 +1,92 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
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
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.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.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
.editorconfig = .editorconfig
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
CODE-OF-CONDUCT.md = CODE-OF-CONDUCT.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.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}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Samples", "Samples\MQTTnet.Samples.csproj", "{71CF35F5-3327-4A91-AAF4-5340F6701771}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Tests", "Source\MQTTnet.Tests\MQTTnet.Tests.csproj", "{B270F32A-9F3E-42EE-A989-813E35E29ADB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Server", "Tests\MQTTnet.Test.BlazorApp\Server\MQTTnet.Test.BlazorApp.Server.csproj", "{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.AspNetCore.Tests", "Source\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj", "{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Client", "Tests\MQTTnet.Test.BlazorApp\Client\MQTTnet.Test.BlazorApp.Client.csproj", "{D260D63D-7902-4C55-9665-84C5CACBBB24}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Benchmarks", "Source\MQTTnet.Benchmarks\MQTTnet.Benchmarks.csproj", "{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Shared", "Tests\MQTTnet.Test.BlazorApp\Shared\MQTTnet.Test.BlazorApp.Shared.csproj", "{DDB069BA-6E1A-48C7-B374-5D903B553CAD}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp", "Source\MQTTnet.TestApp\MQTTnet.TestApp.csproj", "{175D5340-CC5B-4542-939D-4E7D15A0BC8D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.AspTestApp", "Source\MQTTnet.AspTestApp\MQTTnet.AspTestApp.csproj", "{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x64.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.ActiveCfg = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|x86.Build.0 = Debug|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|ARM.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x64.Build.0 = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.ActiveCfg = Release|Any CPU
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|x86.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|ARM.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x64.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.ActiveCfg = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Debug|x86.Build.0 = Debug|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|Any CPU.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|ARM.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x64.Build.0 = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.ActiveCfg = Release|Any CPU
{3D283AAD-AAA8-4339-8394-52F80B6304DB}.Release|x86.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|ARM.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x64.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.ActiveCfg = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Debug|x86.Build.0 = Debug|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|Any CPU.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|ARM.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x64.Build.0 = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.ActiveCfg = Release|Any CPU
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9}.Release|x86.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|ARM.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x64.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.ActiveCfg = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|x86.Build.0 = Debug|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|ARM.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x64.Build.0 = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.ActiveCfg = Release|Any CPU
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|x86.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|ARM.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x64.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|x86.Build.0 = Debug|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|ARM.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|ARM.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x64.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.ActiveCfg = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|x86.Build.0 = Debug|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|ARM.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x64.Build.0 = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.ActiveCfg = Release|Any CPU
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|x86.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|ARM.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x64.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.ActiveCfg = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Debug|x86.Build.0 = Debug|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|Any CPU.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|ARM.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x64.Build.0 = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.ActiveCfg = Release|Any CPU
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E}.Release|x86.Build.0 = Release|Any CPU
{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
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Release|Any CPU.Build.0 = Release|Any CPU
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Release|Any CPU.Build.0 = Release|Any CPU
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Release|Any CPU.Build.0 = Release|Any CPU
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Release|Any CPU.Build.0 = Release|Any CPU
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Release|Any CPU.Build.0 = Release|Any CPU
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{F10C4060-F7EE-4A83-919F-FF723E72F94A} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{C444E9C8-95FA-430E-9126-274129DE16CD} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{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}
+306 -1
View File
@@ -1,16 +1,321 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=MQTTnet/@EntryIndexedValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;Profile name="MQTTnet"&gt;&lt;CppReformatCode&gt;True&lt;/CppReformatCode&gt;&lt;ShaderLabReformatCode&gt;True&lt;/ShaderLabReformatCode&gt;&lt;XMLReformatCode&gt;True&lt;/XMLReformatCode&gt;&lt;HtmlReformatCode&gt;True&lt;/HtmlReformatCode&gt;&lt;VBReformatCode&gt;True&lt;/VBReformatCode&gt;&lt;CSReformatCode&gt;True&lt;/CSReformatCode&gt;&lt;CSCodeStyleAttributes ArrangeVarStyle="True" ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" ArrangeArgumentsStyle="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeCodeBodyStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" ArrangeNamespaces="True" /&gt;&lt;CSArrangeQualifiers&gt;True&lt;/CSArrangeQualifiers&gt;&lt;CSFixBuiltinTypeReferences&gt;True&lt;/CSFixBuiltinTypeReferences&gt;&lt;CppCodeStyleCleanupDescriptor ArrangeBraces="True" ArrangeAuto="True" ArrangeFunctionDeclarations="True" ArrangeNestedNamespaces="True" ArrangeTypeAliases="True" ArrangeCVQualifiers="True" ArrangeSlashesInIncludeDirectives="True" ArrangeOverridingFunctions="True" SortIncludeDirectives="True" SortMemberInitializers="True" /&gt;&lt;FormatAttributeQuoteDescriptor&gt;True&lt;/FormatAttributeQuoteDescriptor&gt;&lt;CSUpdateFileHeader&gt;True&lt;/CSUpdateFileHeader&gt;&lt;CppUpdateFileHeader&gt;True&lt;/CppUpdateFileHeader&gt;&lt;IDEA_SETTINGS&gt;&amp;lt;profile version="1.0"&amp;gt;&#xD;
&amp;lt;option name="myName" value="MQTTnet" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="ConditionalExpressionWithIdenticalBranchesJS" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="ES6ShorthandObjectProperty" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="JSArrowFunctionBracesCanBeRemoved" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="JSRemoveUnnecessaryParentheses" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="TypeScriptExplicitMemberType" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="UnterminatedStatementJS" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;inspection_tool class="WrongPropertyKeyValueDelimiter" enabled="true" level="WARNING" enabled_by_default="true" /&amp;gt;&#xD;
&amp;lt;/profile&amp;gt;&lt;/IDEA_SETTINGS&gt;&lt;RIDER_SETTINGS&gt;&amp;lt;profile&amp;gt;&#xD;
&amp;lt;Language id="CSS"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;Rearrange&amp;gt;true&amp;lt;/Rearrange&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="EditorConfig"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="HTML"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;Rearrange&amp;gt;true&amp;lt;/Rearrange&amp;gt;&#xD;
&amp;lt;OptimizeImports&amp;gt;true&amp;lt;/OptimizeImports&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="HTTP Request"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="Handlebars"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="Ini"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="JSON"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="Jade"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="JavaScript"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;Rearrange&amp;gt;true&amp;lt;/Rearrange&amp;gt;&#xD;
&amp;lt;OptimizeImports&amp;gt;true&amp;lt;/OptimizeImports&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="Markdown"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="Properties"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="RELAX-NG"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="SQL"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="XML"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;Rearrange&amp;gt;true&amp;lt;/Rearrange&amp;gt;&#xD;
&amp;lt;OptimizeImports&amp;gt;true&amp;lt;/OptimizeImports&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;Language id="yaml"&amp;gt;&#xD;
&amp;lt;Reformat&amp;gt;true&amp;lt;/Reformat&amp;gt;&#xD;
&amp;lt;/Language&amp;gt;&#xD;
&amp;lt;/profile&amp;gt;&lt;/RIDER_SETTINGS&gt;&lt;CSOptimizeUsings&gt;&lt;OptimizeUsings&gt;True&lt;/OptimizeUsings&gt;&lt;/CSOptimizeUsings&gt;&lt;CSShortenReferences&gt;True&lt;/CSShortenReferences&gt;&lt;VBOptimizeImports&gt;True&lt;/VBOptimizeImports&gt;&lt;VBShortenReferences&gt;True&lt;/VBShortenReferences&gt;&lt;Xaml.RemoveRedundantNamespaceAlias&gt;True&lt;/Xaml.RemoveRedundantNamespaceAlias&gt;&lt;AspOptimizeRegisterDirectives&gt;True&lt;/AspOptimizeRegisterDirectives&gt;&lt;CSReorderTypeMembers&gt;True&lt;/CSReorderTypeMembers&gt;&lt;RemoveCodeRedundancies&gt;True&lt;/RemoveCodeRedundancies&gt;&lt;CSUseAutoProperty&gt;True&lt;/CSUseAutoProperty&gt;&lt;CSMakeFieldReadonly&gt;True&lt;/CSMakeFieldReadonly&gt;&lt;CSMakeAutoPropertyGetOnly&gt;True&lt;/CSMakeAutoPropertyGetOnly&gt;&lt;CppAddTypenameTemplateKeywords&gt;True&lt;/CppAddTypenameTemplateKeywords&gt;&lt;CppJoinDeclarationAndAssignmentDescriptor&gt;True&lt;/CppJoinDeclarationAndAssignmentDescriptor&gt;&lt;CppMakeLocalVarConstDescriptor&gt;True&lt;/CppMakeLocalVarConstDescriptor&gt;&lt;CppMakeMethodConst&gt;True&lt;/CppMakeMethodConst&gt;&lt;CppMakeMethodStatic&gt;True&lt;/CppMakeMethodStatic&gt;&lt;CppRemoveCastDescriptor&gt;True&lt;/CppRemoveCastDescriptor&gt;&lt;CppRemoveElseKeyword&gt;True&lt;/CppRemoveElseKeyword&gt;&lt;CppRemoveElaboratedTypeSpecifierDescriptor&gt;True&lt;/CppRemoveElaboratedTypeSpecifierDescriptor&gt;&lt;CppRemoveRedundantLambdaParameterListDescriptor&gt;True&lt;/CppRemoveRedundantLambdaParameterListDescriptor&gt;&lt;CppRemoveRedundantMemberInitializerDescriptor&gt;True&lt;/CppRemoveRedundantMemberInitializerDescriptor&gt;&lt;CppRemoveRedundantParentheses&gt;True&lt;/CppRemoveRedundantParentheses&gt;&lt;CppShortenQualifiedName&gt;True&lt;/CppShortenQualifiedName&gt;&lt;CppDeleteRedundantSpecifier&gt;True&lt;/CppDeleteRedundantSpecifier&gt;&lt;CppRemoveStatement&gt;True&lt;/CppRemoveStatement&gt;&lt;CppRemoveTemplateArgumentsDescriptor&gt;True&lt;/CppRemoveTemplateArgumentsDescriptor&gt;&lt;CppDeleteRedundantTypenameTemplateKeywords&gt;True&lt;/CppDeleteRedundantTypenameTemplateKeywords&gt;&lt;CppRemoveUnreachableCode&gt;True&lt;/CppRemoveUnreachableCode&gt;&lt;CppRemoveUnusedIncludes&gt;True&lt;/CppRemoveUnusedIncludes&gt;&lt;CppRemoveUnusedLambdaCaptures&gt;True&lt;/CppRemoveUnusedLambdaCaptures&gt;&lt;CppCStyleToStaticCastDescriptor&gt;True&lt;/CppCStyleToStaticCastDescriptor&gt;&lt;CppReplaceExpressionWithBooleanConst&gt;True&lt;/CppReplaceExpressionWithBooleanConst&gt;&lt;CppMakeIfConstexpr&gt;True&lt;/CppMakeIfConstexpr&gt;&lt;CppMakePostfixOperatorPrefix&gt;True&lt;/CppMakePostfixOperatorPrefix&gt;&lt;CppChangeSmartPointerToMakeFunction&gt;True&lt;/CppChangeSmartPointerToMakeFunction&gt;&lt;CppReplaceThrowWithRethrowFix&gt;True&lt;/CppReplaceThrowWithRethrowFix&gt;&lt;CppTypeTraitAliasDescriptor&gt;True&lt;/CppTypeTraitAliasDescriptor&gt;&lt;CppReplaceExpressionWithNullptr&gt;True&lt;/CppReplaceExpressionWithNullptr&gt;&lt;CppReplaceTieWithStructuredBindingDescriptor&gt;True&lt;/CppReplaceTieWithStructuredBindingDescriptor&gt;&lt;CppUseAssociativeContainsDescriptor&gt;True&lt;/CppUseAssociativeContainsDescriptor&gt;&lt;CppUseEraseAlgorithmDescriptor&gt;True&lt;/CppUseEraseAlgorithmDescriptor&gt;&lt;RemoveCodeRedundanciesVB&gt;True&lt;/RemoveCodeRedundanciesVB&gt;&lt;Xaml.RedundantFreezeAttribute&gt;True&lt;/Xaml.RedundantFreezeAttribute&gt;&lt;Xaml.RemoveRedundantModifiersAttribute&gt;True&lt;/Xaml.RemoveRedundantModifiersAttribute&gt;&lt;Xaml.RemoveRedundantNameAttribute&gt;True&lt;/Xaml.RemoveRedundantNameAttribute&gt;&lt;Xaml.RemoveRedundantResource&gt;True&lt;/Xaml.RemoveRedundantResource&gt;&lt;Xaml.RemoveRedundantCollectionProperty&gt;True&lt;/Xaml.RemoveRedundantCollectionProperty&gt;&lt;Xaml.RemoveRedundantAttachedPropertySetter&gt;True&lt;/Xaml.RemoveRedundantAttachedPropertySetter&gt;&lt;Xaml.RemoveRedundantStyledValue&gt;True&lt;/Xaml.RemoveRedundantStyledValue&gt;&lt;Xaml.RemoveForbiddenResourceName&gt;True&lt;/Xaml.RemoveForbiddenResourceName&gt;&lt;Xaml.RemoveRedundantGridDefinitionsAttribute&gt;True&lt;/Xaml.RemoveRedundantGridDefinitionsAttribute&gt;&lt;Xaml.RemoveRedundantUpdateSourceTriggerAttribute&gt;True&lt;/Xaml.RemoveRedundantUpdateSourceTriggerAttribute&gt;&lt;Xaml.RemoveRedundantBindingModeAttribute&gt;True&lt;/Xaml.RemoveRedundantBindingModeAttribute&gt;&lt;Xaml.RemoveRedundantGridSpanAttribut&gt;True&lt;/Xaml.RemoveRedundantGridSpanAttribut&gt;&lt;CSharpFormatDocComments&gt;True&lt;/CSharpFormatDocComments&gt;&lt;VBFormatDocComments&gt;True&lt;/VBFormatDocComments&gt;&lt;/Profile&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_SWITCH_EXPRESSION_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_PROPERTY_PATTERN_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_METHOD_CALL_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_METHOD_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">180</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PROPERTY_PATTERN/@EntryValue">CHOP_ALWAYS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/KeepUserLineBreaks/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/ProcessingInstructionAttributesFormat/@EntryValue">OnDifferentLines</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/TagAttributesFormat/@EntryValue">OnDifferentLines</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"&gt;
&lt;TypePattern DisplayName="Non-reorderable types"&gt;
&lt;TypePattern.Match&gt;
&lt;Or&gt;
&lt;And&gt;
&lt;Kind Is="Interface" /&gt;
&lt;Or&gt;
&lt;HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /&gt;
&lt;HasAttribute Name="System.Runtime.InteropServices.ComImport" /&gt;
&lt;/Or&gt;
&lt;/And&gt;
&lt;Kind Is="Struct" /&gt;
&lt;HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" /&gt;
&lt;HasAttribute Name="JetBrains.Annotations.NoReorder" /&gt;
&lt;/Or&gt;
&lt;/TypePattern.Match&gt;
&lt;/TypePattern&gt;
&lt;TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All"&gt;
&lt;TypePattern.Match&gt;
&lt;And&gt;
&lt;Kind Is="Class" /&gt;
&lt;HasMember&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;HasAttribute Name="Xunit.FactAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="Xunit.TheoryAttribute" Inherited="True" /&gt;
&lt;/And&gt;
&lt;/HasMember&gt;
&lt;/And&gt;
&lt;/TypePattern.Match&gt;
&lt;Entry DisplayName="Setup/Teardown Methods"&gt;
&lt;Entry.Match&gt;
&lt;Or&gt;
&lt;Kind Is="Constructor" /&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;ImplementsInterface Name="System.IDisposable" /&gt;
&lt;/And&gt;
&lt;/Or&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Kind Order="Constructor" /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="All other members" /&gt;
&lt;Entry Priority="100" DisplayName="Test Methods"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;HasAttribute Name="Xunit.FactAttribute" /&gt;
&lt;HasAttribute Name="Xunit.TheoryAttribute" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"&gt;
&lt;TypePattern.Match&gt;
&lt;And&gt;
&lt;Kind Is="Class" /&gt;
&lt;Or&gt;
&lt;HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestFixtureSourceAttribute" Inherited="True" /&gt;
&lt;HasMember&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestAttribute" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestCaseAttribute" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestCaseSourceAttribute" /&gt;
&lt;/And&gt;
&lt;/HasMember&gt;
&lt;/Or&gt;
&lt;/And&gt;
&lt;/TypePattern.Match&gt;
&lt;Entry DisplayName="Setup/Teardown Methods"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;Or&gt;
&lt;HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestFixtureSetUpAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestFixtureTearDownAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.OneTimeSetUpAttribute" Inherited="True" /&gt;
&lt;HasAttribute Name="NUnit.Framework.OneTimeTearDownAttribute" Inherited="True" /&gt;
&lt;/Or&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="All other members" /&gt;
&lt;Entry Priority="100" DisplayName="Test Methods"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Method" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestAttribute" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestCaseAttribute" /&gt;
&lt;HasAttribute Name="NUnit.Framework.TestCaseSourceAttribute" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;TypePattern DisplayName="Default Pattern"&gt;
&lt;Entry Priority="100" DisplayName="Public Delegates"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Access Is="Public" /&gt;
&lt;Kind Is="Delegate" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry Priority="100" DisplayName="Public Enums"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Access Is="Public" /&gt;
&lt;Kind Is="Enum" /&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Static Fields and Constants"&gt;
&lt;Entry.Match&gt;
&lt;Or&gt;
&lt;Kind Is="Constant" /&gt;
&lt;And&gt;
&lt;Kind Is="Field" /&gt;
&lt;Static /&gt;
&lt;/And&gt;
&lt;/Or&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Kind Order="Constant Field" /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Fields"&gt;
&lt;Entry.Match&gt;
&lt;And&gt;
&lt;Kind Is="Field" /&gt;
&lt;Not&gt;
&lt;Static /&gt;
&lt;/Not&gt;
&lt;/And&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Readonly /&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Constructors"&gt;
&lt;Entry.Match&gt;
&lt;Kind Is="Constructor" /&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Static /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Events"&gt;
&lt;Entry.Match&gt;
&lt;Kind Is="Event" /&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Properties, Indexers"&gt;
&lt;Entry.Match&gt;
&lt;Or&gt;
&lt;Kind Is="Property" /&gt;
&lt;Kind Is="Indexer" /&gt;
&lt;/Or&gt;
&lt;/Entry.Match&gt;
&lt;Entry.SortBy&gt;
&lt;Access Order="Public Internal Protected Private" /&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="All other members"&gt;
&lt;Entry.SortBy&gt;
&lt;Access Order="Public Internal Protected Private" /&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;Entry DisplayName="Nested Types"&gt;
&lt;Entry.Match&gt;
&lt;Kind Is="Type" /&gt;
&lt;/Entry.Match&gt;
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;/Patterns&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Licensed to the .NET Foundation under one or more agreements.
The .NET Foundation licenses this file to you under the MIT license.
See the LICENSE file in the project root for more information.</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<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_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=CONNACK/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PINGREQ/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsub/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PINGRESP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PUBACK/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PUBCOMP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PUBREC/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PUBREL/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SUBACK/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tnet/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsub/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UNSUBACK/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+13 -105
View File
@@ -1,18 +1,18 @@
<p align="center">
<img src="https://github.com/chkr1011/MQTTnet/blob/master/Images/icon_det_256.png?raw=true" width="196">
<br/>
<img src="https://github.com/dotnet/MQTTnet/blob/master/Images/icon_det_256.png?raw=true" width="196">
<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)
[![BCH compliance](https://bettercodehub.com/edge/badge/chkr1011/MQTTnet?branch=master)](https://bettercodehub.com/)
[![CI](https://github.com/dotnet/MQTTnet/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/dotnet/MQTTnet/actions/workflows/ci.yml)
[![MyGet](https://img.shields.io/myget/mqttnet/v/mqttnet?color=orange&label=MyGet-Preview)](https://www.myget.org/feed/mqttnet/package/nuget/MQTTnet)
![Size](https://img.shields.io/github/repo-size/dotnet/MQTTnet.svg)
[![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)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://raw.githubusercontent.com/dotnet/MQTTnet/master/LICENSE)
# MQTTnet
MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from <http://mqtt.org/>.
MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports the MQTT protocol up to version 5. It is compatible with mostly any supported .NET Framework version and CPU architecture.
## Features
@@ -22,11 +22,10 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
* TLS support for client and server (but not UWP servers)
* Extensible communication channels (e.g. In-Memory, TCP, TCP+TLS, WS)
* Lightweight (only the low level implementation of MQTT, no overhead)
* Performance optimized (processing ~70.000 messages / second)*
* Performance optimized (processing ~150.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 (~250 tests)
* Unit tested (~636 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_.
@@ -50,103 +49,12 @@ 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
## Code of Conduct
_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
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
## Supported frameworks
## .NET Foundation
* .NET 5.0+
* .NET Standard 1.3+
* .NET Core 1.1+
* .NET Core App 1.1+
* .NET Framework 4.5.2+
* Mono 5.2+
* Universal Windows Platform (UWP) 10.0.10240+ (Windows 10 IoT Core)
* Xamarin.Android 7.5+
* Xamarin.iOS 10.14+
* Blazor WebAssembly 3.2.0+
## Supported platforms
* x86
* x64
* AnyCPU
* ARM
## Supported OS
* Windows
* Windows 10 IoT Core
* Linux (Ubuntu, Raspbian etc.)
* macOS
* Android
* iOS
## Supported MQTT versions
* 5.0.0
* 3.1.1
* 3.1.0
## Nuget
This library is available as a nuget package: <https://www.nuget.org/packages/MQTTnet/>
## Examples
Please find examples and the documentation at the Wiki of this repository (<https://github.com/chkr1011/MQTTnet/wiki>).
## Contributions
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.
## References
This library is used in the following projects:
* Azure Functions MQTT Bindings, <https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt>)
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
* MQTT Client Rx (Managed Client Wrapper for Reactive Extensions, <https://github.com/mmuecke/RxMQTTnet>)
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
* MQTTnet App (Cross platform client application for MQTT debugging, inspection etc., <https://github.com/chkr1011/MQTTnet.App>)
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
* SparkplugNet (Sparkplug library for .Net, <https://github.com/SeppPenner/SparkplugNet>)
Further projects using this project can be found under https://github.com/chkr1011/MQTTnet/network/dependents.
If you use this library and want to see your project here please create a pull request.
## License
MIT License
MQTTnet Copyright (c) 2016-2021 Christian Kratky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
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.
This project is supported by the [.NET Foundation](https://dotnetfoundation.org).
+411
View File
@@ -0,0 +1,411 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using System.Security.Authentication;
using MQTTnet.Client;
using MQTTnet.Extensions.WebSocket4Net;
using MQTTnet.Formatter;
using MQTTnet.Samples.Helpers;
namespace MQTTnet.Samples.Client;
public static class Client_Connection_Samples
{
public static async Task Clean_Disconnect()
{
/*
* This sample disconnects in a clean way. This will send a MQTT DISCONNECT packet
* to the server and close the connection afterwards.
*
* See sample _Connect_Client_ for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// This will send the DISCONNECT packet. Calling _Dispose_ without DisconnectAsync the
// connection is closed in a "not clean" way. See MQTT specification for more details.
await mqttClient.DisconnectAsync(new MqttClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.NormalDisconnection).Build());
}
}
public static async Task Connect_Client()
{
/*
* This sample creates a simple MQTT client and connects to a public broker.
*
* Always dispose the client when it is no longer used.
* The default version of MQTT is 3.1.1.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
// Use builder classes where possible in this project.
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
// This will throw an exception if the server is not available.
// The result from this message returns additional data which was sent
// from the server. Please refer to the MQTT protocol specification for details.
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("The MQTT client is connected.");
response.DumpToConsole();
// Send a clean disconnect to the server by calling _DisconnectAsync_. Without this the TCP connection
// gets dropped and the server will handle this as a non clean disconnect (see MQTT spec for details).
var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder().Build();
await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
}
}
public static async Task Connect_Client_Timeout()
{
/*
* This sample creates a simple MQTT client and connects to an invalid broker using a timeout.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build();
try
{
using (var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(1)))
{
await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Timeout while connecting.");
}
}
}
public static async Task Connect_Client_Using_MQTTv5()
{
/*
* This sample creates a simple MQTT client and connects to a public broker using MQTTv5.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").WithProtocolVersion(MqttProtocolVersion.V500).Build();
// In MQTTv5 the response contains much more information.
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("The MQTT client is connected.");
response.DumpToConsole();
}
}
public static async Task Connect_Client_Using_TLS_1_2()
{
/*
* This sample creates a simple MQTT client and connects to a public broker using TLS 1.2 encryption.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io")
.WithTls(
o =>
{
// The used public broker sometimes has invalid certificates. This sample accepts all
// certificates. This should not be used in live environments.
o.CertificateValidationHandler = _ => true;
// The default value is determined by the OS. Set manually to force version.
o.SslProtocol = SslProtocols.Tls12;
})
.Build();
using (var timeout = new CancellationTokenSource(5000))
{
await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
Console.WriteLine("The MQTT client is connected.");
}
}
}
public static async Task Connect_Client_Using_WebSocket4Net()
{
/*
* This sample creates a simple MQTT client and connects to a public broker using a WebSocket connection.
* Instead of the .NET implementation of WebSockets the implementation from WebSocket4Net is used. It provides more
* encryption algorithms and supports more platforms.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory().UseWebSocket4Net();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt").Build();
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("The MQTT client is connected.");
response.DumpToConsole();
}
}
public static async Task Connect_Client_Using_WebSockets()
{
/*
* This sample creates a simple MQTT client and connects to a public broker using a WebSocket connection.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt").Build();
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("The MQTT client is connected.");
response.DumpToConsole();
}
}
public static async Task Connect_Client_With_TLS_Encryption()
{
/*
* This sample creates a simple MQTT client and connects to a public broker with enabled TLS encryption.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8883)
.WithTls(
o =>
{
// The used public broker sometimes has invalid certificates. This sample accepts all
// certificates. This should not be used in live environments.
o.CertificateValidationHandler = _ => true;
})
.Build();
// In MQTTv5 the response contains much more information.
using (var timeout = new CancellationTokenSource(5000))
{
var response = await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
Console.WriteLine("The MQTT client is connected.");
response.DumpToConsole();
}
}
}
public static async Task Disconnect_Clean()
{
/*
* This sample disconnects from the server with sending a DISCONNECT packet.
* This way of disconnecting is treated as a clean disconnect which will not
* trigger sending the last will etc.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// Calling _DisconnectAsync_ will send a DISCONNECT packet before closing the connection.
// Using a reason code requires MQTT version 5.0.0!
await mqttClient.DisconnectAsync(MqttClientDisconnectOptionsReason.ImplementationSpecificError);
}
}
public static async Task Disconnect_Non_Clean()
{
/*
* This sample disconnects from the server without sending a DISCONNECT packet.
* This way of disconnecting is treated as a non clean disconnect which will
* trigger sending the last will etc.
*/
var mqttFactory = new MqttFactory();
var mqttClient = mqttFactory.CreateMqttClient();
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// Calling _Dispose_ or use of a _using_ statement will close the transport connection
// without sending a DISCONNECT packet to the server.
mqttClient.Dispose();
}
public static async Task Inspect_Certificate_Validation_Errors()
{
/*
* This sample prints the certificate information while connection. This data can be used to decide whether a connection is secure or not
* including the reason for that status.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io", 8883)
.WithTls(
o =>
{
o.CertificateValidationHandler = eventArgs =>
{
eventArgs.Certificate.Subject.DumpToConsole();
eventArgs.Certificate.GetExpirationDateString().DumpToConsole();
eventArgs.Chain.ChainPolicy.RevocationMode.DumpToConsole();
eventArgs.Chain.ChainStatus.DumpToConsole();
eventArgs.SslPolicyErrors.DumpToConsole();
return true;
};
})
.Build();
// In MQTTv5 the response contains much more information.
using (var timeout = new CancellationTokenSource(5000))
{
await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
}
}
}
public static async Task Ping_Server()
{
/*
* This sample sends a PINGREQ packet to the server and waits for a reply.
*
* This is only supported in MQTTv5.0.0+.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// This will throw an exception if the server does not reply.
await mqttClient.PingAsync(CancellationToken.None);
Console.WriteLine("The MQTT server replied to the ping request.");
}
}
public static async Task Reconnect_Using_Event()
{
/*
* This sample shows how to reconnect when the connection was dropped.
* This approach uses one of the events from the client.
* This approach has a risk of dead locks! Consider using the timer approach (see sample).
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
mqttClient.DisconnectedAsync += async e =>
{
if (e.ClientWasConnected)
{
// Use the current options as the new options.
await mqttClient.ConnectAsync(mqttClient.Options);
}
};
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
}
}
public static void Reconnect_Using_Timer()
{
/*
* This sample shows how to reconnect when the connection was dropped.
* This approach uses a custom Task/Thread which will monitor the connection status.
* This is the recommended way but requires more custom code!
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
_ = Task.Run(
async () =>
{
// User proper cancellation and no while(true).
while (true)
{
try
{
// This code will also do the very first connect! So no call to _ConnectAsync_ is required in the first place.
if (!await mqttClient.TryPingAsync())
{
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// Subscribe to topics when session is clean etc.
Console.WriteLine("The MQTT client is connected.");
}
}
catch
{
// Handle the exception properly (logging etc.).
}
finally
{
// Check the connection state every 5 seconds and perform a reconnect if required.
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
});
}
}
}
+93
View File
@@ -0,0 +1,93 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Client;
namespace MQTTnet.Samples.Client;
public static class Client_Publish_Samples
{
public static async Task Publish_Application_Message()
{
/*
* This sample pushes a simple application message including a topic and a payload.
*
* Always use builders where they exist. Builders (in this project) are designed to be
* backward compatible. Creating an _MqttApplicationMessage_ via its constructor is also
* supported but the class might change often in future releases where the builder does not
* or at least provides backward compatibility where possible.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("samples/temperature/living_room")
.WithPayload("19.5")
.Build();
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
await mqttClient.DisconnectAsync();
Console.WriteLine("MQTT application message is published.");
}
}
public static async Task Publish_Multiple_Application_Messages()
{
/*
* This sample pushes multiple simple application message including a topic and a payload.
*
* See sample _Publish_Application_Message_ for more details.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("samples/temperature/living_room")
.WithPayload("19.5")
.Build();
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("samples/temperature/living_room")
.WithPayload("20.0")
.Build();
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("samples/temperature/living_room")
.WithPayload("21.0")
.Build();
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
await mqttClient.DisconnectAsync();
Console.WriteLine("MQTT application message is published.");
}
}
}
+179
View File
@@ -0,0 +1,179 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Client;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Samples.Helpers;
namespace MQTTnet.Samples.Client;
public static class Client_Subscribe_Samples
{
public static async Task Handle_Received_Application_Message()
{
/*
* This sample subscribes to a topic and processes the received message.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
// Setup message handling before connecting so that queued messages
// are also handled properly. When there is no event handler attached all
// received messages get lost.
mqttClient.ApplicationMessageReceivedAsync += e =>
{
Console.WriteLine("Received application message.");
e.DumpToConsole();
return Task.CompletedTask;
};
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/2");
})
.Build();
await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
Console.WriteLine("MQTT client subscribed to topic.");
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
}
public static async Task Send_Responses()
{
/*
* This sample subscribes to a topic and sends a response to the broker. This requires at least QoS level 1 to work!
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
mqttClient.ApplicationMessageReceivedAsync += delegate(MqttApplicationMessageReceivedEventArgs args)
{
// Do some work with the message...
// Now respond to the broker with a reason code other than success.
args.ReasonCode = MqttApplicationMessageReceivedReasonCode.ImplementationSpecificError;
args.ResponseReasonString = "That did not work!";
// User properties require MQTT v5!
args.ResponseUserProperties.Add(new MqttUserProperty("My", "Data"));
// Now the broker will resend the message again.
return Task.CompletedTask;
};
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/1");
})
.Build();
var response = await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
Console.WriteLine("MQTT client subscribed to topic.");
// The response contains additional data sent by the server after subscribing.
response.DumpToConsole();
}
}
public static async Task Subscribe_Multiple_Topics()
{
/*
* This sample subscribes to several topics in a single request.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// Create the subscribe options including several topics with different options.
// It is also possible to all of these topics using a dedicated call of _SubscribeAsync_ per topic.
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/1");
})
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/2").WithNoLocal();
})
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/3").WithRetainHandling(MqttRetainHandling.SendAtSubscribe);
})
.Build();
var response = await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
Console.WriteLine("MQTT client subscribed to topics.");
// The response contains additional data sent by the server after subscribing.
response.DumpToConsole();
}
}
public static async Task Subscribe_Topic()
{
/*
* This sample subscribes to a topic.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("mqttnet/samples/topic/1");
})
.Build();
var response = await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
Console.WriteLine("MQTT client subscribed to topic.");
// The response contains additional data sent by the server after subscribing.
response.DumpToConsole();
}
}
}
+95
View File
@@ -0,0 +1,95 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using System.Text;
using MQTTnet.Diagnostics;
namespace MQTTnet.Samples.Diagnostics;
public static class Logger_Samples
{
public static async Task Create_Custom_Logger()
{
/*
* This sample covers the creation of a custom logger which can be used to forward MQTTnet log messages
* to other loggers like Microsoft logger or Serilog or log4net etc.
*/
var mqttFactory = new MqttFactory(new MyLogger());
var mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("MQTT client is connected.");
var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder()
.Build();
await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
}
}
public static async Task Use_Event_Logger()
{
/*
* This sample shows how to get logs from the library.
*
* ATTENTION: Only use the logger for debugging etc. The performance is heavily decreased when a logger is used.
*/
// The logger ID is optional but can be set do distinguish different logger instances.
var mqttEventLogger = new MqttNetEventLogger("MyCustomLogger");
mqttEventLogger.LogMessagePublished += (sender, args) =>
{
var output = new StringBuilder();
output.AppendLine($">> [{args.LogMessage.Timestamp:O}] [{args.LogMessage.ThreadId}] [{args.LogMessage.Source}] [{args.LogMessage.Level}]: {args.LogMessage.Message}");
if (args.LogMessage.Exception != null)
{
output.AppendLine(args.LogMessage.Exception.ToString());
}
Console.Write(output);
};
var mqttFactory = new MqttFactory(mqttEventLogger);
var mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("MQTT client is connected.");
var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder()
.Build();
await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
}
}
sealed class MyLogger : IMqttNetLogger
{
public bool IsEnabled { get; set; } = true;
public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception)
{
// Forward the log message to other loggers.
// 1. Convert log level to matching log level in target logger.
// 2. Call target logger and pass data accordingly.
}
}
}
@@ -0,0 +1,55 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Diagnostics;
namespace MQTTnet.Samples.Diagnostics;
public static class PackageInspection_Samples
{
public static async Task Inspect_Outgoing_Package()
{
/*
* This sample covers the inspection of outgoing packages from the client.
*/
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
mqttClient.InspectPackage += OnInspectPackage;
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Console.WriteLine("MQTT client is connected.");
var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder()
.Build();
await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
}
}
static Task OnInspectPackage(InspectMqttPacketEventArgs eventArgs)
{
if (eventArgs.Direction == MqttPacketFlowDirection.Inbound)
{
Console.WriteLine($"IN: {Convert.ToBase64String(eventArgs.Buffer)}");
}
else
{
Console.WriteLine($"OUT: {Convert.ToBase64String(eventArgs.Buffer)}");
}
return Task.CompletedTask;
}
}
+25
View File
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
namespace MQTTnet.Samples.Helpers;
internal static class ObjectExtensions
{
public static TObject DumpToConsole<TObject>(this TObject @object)
{
var output = "NULL";
if (@object != null)
{
output = JsonSerializer.Serialize(@object, new JsonSerializerOptions
{
WriteIndented = true
});
}
Console.WriteLine($"[{@object?.GetType().Name}]:\r\n{output}");
return @object;
}
}
+24
View File
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<NoWarn>1591;NETSDK1138</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
<ProjectReference Include="..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" />
<ProjectReference Include="..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj" />
<ProjectReference Include="..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj" />
<ProjectReference Include="..\Source\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Client;
using MQTTnet.Extensions.ManagedClient;
namespace MQTTnet.Samples.ManagedClient;
public sealed class Managed_Client_Simple_Samples
{
public static async Task Connect_Client()
{
/*
* This sample creates a simple managed MQTT client and connects to a public broker.
*
* The managed client extends the existing _MqttClient_. It adds the following features.
* - Reconnecting when connection is lost.
* - Storing pending messages in an internal queue so that an enqueue is possible while the client remains not connected.
*/
var mqttFactory = new MqttFactory();
using (var managedMqttClient = mqttFactory.CreateManagedMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
var managedMqttClientOptions = new ManagedMqttClientOptionsBuilder()
.WithClientOptions(mqttClientOptions)
.Build();
await managedMqttClient.StartAsync(managedMqttClientOptions);
// The application message is not sent. It is stored in an internal queue and
// will be sent when the client is connected.
await managedMqttClient.EnqueueAsync("Topic", "Payload");
Console.WriteLine("The managed MQTT client is connected.");
// Wait until the queue is fully processed.
SpinWait.SpinUntil(() => managedMqttClient.EnqueuedApplicationMessagesCount == 0, 10000);
Console.WriteLine($"Pending messages = {managedMqttClient.EnqueuedApplicationMessagesCount}");
}
}
}
+54
View File
@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Reflection;
Console.WriteLine("Welcome to MQTTnet samples!");
Console.WriteLine();
var sampleClasses = Assembly.GetExecutingAssembly().GetExportedTypes().OrderBy(c => c.Name).ToList();
var index = 0;
foreach (var sampleClass in sampleClasses)
{
Console.WriteLine($"{index} = {sampleClass.Name}");
index++;
}
Console.Write("Please choose sample class (press Enter to continue): ");
var input = Console.ReadLine();
var selectedIndex = int.Parse(input ?? "0");
var selectedSampleClass = sampleClasses[selectedIndex];
var sampleMethods = selectedSampleClass.GetMethods(BindingFlags.Static | BindingFlags.Public).OrderBy(m => m.Name).ToList();
index = 0;
foreach (var sampleMethod in sampleMethods)
{
Console.WriteLine($"{index} = {sampleMethod.Name}");
index++;
}
Console.Write("Please choose sample (press Enter to continue): ");
input = Console.ReadLine();
selectedIndex = int.Parse(input ?? "0");
var selectedSampleMethod = sampleMethods[selectedIndex];
Console.WriteLine("Executing sample...");
Console.WriteLine();
try
{
if (selectedSampleMethod.Invoke(null, null) is Task task)
{
await task;
}
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
Console.WriteLine();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
+88
View File
@@ -0,0 +1,88 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Client;
using MQTTnet.Extensions.Rpc;
using MQTTnet.Protocol;
namespace MQTTnet.Samples.RpcClient;
public static class RpcClient_Samples
{
/*
* The extension MQTTnet.Extensions.Rpc (available as nuget) allows sending a request and waiting for the matching reply.
* This is done via defining a pattern which uses the topic to correlate the request and the response.
* From client usage it is possible to define a timeout.
*/
public static async Task Send_Request()
{
var mqttFactory = new MqttFactory();
// The RPC client is an addon for the existing client. So we need a regular client
// which is wrapped later.
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.Build();
await mqttClient.ConnectAsync(mqttClientOptions);
using (var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient))
{
// Access to a fully featured application message is not supported for RPC calls!
// The method will throw an exception when the response was not received in time.
await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(2), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
}
Console.WriteLine("The RPC call was successful.");
}
}
/*
* The device must respond to the request using the correct topic. The following C code shows how a
* smart device like an ESP8266 must respond to the above sample.
*
// If using the MQTT client PubSubClient it must be ensured
// that the request topic for each method is subscribed like the following.
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:
mqttClient.subscribe("MQTTnet.RPC/+/deviceA.ping");
mqttClient.subscribe("MQTTnet.RPC/+/deviceB.ping");
mqttClient.subscribe("MQTTnet.RPC/+/deviceC.getTemperature");
// Within the callback of the MQTT client the topic must be checked
// if it belongs to MQTTnet RPC. The following code shows one
// possible way of doing this.
void mqtt_Callback(char *topic, byte *payload, unsigned int payloadLength)
{
String topicString = String(topic);
if (topicString.startsWith("MQTTnet.RPC/")) {
String responseTopic = topicString + String("/response");
if (topicString.endsWith("/deviceA.ping")) {
mqtt_publish(responseTopic, "pong", false);
return;
}
}
}
// Important notes:
// ! Do not send response message with the _retain_ flag set to true.
// ! All required data for a RPC call and the result must be placed into the payload.
*/
}
+110
View File
@@ -0,0 +1,110 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
// ReSharper disable EmptyConstructor
// ReSharper disable MemberCanBeMadeStatic.Local
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MQTTnet.AspNetCore;
using MQTTnet.Server;
namespace MQTTnet.Samples.Server;
public static class Server_Asp_Net_Samples
{
public static Task Start_Server_With_WebSockets_Support()
{
/*
* This sample starts a minimal ASP.NET Webserver including a hosted MQTT server.
*/
var host = Host.CreateDefaultBuilder(Array.Empty<string>())
.ConfigureWebHostDefaults(
webBuilder =>
{
webBuilder.UseKestrel(
o =>
{
// This will allow MQTT connections based on TCP port 1883.
o.ListenAnyIP(1883, l => l.UseMqtt());
// This will allow MQTT connections based on HTTP WebSockets with URI "localhost:5000/mqtt"
// See code below for URI configuration.
o.ListenAnyIP(5000); // Default HTTP pipeline
});
webBuilder.UseStartup<Startup>();
});
return host.RunConsoleAsync();
}
sealed class MqttController
{
public MqttController()
{
// Inject other services via constructor.
}
public Task OnClientConnected(ClientConnectedEventArgs eventArgs)
{
Console.WriteLine($"Client '{eventArgs.ClientId}' connected.");
return Task.CompletedTask;
}
public Task ValidateConnection(ValidatingConnectionEventArgs eventArgs)
{
Console.WriteLine($"Client '{eventArgs.ClientId}' wants to connect. Accepting!");
return Task.CompletedTask;
}
}
sealed class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment environment, MqttController mqttController)
{
app.UseRouting();
app.UseEndpoints(
endpoints =>
{
endpoints.MapConnectionHandler<MqttConnectionHandler>(
"/mqtt",
httpConnectionDispatcherOptions => httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector =
protocolList => protocolList.FirstOrDefault() ?? string.Empty);
});
app.UseMqttServer(
server =>
{
/*
* Attach event handlers etc. if required.
*/
server.ValidatingConnectionAsync += mqttController.ValidateConnection;
server.ClientConnectedAsync += mqttController.OnClientConnected;
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedMqttServer(
optionsBuilder =>
{
optionsBuilder.WithDefaultEndpoint();
});
services.AddMqttConnectionHandler();
services.AddConnections();
services.AddSingleton<MqttController>();
}
}
}
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Server;
namespace MQTTnet.Samples.Server;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
// ReSharper disable EmptyConstructor
// ReSharper disable MemberCanBeMadeStatic.Local
public static class Server_Diagnostics_Samples
{
public static async Task Get_Notified_When_Client_Received_Message()
{
/*
* This sample starts a MQTT server and attaches an event which gets fired whenever
* a client received and acknowledged a PUBLISH packet.
*/
var mqttFactory = new MqttFactory();
var mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
{
// Attach the event handler.
mqttServer.ClientAcknowledgedPublishPacketAsync += e =>
{
Console.WriteLine($"Client '{e.ClientId}' acknowledged packet {e.PublishPacket.PacketIdentifier} with topic '{e.PublishPacket.Topic}'");
// It is also possible to read additional data from the client response. This requires casting the response packet.
var qos1AcknowledgePacket = e.AcknowledgePacket as MqttPubAckPacket;
Console.WriteLine($"QoS 1 reason code: {qos1AcknowledgePacket?.ReasonCode}");
var qos2AcknowledgePacket = e.AcknowledgePacket as MqttPubCompPacket;
Console.WriteLine($"QoS 2 reason code: {qos1AcknowledgePacket?.ReasonCode}");
return CompletedTask.Instance;
};
await mqttServer.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
await mqttServer.StopAsync();
}
}
}
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
// ReSharper disable EmptyConstructor
// ReSharper disable MemberCanBeMadeStatic.Local
using MQTTnet.Internal;
using MQTTnet.Server;
namespace MQTTnet.Samples.Server;
public static class Server_Intercepting_Samples
{
public static async Task Intercept_Application_Messages()
{
/*
* This sample starts a simple MQTT server which manipulate all processed application messages.
* Please see _Server_Simple_Samples_ for more details on how to start a server.
*/
var mqttFactory = new MqttFactory();
var mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
{
mqttServer.InterceptingPublishAsync += args =>
{
// Here we only change the topic of the received application message.
// but also changing the payload etc. is required. Changing the QoS after
// transmitting is not supported and makes no sense at all.
args.ApplicationMessage.Topic += "/manipulated";
return CompletedTask.Instance;
};
await mqttServer.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
await mqttServer.StopAsync();
}
}
}
@@ -0,0 +1,82 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using System.Text.Json;
namespace MQTTnet.Samples.Server;
public static class Server_Retained_Messages_Samples
{
public static async Task Persist_Retained_Messages()
{
/*
* This sample starts a simple MQTT server which will store all retained messages in a file.
*/
var storePath = Path.Combine(Path.GetTempPath(), "RetainedMessages.json");
var mqttFactory = new MqttFactory();
// Due to security reasons the "default" endpoint (which is unencrypted) is not enabled by default!
var mqttServerOptions = mqttFactory.CreateServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var server = mqttFactory.CreateMqttServer(mqttServerOptions))
{
// Make sure that the server will load the retained messages.
server.LoadingRetainedMessageAsync += async eventArgs =>
{
try
{
eventArgs.LoadedRetainedMessages = await JsonSerializer.DeserializeAsync<List<MqttApplicationMessage>>(File.OpenRead(storePath));
Console.WriteLine("Retained messages loaded.");
}
catch (FileNotFoundException)
{
// Ignore because nothing is stored yet.
Console.WriteLine("No retained messages stored yet.");
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
};
// Make sure to persist the changed retained messages.
server.RetainedMessageChangedAsync += async eventArgs =>
{
try
{
// This sample uses the property _StoredRetainedMessages_ which will contain all(!) retained messages.
// The event args also contain the affected retained message (property ChangedRetainedMessage). This can be
// used to write all retained messages to dedicated files etc. Then all files must be loaded and a full list
// of retained messages must be provided in the loaded event.
var buffer = JsonSerializer.SerializeToUtf8Bytes(eventArgs.StoredRetainedMessages);
await File.WriteAllBytesAsync(storePath, buffer);
Console.WriteLine("Retained messages saved.");
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
};
// Make sure to clear the retained messages when they are all deleted via API.
server.RetainedMessagesClearedAsync += _ =>
{
File.Delete(storePath);
return Task.CompletedTask;
};
await server.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
}
}
+219
View File
@@ -0,0 +1,219 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable InconsistentNaming
using MQTTnet.Diagnostics;
using MQTTnet.Protocol;
using MQTTnet.Server;
namespace MQTTnet.Samples.Server;
public static class Server_Simple_Samples
{
public static async Task Force_Disconnecting_Client()
{
/*
* This sample will disconnect a client.
*
* See _Run_Minimal_Server_ for more information.
*/
using (var mqttServer = await StartMqttServer())
{
// Let the client connect.
await Task.Delay(TimeSpan.FromSeconds(5));
// Now disconnect the client (if connected).
var affectedClient = (await mqttServer.GetClientsAsync()).FirstOrDefault(c => c.Id == "MyClient");
if (affectedClient != null)
{
await affectedClient.DisconnectAsync();
}
}
}
public static async Task Publish_Message_From_Broker()
{
/*
* This sample will publish a message directly at the broker.
*
* See _Run_Minimal_Server_ for more information.
*/
using (var mqttServer = await StartMqttServer())
{
// Create a new message using the builder as usual.
var message = new MqttApplicationMessageBuilder().WithTopic("HelloWorld").WithPayload("Test").Build();
// Now inject the new message at the broker.
await mqttServer.InjectApplicationMessage(
new InjectedMqttApplicationMessage(message)
{
SenderClientId = "SenderClientId"
});
}
}
public static async Task Run_Minimal_Server()
{
/*
* This sample starts a simple MQTT server which will accept any TCP connection.
*/
var mqttFactory = new MqttFactory();
// The port for the default endpoint is 1883.
// The default endpoint is NOT encrypted!
// Use the builder classes where possible.
var mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
// The port can be changed using the following API (not used in this example).
// new MqttServerOptionsBuilder()
// .WithDefaultEndpoint()
// .WithDefaultEndpointPort(1234)
// .Build();
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
{
await mqttServer.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
// Stop and dispose the MQTT server if it is no longer needed!
await mqttServer.StopAsync();
}
}
public static async Task Run_Server_With_Logging()
{
/*
* This sample starts a simple MQTT server and prints the logs to the output.
*
* IMPORTANT! Do not enable logging in live environment. It will decrease performance.
*
* See sample "Run_Minimal_Server" for more details.
*/
var mqttFactory = new MqttFactory(new ConsoleLogger());
var mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
{
await mqttServer.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
// Stop and dispose the MQTT server if it is no longer needed!
await mqttServer.StopAsync();
}
}
public static async Task Validating_Connections()
{
/*
* This sample starts a simple MQTT server which will check for valid credentials and client ID.
*
* See _Run_Minimal_Server_ for more information.
*/
var mqttFactory = new MqttFactory();
var mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
{
// Setup connection validation before starting the server so that there is
// no change to connect without valid credentials.
mqttServer.ValidatingConnectionAsync += e =>
{
if (e.ClientId != "ValidClientId")
{
e.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
}
if (e.UserName != "ValidUser")
{
e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
}
if (e.Password != "SecretPassword")
{
e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
}
return Task.CompletedTask;
};
await mqttServer.StartAsync();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
await mqttServer.StopAsync();
}
}
static async Task<MqttServer> StartMqttServer()
{
var mqttFactory = new MqttFactory();
// Due to security reasons the "default" endpoint (which is unencrypted) is not enabled by default!
var mqttServerOptions = mqttFactory.CreateServerOptionsBuilder().WithDefaultEndpoint().Build();
var server = mqttFactory.CreateMqttServer(mqttServerOptions);
await server.StartAsync();
return server;
}
class ConsoleLogger : IMqttNetLogger
{
readonly object _consoleSyncRoot = new();
public bool IsEnabled => true;
public void Publish(MqttNetLogLevel logLevel, string source, string message, object[]? parameters, Exception? exception)
{
var foregroundColor = ConsoleColor.White;
switch (logLevel)
{
case MqttNetLogLevel.Verbose:
foregroundColor = ConsoleColor.White;
break;
case MqttNetLogLevel.Info:
foregroundColor = ConsoleColor.Green;
break;
case MqttNetLogLevel.Warning:
foregroundColor = ConsoleColor.DarkYellow;
break;
case MqttNetLogLevel.Error:
foregroundColor = ConsoleColor.Red;
break;
}
if (parameters?.Length > 0)
{
message = string.Format(message, parameters);
}
lock (_consoleSyncRoot)
{
Console.ForegroundColor = foregroundColor;
Console.WriteLine(message);
if (exception != null)
{
Console.WriteLine(exception);
}
}
}
}
}
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netcoreapp3.1' ">
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
<ProjectReference Include="..\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
<ProjectReference Include="..\MQTTnet.Tests\MQTTnet.Tests.csproj" />
</ItemGroup>
</Project>
@@ -1,18 +1,23 @@
using Microsoft.AspNetCore.Connections;
using MQTTnet.Adapter;
using MQTTnet.Formatter;
using MQTTnet.Server;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Server;
namespace MQTTnet.AspNetCore.Tests.Mockups
{
public class ConnectionHandlerMockup: IMqttServerAdapter
public sealed class ConnectionHandlerMockup : IMqttServerAdapter
{
public TaskCompletionSource<MqttConnectionContext> Context { get; } = new TaskCompletionSource<MqttConnectionContext>();
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public TaskCompletionSource<MqttConnectionContext> Context { get; } = new TaskCompletionSource<MqttConnectionContext>();
public ConnectionHandlerMockup()
public void Dispose()
{
}
@@ -20,8 +25,7 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
{
try
{
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(writer);
var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535));
var context = new MqttConnectionContext(formatter, connection);
Context.TrySetResult(context);
@@ -33,7 +37,7 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
}
}
public Task StartAsync(IMqttServerOptions options)
public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger)
{
return Task.CompletedTask;
}
@@ -42,9 +46,5 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
{
return Task.CompletedTask;
}
public void Dispose()
{
}
}
}
}
@@ -1,8 +1,12 @@
using System.IO.Pipelines;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO.Pipelines;
namespace MQTTnet.AspNetCore.Tests.Mockups
{
public class DuplexPipeMockup : IDuplexPipe
public sealed class DuplexPipeMockup : IDuplexPipe
{
public DuplexPipeMockup()
{
@@ -16,9 +20,8 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
PipeWriter IDuplexPipe.Output => Send.Writer;
public Pipe Receive { get; }
public Pipe Receive { get; set; }
public Pipe Send { get; set; }
public Pipe Send { get; }
}
}
@@ -1,8 +1,12 @@
using System.Buffers;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Buffers;
namespace MQTTnet.AspNetCore.Tests.Mockups
{
public class LimitedMemoryPool : MemoryPool<byte>
public sealed class LimitedMemoryPool : MemoryPool<byte>
{
protected override void Dispose(bool disposing)
{
@@ -1,11 +1,15 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
namespace MQTTnet.AspNetCore.Tests.Mockups
{
public class MemoryOwner : IMemoryOwner<byte>
public sealed class MemoryOwner : IMemoryOwner<byte>
{
private readonly byte[] _raw;
readonly byte[] _raw;
public MemoryOwner(int size)
{
@@ -23,11 +27,11 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
Memory = _raw;
}
public Memory<byte> Memory { get; }
public void Dispose()
{
ArrayPool<byte>.Shared.Return(_raw);
}
public Memory<byte> Memory { get; }
}
}
@@ -1,58 +1,76 @@
using Microsoft.AspNetCore.Builder;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Tests.Mockups;
using MQTTnet.Client.Options;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using System.Net;
using MQTTnet.AspNetCore.Extensions;
using MQTTnet.Protocol;
using MQTTnet.Tests.Helpers;
namespace MQTTnet.AspNetCore.Tests
{
[TestClass]
public class MqttConnectionContextTest
{
[TestMethod]
public async Task TestReceivePacketAsyncThrowsWhenReaderCompleted()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
pipe.Receive.Writer.Complete();
await Assert.ThrowsExceptionAsync<MqttCommunicationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
}
[TestMethod]
public async Task TestCorruptedConnectPacket()
{
var writer = new MqttPacketWriter();
var writer = new MqttBufferWriter(4096, 65535);
var serializer = new MqttPacketFormatterAdapter(writer);
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
await pipe.Receive.Writer.WriteAsync(writer.AddMqttHeader(MqttControlPacketType.Connect, new byte[0]));
await pipe.Receive.Writer.WriteAsync(writer.AddMqttHeader(MqttControlPacketType.Connect, Array.Empty<byte>()));
await Assert.ThrowsExceptionAsync<MqttProtocolViolationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
// the first exception should complete the pipes so if someone tries to use the connection after that it should throw immidiatly
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
}
[TestMethod]
public async Task TestEndpoint()
{
var mockup = new ConnectionHandlerMockup();
using (var host = new WebHostBuilder().UseKestrel(kestrel => kestrel.ListenLocalhost(1883, listener => listener.Use((ctx, next) => mockup.OnConnectedAsync(ctx))))
.UseStartup<Startup>()
.ConfigureServices(
(hostContext, services) =>
{
services.AddHostedMqttServer(o => o.WithoutDefaultEndpoint());
services.AddSingleton<IMqttServerAdapter>(mockup);
})
.Build())
using (var client = new MqttFactory().CreateMqttClient())
{
host.Start();
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build(), CancellationToken.None);
var ctx = await mockup.Context.Task;
#if NETCOREAPP3_1
var ep = IPEndPoint.Parse(ctx.Endpoint);
Assert.IsNotNull(ep);
#endif
Assert.IsNotNull(ctx);
}
}
// COMMENTED OUT DUE TO DEAD LOCK? OR VERY VERY SLOW PERFORMANCE ON LOCAL DEV MACHINE. TEST WAS STILL RUNNING AFTER SEVERAL MINUTES!
@@ -75,11 +93,11 @@ namespace MQTTnet.AspNetCore.Tests
// await Task.WhenAll(tasks).ConfigureAwait(false);
//}
[TestMethod]
public async Task TestLargePacket()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
@@ -91,42 +109,25 @@ namespace MQTTnet.AspNetCore.Tests
Assert.IsTrue(readResult.Buffer.Length > 20000);
}
private class Startup
[TestMethod]
public async Task TestReceivePacketAsyncThrowsWhenReaderCompleted()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
pipe.Receive.Writer.Complete();
await Assert.ThrowsExceptionAsync<MqttCommunicationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
}
class Startup
{
public void Configure(IApplicationBuilder app)
{
{
}
}
[TestMethod]
public async Task TestEndpoint()
{
var mockup = new ConnectionHandlerMockup();
using (var host = new WebHostBuilder()
.UseKestrel(kestrel => kestrel.ListenLocalhost(1883, listener => listener.Use((ctx, next) => mockup.OnConnectedAsync(ctx))))
.UseStartup<Startup>()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedMqttServer(o => o.WithoutDefaultEndpoint());
services.AddSingleton<IMqttServerAdapter>(mockup);
})
.Build())
using (var client = new MqttFactory().CreateMqttClient())
{
host.Start();
await client.ConnectAsync(new MqttClientOptionsBuilder()
.WithTcpServer("localhost")
.Build(), CancellationToken.None);
var ctx = await mockup.Context.Task;
#if NETCOREAPP3_1
var ep = IPEndPoint.Parse(ctx.Endpoint);
Assert.IsNotNull(ep);
#endif
Assert.IsNotNull(ctx);
}
}
}
}
}
@@ -1,47 +1,49 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETCOREAPP3_1
using System.Buffers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.AspNetCore.Extensions;
using MQTTnet.AspNetCore;
using MQTTnet.Formatter;
using MQTTnet.Packets;
namespace MQTTnet.AspNetCore.Tests
{
[TestClass]
public class ReaderExtensionsTest
public sealed class ReaderExtensionsTest
{
[TestMethod]
public void TestTryDeserialize()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var buffer = serializer.Encode(new MqttPublishPacket() {Topic = "a", Payload = new byte[5]});
var buffer = serializer.Encode(new MqttPublishPacket {Topic = "a", Payload = new byte[5]}).Join();
var sequence = new ReadOnlySequence<byte>(buffer.Array, buffer.Offset, buffer.Count);
var part = sequence;
MqttBasePacket packet;
MqttPacket packet;
var consumed = part.Start;
var observed = part.Start;
var result = false;
var read = 0;
var reader = new SpanBasedMqttPacketBodyReader();
part = sequence.Slice(sequence.Start, 0); // empty message should fail
result = serializer.TryDecode(reader, part, out packet, out consumed, out observed, out read);
result = serializer.TryDecode(part, out packet, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence.Slice(sequence.Start, 1); // partial fixed header should fail
result = serializer.TryDecode(reader, part, out packet, out consumed, out observed, out read);
result = serializer.TryDecode(part, out packet, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence.Slice(sequence.Start, 4); // partial body should fail
result = serializer.TryDecode(reader, part, out packet, out consumed, out observed, out read);
result = serializer.TryDecode(part, out packet, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence; // complete msg should work
result = serializer.TryDecode(reader, part, out packet, out consumed, out observed, out read);
result = serializer.TryDecode(part, out packet, out consumed, out observed, out read);
Assert.IsTrue(result);
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<NoWarn>1591;NETSDK1138</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
</Project>
@@ -0,0 +1,34 @@
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div>
<h1>MQTTnet ASP.NET Core Test App</h1>
</div>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script>
const options = {
clean: true,
connectTimeout: 4000,
clientId: 'mqttnet_web_client'
}
const client = mqtt.connect('ws://localhost:5049/mqtt')
client.on('connect', function () {
console.log('Connected')
client.subscribe('#', function (err) {
if (!err) {
client.publish('test', 'Hello mqtt')
}
})
})
client.on('message', function (topic, message) {
console.log(message.toString())
})
</script>
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace MQTTnet.AspTestApp.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MQTTnet</title>
</head>
<body>
@RenderBody()
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
@@ -0,0 +1,2 @@
@namespace MQTTnet.AspTestApp.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}
+73
View File
@@ -0,0 +1,73 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet;
using MQTTnet.AspNetCore;
using MQTTnet.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
// Setup MQTT stuff.
builder.Services.AddMqttServer();
builder.Services.AddConnections();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
// Setup MQTT stuff.
app.UseEndpoints(endpoints =>
{
endpoints.MapMqtt("/mqtt");
});
app.UseMqttServer(server =>
{
server.StartedAsync += args =>
{
_ = Task.Run(async () =>
{
var mqttApplicationMessage = new MqttApplicationMessageBuilder()
.WithPayload($"Test application message from MQTTnet server.")
.WithTopic("message")
.Build();
while (true)
{
try
{
await server.InjectApplicationMessage(new InjectedMqttApplicationMessage(mqttApplicationMessage)
{
SenderClientId = "server"
});
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
});
return Task.CompletedTask;
};
});
app.Run();
@@ -0,0 +1,9 @@
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
+5
View File
@@ -0,0 +1,5 @@
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": []
}
@@ -1,9 +1,13 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using MQTTnet.Server;
namespace MQTTnet.AspNetCore.Extensions
namespace MQTTnet.AspNetCore
{
public static class ApplicationBuilderExtensions
{
@@ -36,9 +40,9 @@ namespace MQTTnet.AspNetCore.Extensions
return app;
}
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<MqttServer> configure)
{
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
var server = app.ApplicationServices.GetRequiredService<MqttServer>();
configure(server);
@@ -1,13 +1,17 @@
using MQTTnet.Server;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet.Server;
using System;
namespace MQTTnet.AspNetCore
{
public class AspNetMqttServerOptionsBuilder : MqttServerOptionsBuilder
public sealed class AspNetMqttServerOptionsBuilder : MqttServerOptionsBuilder
{
public AspNetMqttServerOptionsBuilder(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public IServiceProvider ServiceProvider { get; }
@@ -1,15 +1,20 @@
using MQTTnet.Adapter;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Client.Tcp;
using MQTTnet.Client.Options;
using MQTTnet.Formatter;
using System;
using System.Net;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
namespace MQTTnet.AspNetCore.Client
{
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
public sealed class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
{
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
public IMqttChannelAdapter CreateClientAdapter(MqttClientOptions options, MqttPacketInspector packetInspector, IMqttNetLogger logger)
{
if (options == null) throw new ArgumentNullException(nameof(options));
@@ -19,9 +24,8 @@ namespace MQTTnet.AspNetCore.Client
{
var endpoint = new DnsEndPoint(tcpOptions.Server, tcpOptions.GetPort());
var tcpConnection = new TcpConnection(endpoint);
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, writer);
var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttBufferWriter(4096, 65535));
return new MqttConnectionContext(formatter, tcpConnection);
}
default:
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace MQTTnet.AspNetCore.Client.Tcp
@@ -1,4 +1,8 @@
using System.IO.Pipelines;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO.Pipelines;
namespace MQTTnet.AspNetCore.Client.Tcp
{
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.IO.Pipelines;
using System.Net.Sockets;
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO.Pipelines;
using System.Net.Sockets;
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
@@ -1,4 +1,8 @@
using Microsoft.AspNetCore.Connections;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Features;
using MQTTnet.Exceptions;
using System;
@@ -40,7 +44,7 @@ namespace MQTTnet.AspNetCore.Client.Tcp
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
_receiver = new SocketReceiver(_socket, PipeScheduler.ThreadPool);
}
#if NETCOREAPP3_1 || NET5_0
#if NETCOREAPP3_1_OR_GREATER
public override ValueTask DisposeAsync()
#else
public Task DisposeAsync()
@@ -53,7 +57,7 @@ namespace MQTTnet.AspNetCore.Client.Tcp
_socket?.Dispose();
#if NETCOREAPP3_1 || NET5_0
#if NETCOREAPP3_1_OR_GREATER
return base.DisposeAsync();
}
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Connections;
namespace MQTTnet.AspNetCore
{
public static class ConnectionBuilderExtensions
{
public static IConnectionBuilder UseMqtt(this IConnectionBuilder builder)
{
return builder.UseConnectionHandler<MqttConnectionHandler>();
}
}
}
@@ -1,11 +1,15 @@
using Microsoft.AspNetCore.Http;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
#if NETCOREAPP3_1
using System;
#endif
namespace MQTTnet.AspNetCore.Extensions
namespace MQTTnet.AspNetCore
{
public static class ConnectionRouteBuilderExtensions
{
@@ -1,5 +1,9 @@

#if NETCOREAPP3_1 || NET5_0
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETCOREAPP3_1_OR_GREATER
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
@@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Connections;
namespace MQTTnet.AspNetCore.Extensions
{
public static class ConnectionBuilderExtensions
{
public static IConnectionBuilder UseMqtt(this IConnectionBuilder builder)
{
return builder.UseConnectionHandler<MqttConnectionHandler>();
}
}
}
@@ -1,110 +0,0 @@
using System;
using System.Buffers;
using MQTTnet.Adapter;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
namespace MQTTnet.AspNetCore.Extensions
{
public static class ReaderExtensions
{
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 int headerLength, out var bodyLength))
{
return false;
}
if (copy.Length < bodyLength)
{
return false;
}
var bodySlice = copy.Slice(0, bodyLength);
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 ReadOnlyMemory<byte> GetMemory(this in ReadOnlySequence<byte> input)
{
if (input.IsSingleSegment)
{
return input.First;
}
// Should be rare
return input.ToArray();
}
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;
headerLength = 0;
bodyLength = 0;
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory().Span;
do
{
if (index == temp.Length)
{
return false;
}
encodedByte = temp[index];
index++;
value += (byte)(encodedByte & 127) * multiplier;
if (multiplier > 128 * 128 * 128)
{
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", temp.Slice(1, index).ToArray())}).");
}
multiplier *= 128;
} while ((encodedByte & 128) != 0);
input = input.Slice(index);
headerLength = index;
bodyLength = value;
return true;
}
}
}
@@ -1,36 +1,66 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<Product />
<Company />
<Authors />
<PackageId />
<LangVersion>7.2</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<AssemblyName>MQTTnet.AspNetCore</AssemblyName>
<RootNamespace>MQTTnet.AspNetCore</RootNamespace>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Company>The contributors of MQTTnet</Company>
<Product>MQTTnet</Product>
<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>
<Authors>The contributors of MQTTnet</Authors>
<PackageId>MQTTnet.AspNetCore</PackageId>
<SignAssembly>false</SignAssembly>
<DelaySign>false</DelaySign>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Copyright>Copyright (c) .NET Foundation and Contributors</Copyright>
<PackageProjectUrl>https://github.com/dotnet/MQTTnet</PackageProjectUrl>
<RepositoryUrl>https://github.com/dotnet/MQTTnet.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>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</PackageTags>
<NeutralLanguage>en-US</NeutralLanguage>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<PackageIcon>nuget.png</PackageIcon>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReleaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</PackageReleaseNotes>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1591;NETSDK1138</NoWarn>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' ">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\Images\nuget.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1' and '$(TargetFramework)' != 'net5.0' ">
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' ">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1' and '$(TargetFramework)' != 'net5.0' and '$(TargetFramework)' != 'net6.0' and '$(TargetFramework)' != 'net7.0' ">
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
</ItemGroup>
</Project>
@@ -1,90 +1,123 @@
using Microsoft.AspNetCore.Connections;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO.Pipelines;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Connections.Features;
using Microsoft.AspNetCore.Http.Features;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore.Client.Tcp;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
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;
using MQTTnet.Packets;
namespace MQTTnet.AspNetCore
{
public sealed class MqttConnectionContext : IMqttChannelAdapter
{
readonly ConnectionContext _connection;
readonly AsyncLock _writerLock = new AsyncLock();
readonly SpanBasedMqttPacketBodyReader _reader;
PipeReader _input;
PipeWriter _output;
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
{
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
Connection = connection ?? throw new ArgumentNullException(nameof(connection));
_connection = connection ?? throw new ArgumentNullException(nameof(connection));
if (Connection.Transport != null)
_input = connection.Transport.Input;
_output = connection.Transport.Output;
}
public long BytesReceived { get; private set; }
public long BytesSent { get; private set; }
public X509Certificate2 ClientCertificate
{
get
{
_input = Connection.Transport.Input;
_output = Connection.Transport.Output;
}
// mqtt over tcp
var tlsFeature = _connection.Features.Get<ITlsConnectionFeature>();
if (tlsFeature != null)
{
return tlsFeature.ClientCertificate;
}
_reader = new SpanBasedMqttPacketBodyReader();
// mqtt over websocket
var httpFeature = _connection.Features.Get<IHttpContextFeature>();
return httpFeature?.HttpContext?.Connection.ClientCertificate;
}
}
public string Endpoint
{
get
{
#if NETCOREAPP3_1
if (Connection?.RemoteEndPoint != null)
// mqtt over tcp
#if NETCOREAPP3_1_OR_GREATER
if (_connection.RemoteEndPoint != null)
{
return Connection.RemoteEndPoint.ToString();
return _connection.RemoteEndPoint.ToString();
}
#endif
var connection = Http?.HttpContext?.Connection;
if (connection == null)
// mqtt over websocket
var httpFeature = _connection.Features.Get<IHttpConnectionFeature>();
if (httpFeature?.RemoteIpAddress != null)
{
return Connection.ConnectionId;
return new IPEndPoint(httpFeature.RemoteIpAddress, httpFeature.RemotePort).ToString();
}
return $"{connection.RemoteIpAddress}:{connection.RemotePort}";
return null;
}
}
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 bool IsReadingPacket { get; private set; }
IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
public bool IsSecureConnection
{
if (Connection is TcpConnection tcp && !tcp.IsConnected)
get
{
// mqtt over tcp
var tlsFeature = _connection.Features.Get<ITlsConnectionFeature>();
if (tlsFeature != null)
{
return true;
}
// mqtt over websocket
var httpFeature = _connection.Features.Get<IHttpContextFeature>();
if (httpFeature?.HttpContext != null)
{
return httpFeature.HttpContext.Request.IsHttps;
}
return false;
}
}
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
public async Task ConnectAsync(CancellationToken cancellationToken)
{
if (_connection is TcpConnection tcp && !tcp.IsConnected)
{
await tcp.StartAsync().ConfigureAwait(false);
}
_input = Connection.Transport.Input;
_output = Connection.Transport.Output;
_input = _connection.Transport.Input;
_output = _connection.Transport.Output;
}
public Task DisconnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
public Task DisconnectAsync(CancellationToken cancellationToken)
{
_input?.Complete();
_output?.Complete();
@@ -92,16 +125,19 @@ namespace MQTTnet.AspNetCore
return Task.CompletedTask;
}
public async Task<MqttBasePacket> ReceivePacketAsync(CancellationToken cancellationToken)
public void Dispose()
{
var input = Connection.Transport.Input;
_writerLock.Dispose();
}
public async Task<MqttPacket> ReceivePacketAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
ReadResult readResult;
var readTask = input.ReadAsync(cancellationToken);
var readTask = _input.ReadAsync(cancellationToken);
if (readTask.IsCompleted)
{
readResult = readTask.Result;
@@ -120,7 +156,7 @@ namespace MQTTnet.AspNetCore
{
if (!buffer.IsEmpty)
{
if (PacketFormatterAdapter.TryDecode(_reader, buffer, out var packet, out consumed, out observed, out var received))
if (PacketFormatterAdapter.TryDecode(buffer, out var packet, out consumed, out observed, out var received))
{
BytesReceived += received;
return packet;
@@ -141,15 +177,15 @@ namespace MQTTnet.AspNetCore
// The buffer was sliced up to where it was consumed, so we can just advance to the start.
// We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data
// before yielding the read again.
input.AdvanceTo(consumed, observed);
_input.AdvanceTo(consumed, observed);
}
}
}
catch (Exception e)
catch (Exception exception)
{
// completing the channel makes sure that there is no more data read after a protocol error
_input?.Complete(e);
_output?.Complete(e);
_input?.Complete(exception);
_output?.Complete(exception);
throw;
}
finally
@@ -167,26 +203,46 @@ namespace MQTTnet.AspNetCore
BytesSent = 0;
}
public async Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
public async Task SendPacketAsync(MqttPacket packet, CancellationToken cancellationToken)
{
var formatter = PacketFormatterAdapter;
using (await _writerLock.WaitAsync(cancellationToken).ConfigureAwait(false))
using (await _writerLock.EnterAsync(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)
try
{
BytesSent += msg.Length;
}
var buffer = PacketFormatterAdapter.Encode(packet);
PacketFormatterAdapter.FreeBuffer();
if (buffer.Payload.Count == 0)
{
// zero copy
// https://github.com/dotnet/runtime/blob/e31ddfdc4f574b26231233dc10c9a9c402f40590/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs#L279
await _output.WriteAsync(buffer.Packet, cancellationToken).ConfigureAwait(false);
}
else
{
WritePacketBuffer(_output, buffer);
await _output.FlushAsync(cancellationToken).ConfigureAwait(false);
}
BytesSent += buffer.Length;
}
finally
{
PacketFormatterAdapter.Cleanup();
}
}
}
public void Dispose()
static void WritePacketBuffer(PipeWriter output, MqttPacketBuffer buffer)
{
// copy MqttPacketBuffer's Packet and Payload to the same buffer block of PipeWriter
// MqttPacket will be transmitted within the bounds of a WebSocket frame after PipeWriter.FlushAsync
var span = output.GetSpan(buffer.Length);
buffer.Packet.AsSpan().CopyTo(span);
buffer.Payload.AsSpan().CopyTo(span.Slice(buffer.Packet.Count));
output.Advance(buffer.Length);
}
}
}
}
@@ -1,15 +1,22 @@
using Microsoft.AspNetCore.Connections;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using MQTTnet.Adapter;
using MQTTnet.Server;
using System;
using System.Threading.Tasks;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
namespace MQTTnet.AspNetCore
{
public class MqttConnectionHandler : ConnectionHandler, IMqttServerAdapter
public sealed class MqttConnectionHandler : ConnectionHandler, IMqttServerAdapter
{
MqttServerOptions _serverOptions;
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public override async Task OnConnectedAsync(ConnectionContext connection)
@@ -20,9 +27,8 @@ namespace MQTTnet.AspNetCore
{
transferFormatFeature.ActiveFormat = TransferFormat.Binary;
}
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(writer);
var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(_serverOptions.WriterBufferSize, _serverOptions.WriterBufferSizeMax));
using (var adapter = new MqttConnectionContext(formatter, connection))
{
var clientHandler = ClientHandler;
@@ -33,8 +39,10 @@ namespace MQTTnet.AspNetCore
}
}
public Task StartAsync(IMqttServerOptions options)
public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger)
{
_serverOptions = options;
return Task.CompletedTask;
}
@@ -1,4 +1,7 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -9,19 +12,16 @@ using MQTTnet.Server;
namespace MQTTnet.AspNetCore
{
public class MqttHostedServer : MqttServer, IHostedService
public sealed class MqttHostedServer : MqttServer, IHostedService
{
private readonly IMqttServerOptions _options;
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
: base(adapters, logger)
public MqttHostedServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
: base(options, adapters, logger)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public Task StartAsync(CancellationToken cancellationToken)
{
_ = StartAsync(_options);
_ = StartAsync();
return Task.CompletedTask;
}
@@ -30,4 +30,4 @@ namespace MQTTnet.AspNetCore
return StopAsync();
}
}
}
}
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
@@ -1,28 +1,28 @@
using Microsoft.AspNetCore.Http;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.AspNetCore.Http;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Server;
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
using MQTTnet.Diagnostics;
namespace MQTTnet.AspNetCore
{
public sealed class MqttWebSocketServerAdapter : IMqttServerAdapter
{
readonly IMqttNetLogger _rootLogger;
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
{
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
}
IMqttNetLogger _logger = new MqttNetNullLogger();
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public Task StartAsync(IMqttServerOptions options)
public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
return Task.CompletedTask;
}
@@ -45,11 +45,10 @@ namespace MQTTnet.AspNetCore
var clientHandler = ClientHandler;
if (clientHandler != null)
{
var writer = new SpanBasedMqttPacketWriter();
var formatter = new MqttPacketFormatterAdapter(writer);
var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535));
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _rootLogger))
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _logger))
{
await clientHandler(channelAdapter).ConfigureAwait(false);
}
@@ -0,0 +1,140 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet.Adapter;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using System;
using System.Buffers;
using System.Linq;
using System.Runtime.InteropServices;
namespace MQTTnet.AspNetCore
{
public static class ReaderExtensions
{
public static bool TryDecode(this MqttPacketFormatterAdapter formatter,
in ReadOnlySequence<byte> input,
out MqttPacket 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;
}
if (!TryReadBodyLength(ref copy, out var headerLength, out var bodyLength))
{
return false;
}
var fixedHeader = copy.First.Span[0];
copy = copy.Slice(headerLength);
if (copy.Length < bodyLength)
{
return false;
}
var bodySlice = copy.Slice(0, bodyLength);
var bodySegment = GetArraySegment(ref bodySlice);
var receivedMqttPacket = new ReceivedMqttPacket(fixedHeader, bodySegment, headerLength + bodyLength);
if (formatter.ProtocolVersion == MqttProtocolVersion.Unknown)
{
formatter.DetectProtocolVersion(receivedMqttPacket);
}
packet = formatter.Decode(receivedMqttPacket);
consumed = bodySlice.End;
observed = bodySlice.End;
bytesRead = headerLength + bodyLength;
return true;
}
static ArraySegment<byte> GetArraySegment(ref ReadOnlySequence<byte> input)
{
if (input.IsSingleSegment && MemoryMarshal.TryGetArray(input.First, out var segment))
{
return segment;
}
// Should be rare
var array = input.ToArray();
return new ArraySegment<byte>(array);
}
static bool TryReadBodyLength(ref ReadOnlySequence<byte> input, out int headerLength, out int bodyLength)
{
var valueSequence = input.Slice(0, Math.Min(5, input.Length));
if (valueSequence.IsSingleSegment)
{
var valueSpan =
#if NET5_0_OR_GREATER
valueSequence.FirstSpan;
#else
valueSequence.First.Span;
#endif
return TryReadBodyLength(valueSpan, out headerLength, out bodyLength);
}
else
{
Span<byte> valueSpan = stackalloc byte[8];
valueSequence.CopyTo(valueSpan);
valueSpan = valueSpan.Slice(0, (int)valueSequence.Length);
return TryReadBodyLength(valueSpan, out headerLength, out bodyLength);
}
}
static bool TryReadBodyLength(ReadOnlySpan<byte> span, 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;
headerLength = 0;
bodyLength = 0;
do
{
if (index == span.Length)
{
return false;
}
encodedByte = span[index];
index++;
value += (byte)(encodedByte & 127) * multiplier;
if (multiplier > 128 * 128 * 128)
{
ThrowProtocolViolationException(span, index);
}
multiplier *= 128;
} while ((encodedByte & 128) != 0);
headerLength = index;
bodyLength = value;
return true;
}
static void ThrowProtocolViolationException(ReadOnlySpan<byte> valueSpan, int index)
{
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", valueSpan.Slice(1, index).ToArray())}).");
}
}
}
@@ -1,4 +1,8 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MQTTnet.Adapter;
@@ -6,11 +10,24 @@ using MQTTnet.Diagnostics;
using MQTTnet.Implementations;
using MQTTnet.Server;
namespace MQTTnet.AspNetCore.Extensions
namespace MQTTnet.AspNetCore
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, IMqttServerOptions options)
public static IServiceCollection AddMqttServer(this IServiceCollection serviceCollection, Action<MqttServerOptionsBuilder> configure = null)
{
if (serviceCollection is null)
{
throw new ArgumentNullException(nameof(serviceCollection));
}
serviceCollection.AddMqttConnectionHandler();
serviceCollection.AddHostedMqttServer(configure);
return serviceCollection;
}
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
@@ -21,13 +38,13 @@ namespace MQTTnet.AspNetCore.Extensions
return services;
}
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure = null)
{
services.AddSingleton<IMqttServerOptions>(s =>
services.AddSingleton(s =>
{
var builder = new MqttServerOptionsBuilder();
configure(builder);
return builder.Build();
var serverOptionsBuilder = new MqttServerOptionsBuilder();
configure?.Invoke(serverOptionsBuilder);
return serverOptionsBuilder.Build();
});
services.AddHostedMqttServer();
@@ -37,7 +54,7 @@ namespace MQTTnet.AspNetCore.Extensions
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
{
services.AddSingleton<IMqttServerOptions>(s =>
services.AddSingleton(s =>
{
var builder = new AspNetMqttServerOptionsBuilder(s);
configure(builder);
@@ -49,24 +66,14 @@ namespace MQTTnet.AspNetCore.Extensions
return services;
}
public static IServiceCollection AddHostedMqttServer<TOptions>(this IServiceCollection services)
where TOptions : class, IMqttServerOptions
static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
{
services.AddSingleton<IMqttServerOptions, TOptions>();
services.AddHostedMqttServer();
return services;
}
private static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
{
var logger = new MqttNetLogger();
var logger = new MqttNetEventLogger();
services.AddSingleton<IMqttNetLogger>(logger);
services.AddSingleton<MqttHostedServer>();
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
services.AddSingleton<IMqttServer>(s => s.GetService<MqttHostedServer>());
services.AddSingleton<MqttServer>(s => s.GetService<MqttHostedServer>());
return services;
}
@@ -1,129 +0,0 @@
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;
}
}
}
@@ -1,144 +0,0 @@
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,66 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Internal;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class AsyncLockBenchmark : BaseBenchmark
{
[Benchmark]
public async Task Synchronize_100_Tasks()
{
const int tasksCount = 100;
var tasks = new Task[tasksCount];
var asyncLock = new AsyncLock();
var globalI = 0;
for (var i = 0; i < tasksCount; i++)
{
tasks[i] = Task.Run(
async () =>
{
using (await asyncLock.EnterAsync().ConfigureAwait(false))
{
var localI = globalI;
await Task.Delay(5).ConfigureAwait(false); // Increase the chance for wrong data.
localI++;
globalI = localI;
}
});
}
await Task.WhenAll(tasks).ConfigureAwait(false);
if (globalI != tasksCount)
{
throw new Exception($"Code is broken ({globalI})!");
}
}
[Benchmark]
public async Task Wait_100_000_Times()
{
var asyncLock = new AsyncLock();
using (var cancellationToken = new CancellationTokenSource())
{
for (var i = 0; i < 100000; i++)
{
using (await asyncLock.EnterAsync(cancellationToken.Token).ConfigureAwait(false))
{
}
}
}
}
}
}
@@ -0,0 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Benchmarks
{
public abstract class BaseBenchmark
{
}
}
@@ -1,50 +1,26 @@
using BenchmarkDotNet.Attributes;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Internal;
using MQTTnet.Packets;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Threading;
using BenchmarkDotNet.Attributes;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Tests.Mockups;
namespace MQTTnet.Benchmarks
{
[MemoryDiagnoser]
public class ChannelAdapterBenchmark
public sealed class ChannelAdapterBenchmark : BaseBenchmark
{
private MqttChannelAdapter _channelAdapter;
private int _iterations;
private MemoryStream _stream;
private MqttPublishPacket _packet;
[GlobalSetup]
public void Setup()
{
_packet = new MqttPublishPacket
{
Topic = "A"
};
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
var serializedPacket = Join(serializer.Encode(_packet));
_iterations = 10000;
_stream = new MemoryStream(_iterations * serializedPacket.Length);
for (var i = 0; i < _iterations; i++)
{
_stream.Write(serializedPacket, 0, serializedPacket.Length);
}
_stream.Position = 0;
var channel = new TestMqttChannel(_stream);
_channelAdapter = new MqttChannelAdapter(channel, serializer, null, new MqttNetLogger());
}
MqttChannelAdapter _channelAdapter;
int _iterations;
MqttPublishPacket _packet;
MemoryStream _stream;
[Benchmark]
public void Receive_10000_Messages()
@@ -72,7 +48,35 @@ namespace MQTTnet.Benchmarks
_stream.Position = 0;
}
private static byte[] Join(params ArraySegment<byte>[] chunks)
[GlobalSetup]
public void Setup()
{
_packet = new MqttPublishPacket
{
Topic = "A"
};
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var serializedPacket = Join(serializer.Encode(_packet).Join());
_iterations = 10000;
_stream = new MemoryStream(_iterations * serializedPacket.Length);
for (var i = 0; i < _iterations; i++)
{
_stream.Write(serializedPacket, 0, serializedPacket.Length);
}
_stream.Position = 0;
var channel = new MemoryMqttChannel(_stream);
_channelAdapter = new MqttChannelAdapter(channel, serializer, null, new MqttNetEventLogger());
}
static byte[] Join(params ArraySegment<byte>[] chunks)
{
var buffer = new MemoryStream();
foreach (var chunk in chunks)
@@ -83,4 +87,4 @@ namespace MQTTnet.Benchmarks
return buffer.ToArray();
}
}
}
}
@@ -0,0 +1,91 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Diagnostics;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter]
[MemoryDiagnoser]
public class LoggerBenchmark : BaseBenchmark
{
MqttNetNullLogger _nullLogger;
MqttNetSourceLogger _sourceNullLogger;
MqttNetEventLogger _eventLogger;
MqttNetSourceLogger _sourceEventLogger;
MqttNetEventLogger _eventLoggerNoListener;
MqttNetSourceLogger _sourceEventLoggerNoListener;
bool _useHandler;
[GlobalSetup]
public void Setup()
{
_nullLogger = new MqttNetNullLogger();
_sourceNullLogger = _nullLogger.WithSource("Source");
_eventLogger = new MqttNetEventLogger();
_eventLogger.LogMessagePublished += OnLogMessagePublished;
_sourceEventLogger = _eventLogger.WithSource("Source");
_eventLoggerNoListener = new MqttNetEventLogger();
_sourceEventLoggerNoListener = _eventLoggerNoListener.WithSource("Source");
}
void OnLogMessagePublished(object sender, MqttNetLogMessagePublishedEventArgs eventArgs)
{
if (_useHandler)
{
eventArgs.LogMessage.ToString();
}
}
[Benchmark]
public void Log_10000_Messages_No_Listener()
{
_useHandler = false;
for (var i = 0; i < 10000; i++)
{
_sourceEventLoggerNoListener.Verbose("test log message {0}", "parameter");
}
}
[Benchmark]
public void Log_10000_Messages_With_To_String()
{
_useHandler = true;
for (var i = 0; i < 10000; i++)
{
_sourceEventLogger.Verbose("test log message {0}", "parameter");
}
}
[Benchmark]
public void Log_10000_Messages_Without_To_String()
{
_useHandler = false;
for (var i = 0; i < 10000; i++)
{
_sourceEventLogger.Verbose("test log message {0}", "parameter");
}
}
[Benchmark]
public void Log_10000_Messages_With_NullLogger()
{
for (var i = 0; i < 10000; i++)
{
_sourceNullLogger.Verbose("test log message {0}", "parameter");
}
}
}
}
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputType>Exe</OutputType>
<DebugType>Full</DebugType>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<LangVersion>7.2</LangVersion>
<IsPackable>false</IsPackable>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<NoWarn>1591;NETSDK1138</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="System.IO.Pipelines" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="System.IO.Pipelines" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="System.IO.Pipelines" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
<ProjectReference Include="..\MQTTnet.Tests\MQTTnet.Tests.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,40 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using System;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class MemoryCopyBenchmark
{
const int max_length = 1024 * 8;
private byte[] source;
private byte[] target;
[Params(64 - 1, 128 - 1, 256 - 1, 512 - 1, 1024 - 1, 2048 - 1, 5096 - 1)]
public int Length { get; set; }
[GlobalSetup]
public void Setup()
{
source = new byte[max_length];
target = new byte[max_length];
}
[Benchmark(Baseline = true)]
public void Array_Copy()
{
Array.Copy(source, 0, target, 0, Length);
}
[Benchmark]
public void Memory_Copy()
{
MQTTnet.Internal.MqttMemoryHelper.Copy(source, 0, target, 0, Length);
}
}
}
@@ -0,0 +1,233 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using MQTTnet.Client;
using MQTTnet.Server;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MQTTnet.Benchmarks
{
[MemoryDiagnoser]
public class MessageDeliveryBenchmark : BaseBenchmark
{
List<MqttApplicationMessage> _topicPublishMessages;
[Params(1, 5)]
public int NumTopicsPerPublisher;
[Params(1000, 10000)]
public int NumPublishers;
[Params(10)]
public int NumSubscribers;
[Params(5, 10, 20, 50)]
public int NumSubscribedTopicsPerSubscriber;
object _lockMsgCount;
int _messagesReceivedCount;
int _messagesExpectedCount;
CancellationTokenSource _cancellationTokenSource;
MqttServer _mqttServer;
List<IMqttClient> _mqttSubscriberClients;
Dictionary<string, IMqttClient> _mqttPublisherClientsByPublisherName;
Dictionary<string, List<string>> _topicsByPublisher;
Dictionary<string, string> _publisherByTopic;
List<string> _allSubscribedTopics; // Keep track of the subset of topics that are subscribed
[GlobalSetup]
public void Setup()
{
_lockMsgCount = new object();
Dictionary<string, List<string>> singleWildcardTopicsByPublisher;
Dictionary<string, List<string>> multiWildcardTopicsByPublisher;
TopicGenerator.Generate(NumPublishers, NumTopicsPerPublisher, out _topicsByPublisher, out singleWildcardTopicsByPublisher, out multiWildcardTopicsByPublisher);
var topics = _topicsByPublisher.First().Value;
_topicPublishMessages = new List<MqttApplicationMessage>();
// Prepare messages, same for each publisher
foreach (var topic in topics)
{
var message = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 })
.Build();
_topicPublishMessages.Add(message);
}
// Create server
var factory = new MqttFactory();
var serverOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
_mqttServer = factory.CreateMqttServer(serverOptions);
_mqttServer.StartAsync().GetAwaiter().GetResult();
// Create publisher clients
_mqttPublisherClientsByPublisherName = new Dictionary<string, IMqttClient>();
foreach (var pt in _topicsByPublisher)
{
var publisherName = pt.Key;
var mqttClient = factory.CreateMqttClient();
var publisherOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost")
.WithClientId(publisherName)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(30))
.Build();
mqttClient.ConnectAsync(publisherOptions).GetAwaiter().GetResult();
_mqttPublisherClientsByPublisherName.Add(publisherName, mqttClient);
}
// Create subscriber clients
_mqttSubscriberClients = new List<IMqttClient>();
for (var i = 0; i < NumSubscribers; i++)
{
var mqttSubscriberClient = factory.CreateMqttClient();
_mqttSubscriberClients.Add(mqttSubscriberClient);
var subscriberOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost")
.WithClientId("subscriber" + i)
.Build();
mqttSubscriberClient.ApplicationMessageReceivedAsync += r =>
{
// count messages and signal cancellation when expected message count is reached
lock (_lockMsgCount)
{
++_messagesReceivedCount;
if (_messagesReceivedCount == _messagesExpectedCount)
{
_cancellationTokenSource.Cancel();
}
}
return Task.CompletedTask;
};
mqttSubscriberClient.ConnectAsync(subscriberOptions).GetAwaiter().GetResult();
}
List<string> allTopics = new List<string>();
_publisherByTopic = new Dictionary<string, string>();
foreach (var t in _topicsByPublisher)
{
foreach (var topic in t.Value)
{
_publisherByTopic.Add(topic, t.Key);
allTopics.Add(topic);
}
}
// Subscribe to NumSubscribedTopics topics spread across all topics
_allSubscribedTopics = new List<string>();
var totalNumTopics = NumPublishers * NumTopicsPerPublisher;
int topicIndexStep = totalNumTopics / (NumSubscribedTopicsPerSubscriber * NumSubscribers);
if (topicIndexStep * NumSubscribedTopicsPerSubscriber * NumSubscribers != totalNumTopics)
{
throw new System.Exception(
String.Format("The total number of topics must be divisible by the number of subscribed topics across all subscribers. Total number of topics: {0}, topic step: {1}",
totalNumTopics, topicIndexStep
));
}
var topicIndex = 0;
foreach (var mqttSubscriber in _mqttSubscriberClients)
{
for (var i = 0; i < NumSubscribedTopicsPerSubscriber; ++i, topicIndex += topicIndexStep)
{
var topic = allTopics[topicIndex];
_allSubscribedTopics.Add(topic);
var subOptions = new Client.MqttClientSubscribeOptionsBuilder().WithTopicFilter(
new Packets.MqttTopicFilter() { Topic = topic })
.Build();
mqttSubscriber.SubscribeAsync(subOptions).GetAwaiter().GetResult();
}
}
Task.Delay(1000).GetAwaiter().GetResult();
}
/// <summary>
/// Publish messages and wait for messages sent to subscribers
/// </summary>
[Benchmark]
public void DeliverMessages()
{
// There should be one message received per publish for each subscribed topic
_messagesExpectedCount = NumSubscribedTopicsPerSubscriber * NumSubscribers;
// Loop for a while and exchange messages
_messagesReceivedCount = 0;
_cancellationTokenSource = new CancellationTokenSource();
// same payload for all messages
var payload = new byte[] { 1, 2, 3, 4 };
var tasks = new List<Task>();
// publish a message for each subscribed topic
foreach (var topic in _allSubscribedTopics)
{
var message = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payload)
.Build();
// pick the correct publisher
var publisherName = _publisherByTopic[topic];
var publisherClient = _mqttPublisherClientsByPublisherName[publisherName];
_ = publisherClient.PublishAsync(message);
}
// Wait one message per publish to be received by subscriber (in the subscriber's application message handler)
try
{
Task.Delay(30000, _cancellationTokenSource.Token).GetAwaiter().GetResult();
}
catch
{
}
_cancellationTokenSource.Dispose();
if (_messagesReceivedCount < _messagesExpectedCount)
{
throw new Exception(string.Format("Messages Received Count mismatch, expected {0}, received {1}", _messagesExpectedCount, _messagesReceivedCount));
}
}
[GlobalCleanup]
public void Cleanup()
{
foreach (var mp in _mqttPublisherClientsByPublisherName)
{
var mqttPublisherClient = mp.Value;
mqttPublisherClient.DisconnectAsync().GetAwaiter().GetResult();
mqttPublisherClient.Dispose();
}
_mqttPublisherClientsByPublisherName.Clear();
foreach (var mqttSubscriber in _mqttSubscriberClients)
{
mqttSubscriber.DisconnectAsync().GetAwaiter().GetResult();
mqttSubscriber.Dispose();
}
_mqttSubscriberClients.Clear();
_mqttServer.StopAsync().GetAwaiter().GetResult();
_mqttServer.Dispose();
_mqttServer = null;
}
}
}
@@ -1,29 +1,33 @@
using BenchmarkDotNet.Attributes;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Server;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net461)]
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class MessageProcessingBenchmark
public class MessageProcessingBenchmark : BaseBenchmark
{
private IMqttServer _mqttServer;
private IMqttClient _mqttClient;
private MqttApplicationMessage _message;
MqttServer _mqttServer;
IMqttClient _mqttClient;
MqttApplicationMessage _message;
[GlobalSetup]
public void Setup()
{
var serverOptions = new MqttServerOptionsBuilder().Build();
var factory = new MqttFactory();
_mqttServer = factory.CreateMqttServer();
_mqttServer = factory.CreateMqttServer(serverOptions);
_mqttClient = factory.CreateMqttClient();
var serverOptions = new MqttServerOptionsBuilder().Build();
_mqttServer.StartAsync(serverOptions).GetAwaiter().GetResult();
_mqttServer.StartAsync().GetAwaiter().GetResult();
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost").Build();
@@ -1,25 +1,25 @@
using BenchmarkDotNet.Attributes;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Client;
using MQTTnet.AspNetCore;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using MQTTnet.Server;
using MQTTnet.Diagnostics;
using MQTTnet.AspNetCore.Client;
using MQTTnet.AspNetCore.Extensions;
using MQTTnet.Client.Options;
using MQTTnet.AspNetCore;
using MQTTnet.Diagnostics;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class MessageProcessingMqttConnectionContextBenchmark
public class MessageProcessingMqttConnectionContextBenchmark : BaseBenchmark
{
private IWebHost _host;
private IMqttClient _mqttClient;
private MqttApplicationMessage _message;
IWebHost _host;
IMqttClient _mqttClient;
MqttApplicationMessage _message;
[GlobalSetup]
public void Setup()
@@ -39,7 +39,7 @@ namespace MQTTnet.Benchmarks
.Build();
var factory = new MqttFactory();
_mqttClient = factory.CreateMqttClient(new MqttNetLogger(), new MqttClientConnectionContextFactory());
_mqttClient = factory.CreateMqttClient(new MqttNetEventLogger(), new MqttClientConnectionContextFactory());
_host.StartAsync().GetAwaiter().GetResult();
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Formatter;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class MqttBufferReaderBenchmark
{
byte[] _buffer;
int _bufferLength;
[GlobalSetup]
public void GlobalSetup()
{
var writer = new MqttBufferWriter(1024, 1024);
writer.WriteString("hgfjkdfkjlghfdjghdfljkdfhgdlkjfshgsldkfjghsdflkjghdsflkjhrstiuoghlkfjbhnfbutghjoiöjhklötnbhtroliöuhbjntluiobkjzbhtdrlskbhtruhjkfthgbkftgjhgfiklhotriuöhbjtrsioöbtrsötrhträhtrühjtriüoätrhjtsrölbktrbnhtrulöbionhströloubinströoliubhnsöotrunbtöroisntröointröioujhgötiohjgötorshjnbgtöorihbnjtröoihbjntröobntröoibntrjhötrohjbtröoihntröoibnrtoiöbtrjnboöitrhjtnriohötrhjtöroihjtroöihjtroösibntsroönbotöirsbntöoihjntröoihntroöbtrboöitrnhoöitrhjntröoishbnjtröosbhtröbntriohjtröoijtöoitbjöotibjnhöotirhbjntroöibhnjrtoöibnhtroöibnhtörsbnhtöoirbnhtöroibntoörhjnbträöbtrbträbtrbtirbätrsibohjntrsöiobthnjiohjsrtoib");
_buffer = writer.GetBuffer();
_bufferLength = writer.Length;
}
[Benchmark]
public void Use_Span()
{
var span = _buffer.AsSpan(0, _bufferLength);
Encoding.UTF8.GetString(span);
}
[Benchmark]
public void Use_Encoding()
{
Encoding.UTF8.GetString(_buffer, 0, _bufferLength);
}
}
}
@@ -0,0 +1,96 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Formatter;
using MQTTnet.Tests.Mockups;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class MqttPacketReaderWriterBenchmark : BaseBenchmark
{
readonly byte[] _demoPayload = new byte[1024];
byte[] _readPayload;
[GlobalCleanup]
public void GlobalCleanup()
{
}
[GlobalSetup]
public void GlobalSetup()
{
TestEnvironment.EnableLogger = false;
var writer = new MqttBufferWriter(4096, 65535);
writer.WriteString("A relative short string.");
writer.WriteBinaryData(_demoPayload);
writer.WriteByte(0x01);
writer.WriteByte(0x02);
writer.WriteVariableByteInteger(5647382);
writer.WriteString("A relative short string.");
writer.WriteVariableByteInteger(8574489);
writer.WriteBinaryData(_demoPayload);
writer.WriteByte(2);
writer.WriteByte(0x02);
writer.WriteString("fjgffiogfhgfhoihgoireghreghreguhreguireoghreouighreouighreughreguiorehreuiohruiorehreuioghreug");
writer.WriteBinaryData(_demoPayload);
_readPayload = new ArraySegment<byte>(writer.GetBuffer(), 0, writer.Length).ToArray();
}
[Benchmark]
public void Read_100_000_Messages()
{
var reader = new MqttBufferReader();
reader.SetBuffer(_readPayload, 0, _readPayload.Length);
for (var i = 0; i < 100000; i++)
{
reader.Seek(0);
reader.ReadString();
reader.ReadBinaryData();
reader.ReadByte();
reader.ReadByte();
reader.ReadVariableByteInteger();
reader.ReadString();
reader.ReadVariableByteInteger();
reader.ReadBinaryData();
reader.ReadByte();
reader.ReadByte();
reader.ReadString();
reader.ReadBinaryData();
}
}
[Benchmark]
public void Write_100_000_Messages()
{
var writer = new MqttBufferWriter(4096, 65535);
for (var i = 0; i < 100000; i++)
{
writer.WriteString("A relative short string.");
writer.WriteByte(0x01);
writer.WriteByte(0x02);
writer.WriteVariableByteInteger(5647382);
writer.WriteString("A relative short string.");
writer.WriteVariableByteInteger(8574589);
writer.WriteBinaryData(_demoPayload);
writer.WriteByte(2);
writer.WriteByte(0x02);
writer.WriteString("fjgffiogfhgfhoihgoireghreghreguhreguireoghreouighreouighreughreguiorehreuiohruiorehreuioghreug");
writer.WriteBinaryData(_demoPayload);
writer.Reset(0);
}
}
}
}
@@ -1,26 +1,33 @@
using BenchmarkDotNet.Attributes;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using BenchmarkDotNet.Attributes;
using MQTTnet.Channel;
using MQTTnet.Client.Options;
using MQTTnet.Diagnostics;
using MQTTnet.Implementations;
using MQTTnet.Server;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Jobs;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class MqttTcpChannelBenchmark
public class MqttTcpChannelBenchmark : BaseBenchmark
{
private IMqttServer _mqttServer;
private IMqttChannel _serverChannel;
private IMqttChannel _clientChannel;
MqttServer _mqttServer;
IMqttChannel _serverChannel;
IMqttChannel _clientChannel;
[GlobalSetup]
public void Setup()
{
var factory = new MqttFactory();
var tcpServer = new MqttTcpServerAdapter(new MqttNetLogger());
var tcpServer = new MqttTcpServerAdapter();
tcpServer.ClientHandler += args =>
{
_serverChannel =
@@ -31,10 +38,11 @@ namespace MQTTnet.Benchmarks
return Task.CompletedTask;
};
_mqttServer = factory.CreateMqttServer(new[] { tcpServer }, new MqttNetLogger());
var serverOptions = new MqttServerOptionsBuilder().Build();
_mqttServer.StartAsync(serverOptions).GetAwaiter().GetResult();
_mqttServer = factory.CreateMqttServer(serverOptions, new[] { tcpServer }, new MqttNetEventLogger());
_mqttServer.StartAsync().GetAwaiter().GetResult();
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost").Build();
@@ -54,7 +62,7 @@ namespace MQTTnet.Benchmarks
await Task.WhenAll(WriteAsync(iterations, size), ReadAsync(iterations, size));
}
private async Task ReadAsync(int iterations, int size)
async Task ReadAsync(int iterations, int size)
{
await Task.Yield();
@@ -63,19 +71,21 @@ namespace MQTTnet.Benchmarks
while (read < expected)
{
var readresult = await _clientChannel.ReadAsync(new byte[size], 0, size, CancellationToken.None).ConfigureAwait(false);
read += readresult;
var readResult = await _clientChannel.ReadAsync(new byte[size], 0, size, CancellationToken.None).ConfigureAwait(false);
read += readResult;
}
}
private async Task WriteAsync(int iterations, int size)
async Task WriteAsync(int iterations, int size)
{
await Task.Yield();
var buffer = new ArraySegment<byte>(new byte[size]);
for (var i = 0; i < iterations; i++)
{
await _serverChannel.WriteAsync(new byte[size], 0, size, CancellationToken.None).ConfigureAwait(false);
await _serverChannel.WriteAsync(buffer, true, CancellationToken.None).ConfigureAwait(false);
}
}
}
}
}
+142
View File
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Running;
using MQTTnet.Diagnostics;
namespace MQTTnet.Benchmarks
{
public static class Program
{
static int _selectedBenchmarkIndex;
static List<Type> _benchmarks;
public static void Main(string[] arguments)
{
_benchmarks = CollectBenchmarks();
HandleArguments(arguments);
while (true)
{
RenderMenu();
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.DownArrow)
{
_selectedBenchmarkIndex++;
if (_selectedBenchmarkIndex > _benchmarks.Count - 1)
{
_selectedBenchmarkIndex = 0;
}
}
else if (key.Key == ConsoleKey.UpArrow)
{
_selectedBenchmarkIndex--;
if (_selectedBenchmarkIndex < 0)
{
_selectedBenchmarkIndex = _benchmarks.Count - 1;
}
}
else if (key.Key == ConsoleKey.Escape)
{
Environment.Exit(0);
}
else if (key.Key == ConsoleKey.Enter)
{
break;
}
}
BenchmarkRunner.Run(_benchmarks[_selectedBenchmarkIndex]);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
static List<Type> CollectBenchmarks()
{
var benchmarks = new List<Type>();
var types = typeof(Program).Assembly.GetExportedTypes();
foreach (var type in types)
{
if (typeof(BaseBenchmark).IsAssignableFrom(type))
{
if (type != typeof(BaseBenchmark))
{
benchmarks.Add(type);
}
}
}
return benchmarks.OrderBy(b => b.Name).ToList();
}
static void HandleArguments(string[] arguments)
{
if (arguments.Length == 0)
{
return;
}
// Allow for preselection to avoid developer frustration.
if (int.TryParse(arguments[0], out var benchmarkIndex))
{
_selectedBenchmarkIndex = benchmarkIndex;
return;
}
_selectedBenchmarkIndex = _benchmarks.FindIndex(b => b.Name.Equals(arguments[0]));
if (_selectedBenchmarkIndex < 0)
{
_selectedBenchmarkIndex = 0;
}
if (_selectedBenchmarkIndex > _benchmarks.Count - 1)
{
_selectedBenchmarkIndex = _benchmarks.Count - 1;
}
}
static void RenderMenu()
{
Console.Clear();
Console.WriteLine($"MQTTnet - Benchmarks ({TargetFrameworkProvider.TargetFramework})");
Console.WriteLine("-----------------------------------------------");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Press arrow keys for benchmark selection");
Console.WriteLine("Press Enter for benchmark execution");
Console.WriteLine("Press Esc for exit");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
for (var index = 0; index < _benchmarks.Count; index++)
{
var benchmark = _benchmarks[index];
if (_selectedBenchmarkIndex == index)
{
Console.Write("-> ");
}
else
{
Console.Write(" ");
}
Console.WriteLine(benchmark.Name);
}
Console.WriteLine();
}
}
}
@@ -0,0 +1,240 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using System;
using System.Buffers;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Threading.Tasks;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class ReaderExtensionsBenchmark
{
MqttPacketFormatterAdapter mqttPacketFormatter;
MemoryStream stream;
[GlobalSetup]
public void GlobalSetup()
{
mqttPacketFormatter = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var mqttMessage = new MqttApplicationMessageBuilder()
.WithTopic("topic")
.WithPayload(new byte[10 * 1024])
.Build();
var packet = MqttPacketFactories.Publish.Create(mqttMessage);
var buffer = mqttPacketFormatter.Encode(packet);
stream = new MemoryStream();
stream.Write(buffer.Packet);
stream.Write(buffer.Payload);
mqttPacketFormatter.Cleanup();
}
[Benchmark(Baseline = true)]
public async Task Before()
{
stream.Position = 0;
var input = PipeReader.Create(stream);
while (true)
{
ReadResult readResult;
var readTask = input.ReadAsync();
if (readTask.IsCompleted)
{
readResult = readTask.Result;
}
else
{
readResult = await readTask.ConfigureAwait(false);
}
var buffer = readResult.Buffer;
var consumed = buffer.Start;
var observed = buffer.Start;
try
{
if (!buffer.IsEmpty)
{
if (ReaderExtensions_Before.TryDecode(mqttPacketFormatter, buffer, out var packet, out consumed, out observed, out var received))
{
break;
}
}
else if (readResult.IsCompleted)
{
throw new MqttCommunicationException("Connection Aborted");
}
}
finally
{
// The buffer was sliced up to where it was consumed, so we can just advance to the start.
// We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data
// before yielding the read again.
input.AdvanceTo(consumed, observed);
}
}
}
[Benchmark]
public async Task After()
{
stream.Position = 0;
var input = PipeReader.Create(stream);
while (true)
{
ReadResult readResult;
var readTask = input.ReadAsync();
if (readTask.IsCompleted)
{
readResult = readTask.Result;
}
else
{
readResult = await readTask.ConfigureAwait(false);
}
var buffer = readResult.Buffer;
var consumed = buffer.Start;
var observed = buffer.Start;
try
{
if (!buffer.IsEmpty)
{
if (ReaderExtensions.TryDecode(mqttPacketFormatter, buffer, out var packet, out consumed, out observed, out var received))
{
break;
}
}
else if (readResult.IsCompleted)
{
throw new MqttCommunicationException("Connection Aborted");
}
}
finally
{
// The buffer was sliced up to where it was consumed, so we can just advance to the start.
// We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data
// before yielding the read again.
input.AdvanceTo(consumed, observed);
}
}
}
public static class ReaderExtensions_Before
{
public static bool TryDecode(MqttPacketFormatterAdapter formatter,
in ReadOnlySequence<byte> input,
out MqttPacket 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 int headerLength, out var bodyLength))
{
return false;
}
if (copy.Length < bodyLength)
{
return false;
}
var bodySlice = copy.Slice(0, bodyLength);
var buffer = GetMemory(bodySlice).ToArray();
var receivedMqttPacket = new ReceivedMqttPacket(fixedHeader, new ArraySegment<byte>(buffer, 0, buffer.Length), 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;
}
static ReadOnlyMemory<byte> GetMemory(in ReadOnlySequence<byte> input)
{
if (input.IsSingleSegment)
{
return input.First;
}
// Should be rare
return input.ToArray();
}
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;
headerLength = 0;
bodyLength = 0;
var temp = GetMemory(input.Slice(0, Math.Min(5, input.Length))).Span;
do
{
if (index == temp.Length)
{
return false;
}
encodedByte = temp[index];
index++;
value += (byte)(encodedByte & 127) * multiplier;
if (multiplier > 128 * 128 * 128)
{
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", temp.Slice(1, index).ToArray())}).");
}
multiplier *= 128;
} while ((encodedByte & 128) != 0);
input = input.Slice(index);
headerLength = index;
bodyLength = value;
return true;
}
}
}
}
@@ -0,0 +1,30 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Tests.Mockups;
using MQTTnet.Tests.Server;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class RoundtripProcessingBenchmark : BaseBenchmark
{
[GlobalSetup]
public void GlobalSetup()
{
TestEnvironment.EnableLogger = false;
}
[GlobalCleanup]
public void GlobalCleanup()
{
}
[Benchmark]
public void Handle_100_000_Messages_In_Receiving_Client()
{
new Load_Tests().Handle_100_000_Messages_In_Receiving_Client().GetAwaiter().GetResult();
}
}
}
@@ -0,0 +1,68 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Formatter;
using System;
using System.IO;
using System.IO.Pipelines;
using System.Threading.Tasks;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class SendPacketAsyncBenchmark : BaseBenchmark
{
MemoryStream stream;
MqttPacketBuffer buffer;
[GlobalSetup]
public void GlobalSetup()
{
stream = new MemoryStream(1024);
var packet = new ArraySegment<byte>(new byte[10]);
buffer = new MqttPacketBuffer(packet);
}
[Benchmark(Baseline = true)]
public async ValueTask Before()
{
stream.Position = 0;
var output = PipeWriter.Create(stream);
WritePacketBuffer(output, buffer);
await output.FlushAsync();
}
[Benchmark]
public async ValueTask After()
{
stream.Position = 0;
var output = PipeWriter.Create(stream);
if (buffer.Payload.Count == 0)
{
await output.WriteAsync(buffer.Packet).ConfigureAwait(false);
}
else
{
WritePacketBuffer(output, buffer);
await output.FlushAsync().ConfigureAwait(false);
}
}
static void WritePacketBuffer(PipeWriter output, MqttPacketBuffer buffer)
{
// copy MqttPacketBuffer's Packet and Payload to the same buffer block of PipeWriter
// MqttPacket will be transmitted within the bounds of a WebSocket frame after PipeWriter.FlushAsync
var span = output.GetSpan(buffer.Length);
buffer.Packet.AsSpan().CopyTo(span);
buffer.Payload.AsSpan().CopyTo(span.Slice(buffer.Packet.Count));
output.Advance(buffer.Length);
}
}
}
@@ -1,4 +1,8 @@
using BenchmarkDotNet.Attributes;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using MQTTnet.Packets;
using System;
using System.Security.Cryptography.X509Certificates;
@@ -13,25 +17,27 @@ using MQTTnet.Diagnostics;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net461)]
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter]
[MemoryDiagnoser]
public class SerializerBenchmark
public class SerializerBenchmark : BaseBenchmark
{
private MqttBasePacket _packet;
private ArraySegment<byte> _serializedPacket;
private IMqttPacketFormatter _serializer;
MqttPacket _packet;
ArraySegment<byte> _serializedPacket;
IMqttPacketFormatter _serializer;
MqttBufferWriter _bufferWriter;
[GlobalSetup]
public void Setup()
public void GlobalSetup()
{
_packet = new MqttPublishPacket
{
Topic = "A"
};
_serializer = new MqttV311PacketFormatter(new MqttPacketWriter());
_serializedPacket = _serializer.Encode(_packet);
_bufferWriter = new MqttBufferWriter(4096, 65535);
_serializer = new MqttV3PacketFormatter(_bufferWriter, MqttProtocolVersion.V311);
_serializedPacket = _serializer.Encode(_packet).Join();
}
[Benchmark]
@@ -40,7 +46,7 @@ namespace MQTTnet.Benchmarks
for (var i = 0; i < 10000; i++)
{
_serializer.Encode(_packet);
_serializer.FreeBuffer();
_bufferWriter.Cleanup();
}
}
@@ -48,8 +54,7 @@ namespace MQTTnet.Benchmarks
public void Deserialize_10000_Messages()
{
var channel = new BenchmarkMqttChannel(_serializedPacket);
var fixedHeader = new byte[2];
var reader = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(new MqttPacketWriter()), null, new MqttNetLogger());
var reader = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger());
for (var i = 0; i < 10000; i++)
{
@@ -59,10 +64,10 @@ namespace MQTTnet.Benchmarks
}
}
private class BenchmarkMqttChannel : IMqttChannel
class BenchmarkMqttChannel : IMqttChannel
{
private readonly ArraySegment<byte> _buffer;
private int _position;
readonly ArraySegment<byte> _buffer;
int _position;
public BenchmarkMqttChannel(ArraySegment<byte> buffer)
{
@@ -99,7 +104,7 @@ namespace MQTTnet.Benchmarks
return Task.FromResult(count);
}
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
public Task WriteAsync(ArraySegment<byte> buffer, bool isEndOfPacket, CancellationToken cancellationToken)
{
throw new NotSupportedException();
}
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Tests.Mockups;
using MQTTnet.Tests.Server;
namespace MQTTnet.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter, RankColumn]
[MemoryDiagnoser]
public class ServerProcessingBenchmark : BaseBenchmark
{
[GlobalSetup]
public void GlobalSetup()
{
TestEnvironment.EnableLogger = false;
}
[GlobalCleanup]
public void GlobalCleanup()
{
}
[Benchmark]
public void Handle_100_000_Messages_In_Server_MqttClient()
{
new Load_Tests().Handle_100_000_Messages_In_Server().GetAwaiter().GetResult();
}
//[Benchmark]
public void Handle_100_000_Messages_In_Server_LowLevelMqttClient()
{
new Load_Tests().Handle_100_000_Messages_In_Low_Level_Client().GetAwaiter().GetResult();
}
}
}
@@ -0,0 +1,66 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MQTTnet.Client;
using MQTTnet.Server;
using System.Collections.Generic;
using System.Linq;
namespace MQTTnet.Benchmarks
{
[MemoryDiagnoser]
public class SubscribeBenchmark : BaseBenchmark
{
MqttServer _mqttServer;
IMqttClient _mqttClient;
const int NumPublishers = 1;
const int NumTopicsPerPublisher = 10000;
List<string> _topics;
[GlobalSetup]
public void Setup()
{
TopicGenerator.Generate(NumPublishers, NumTopicsPerPublisher, out var topicsByPublisher, out var singleWildcardTopicsByPublisher, out var multiWildcardTopicsByPublisher);
_topics = topicsByPublisher.Values.First();
var serverOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();
var factory = new MqttFactory();
_mqttServer = factory.CreateMqttServer(serverOptions);
_mqttClient = factory.CreateMqttClient();
_mqttServer.StartAsync().GetAwaiter().GetResult();
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost").Build();
_mqttClient.ConnectAsync(clientOptions).GetAwaiter().GetResult();
}
[GlobalCleanup]
public void Cleanup()
{
_mqttClient.DisconnectAsync().GetAwaiter().GetResult();
_mqttServer.StopAsync().GetAwaiter().GetResult();
_mqttServer.Dispose();
}
[Benchmark]
public void Subscribe_10000_Topics()
{
foreach (var topic in _topics)
{
var subscribeOptions = new MqttClientSubscribeOptionsBuilder()
.WithTopicFilter(topic, Protocol.MqttQualityOfServiceLevel.AtMostOnce)
.Build();
_mqttClient.SubscribeAsync(subscribeOptions).GetAwaiter().GetResult();
}
}
}
}

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