Compare commits

...
602 Commits
Author SHA1 Message Date
Christian Kratky efef23e3f5 Merge branch 'develop' 2019-05-06 20:24:12 +02:00
Christian Kratky 53ab2ac140 Add Wiki Code. 2019-05-06 20:22:41 +02:00
Christian Kratky 2ecbd83d06 Add UnitTests. 2019-05-06 20:22:20 +02:00
Christian Kratky a278b6189b Refactor empty payload detection for retained messages. 2019-05-01 19:41:34 +02:00
Christian Kratky cdbdfdec6d Add UnitTests. 2019-05-01 19:39:10 +02:00
Christian Kratky 808c2da5f6 Add PacketIdentifier for QoS 2. 2019-04-28 23:03:54 +02:00
Christian Kratky 6ed3b0cedd Add ClientId for application messages published by the server. 2019-04-24 21:37:29 +02:00
Christian Kratky 9da3377aa7 Fix credential generation. 2019-04-24 20:19:55 +02:00
Christian Kratky 0cac2aa1bc Fix broken log message. 2019-04-24 20:19:46 +02:00
Christian Kratky 2d59b5c1ac Refactoring. 2019-04-23 14:49:19 +02:00
Christian Kratky 9dfa0b32e4 Add extension methods for server. 2019-04-23 14:49:12 +02:00
Christian Kratky 20a7579156 Fix issues in ApplicationMessageInterceptor. 2019-04-23 14:48:51 +02:00
Christian Kratky c7409c2ff4 Fix missing endpoint in client status. 2019-04-23 14:48:38 +02:00
Christian Kratky d4c6fb44c9 Expose PacketIdentifier in PublishResult. 2019-04-23 14:47:42 +02:00
Christian Kratky e6cf23aebd Add API controllers for MQTTnet.Server. 2019-04-23 14:46:13 +02:00
Christian Kratky 0fec860b25 Add UnitTests. 2019-04-23 14:46:02 +02:00
Christian Kratky 2c927c5995 Cleanup. 2019-04-22 10:59:39 +02:00
Christian Kratky 6399172582 Improve connection disposal. 2019-04-22 10:50:47 +02:00
Christian Kratky 5c903e6fbf Improve connection handling. 2019-04-20 21:12:30 +02:00
Christian Kratky f60bbf7dd7 MQTTnet.Server startup cleanup. 2019-04-20 20:59:28 +02:00
Christian Kratky 519bb05aac Fix broken code. 2019-04-18 00:09:19 +02:00
Christian Kratky a8434d1b58 Expose results of publish operations for MQTTv5. 2019-04-18 00:01:22 +02:00
Christian Kratky 420b35e37d Merge remote-tracking branch 'origin/develop' into develop 2019-04-17 21:44:12 +02:00
Christian Kratky a25c8cd4c7 Fix some minor TODOs. 2019-04-17 21:44:09 +02:00
Christian 8ac77558af Merge pull request #593 from JanEggers/fixTodo
fixed todo in MqttConnectionContext
2019-04-17 19:14:00 +02:00
JanEggers 953578eba2 fixed todo in MqttConnectionContext 2019-04-17 09:47:17 +02:00
Christian 527713ccf8 Merge pull request #592 from JanEggers/spanV2
performance improvements span based serializers
2019-04-16 19:28:38 +02:00
JanEggers 477e2d23ab added benchmark option to compare netfx and core runtime 2019-04-15 15:52:51 +02:00
JanEggers 03c61ad82c fixed tests and added testcase for user property serialization 2019-04-15 15:37:15 +02:00
JanEggers 9475ccd0d8 revert accidential change 2019-04-15 15:31:31 +02:00
JanEggers 73b051d159 reuse reader 2019-04-15 15:00:09 +02:00
JanEggers a9944def68 added span based writer 2019-04-15 14:43:49 +02:00
JanEggers aee10ba6fa added netcore 2.1 build 2019-04-15 14:24:27 +02:00
JanEggers cfc1b27950 fixed build and added implementations for new read functions 2019-04-15 14:14:32 +02:00
JanEggers 149d01e173 added tests 2019-04-15 14:09:22 +02:00
JanEggers 888e1797d7 fixed cherry pick 2019-04-15 14:04:21 +02:00
JanEggers f8ade2daf4 slight improvements 2019-04-15 14:04:06 +02:00
JanEggers a85792c392 fixed another issue 2019-04-15 14:00:22 +02:00
JanEggers fbca8a6dc1 span based reader 2019-04-15 14:00:00 +02:00
Christian Kratky 732ea84caa Update build script. 2019-04-13 00:09:10 +02:00
Christian Kratky 65896269da Improve protocol version detection. 2019-04-11 20:13:30 +02:00
Christian Kratky 631f660d5c Add MQTTnet.Server to build script. 2019-04-11 20:13:08 +02:00
Christian Kratky 7f08371532 Update tests. 2019-04-08 22:29:52 +02:00
Christian Kratky 1afd59325f Add validations for client options builder. 2019-04-08 22:29:46 +02:00
Christian Kratky 45c033f401 Improve payload handling and allocation. 2019-04-08 22:29:29 +02:00
Christian Kratky 7855eccb78 Update solution files. 2019-04-07 20:54:16 +02:00
Christian Kratky d51300d32d Update build process. 2019-04-07 20:45:16 +02:00
Christian Kratky 61b10a8b56 Add extension methods. 2019-04-07 19:58:01 +02:00
Christian Kratky dbee941dcc Update nuget packages. 2019-04-04 22:00:40 +02:00
Christian Kratky fd7c98d0d1 Update docs. 2019-04-03 23:46:32 +02:00
Christian Kratky c911797f1b Fix broken config in MQTTnet.Server. 2019-04-03 23:46:26 +02:00
Christian Kratky b5a1d3a69f Add more config values for TCP connections. 2019-04-03 23:46:13 +02:00
Christian Kratky cdeb073bb0 Fix disposal of SSL streams. 2019-04-03 23:45:53 +02:00
Christian Kratky a8db0dd3d6 Rename tests. 2019-04-03 23:44:48 +02:00
Christian Kratky 2267770a72 Make internal message of server async. 2019-04-02 21:51:26 +02:00
Christian Kratky 35ee732045 Remove obsolete files from MQTTnet.Server. 2019-04-02 21:50:49 +02:00
Christian Kratky ad5834dd1f Add long runnings tests for all QoS levels. 2019-04-02 21:50:16 +02:00
Christian Kratky a7204234f6 Update docs. 2019-03-24 10:40:59 +01:00
Christian Kratky e8c33077b7 Update build script. 2019-03-24 10:35:42 +01:00
Christian Kratky bd86dae8a9 Update build script. 2019-03-24 10:19:43 +01:00
Christian Kratky 7188aaf79d Merge branch 'master' into develop 2019-03-24 10:06:09 +01:00
Christian Kratky bafcc81672 Update nuspecs. 2019-03-24 10:05:45 +01:00
Christian Kratky d0f1659eec Remove obsolete methods. 2019-03-24 10:05:38 +01:00
Christian Kratky 11a5b5a080 Add queue with async support to free up threads. 2019-03-22 23:12:37 +01:00
Christian Kratky 7ed5580352 Fix breaking changes. 2019-03-22 21:08:38 +01:00
Christian Kratky efc6f124b4 Merge remote-tracking branch 'origin/develop' into develop 2019-03-22 20:37:16 +01:00
Christian Kratky 7c3d88f62d Add validation for topics before publishing. 2019-03-22 20:37:14 +01:00
Christian b383a54416 Merge pull request #547 from vbBerni/develop
Fix Managed Client should dispose inner mqtt client #527
2019-03-22 20:31:24 +01:00
Christian Kratky 673fc5e20c Add windows startup script. 2019-03-16 09:55:45 +01:00
Christian Kratky f2b9642712 Add linuc startup script. 2019-03-16 09:55:15 +01:00
Christian 4f03f22afb Update README.md 2019-03-13 21:22:24 +01:00
Christian 27a4af6070 Update README.md 2019-03-13 21:20:09 +01:00
Christian 0184ce400c Update README.md 2019-03-13 21:19:55 +01:00
Christian Kratky 653ea8a102 Add MQTTnet debug logging. 2019-03-11 21:32:36 +01:00
Christian Kratky 3450889e84 Refactor settings. 2019-03-11 21:15:02 +01:00
Christian Kratky 1311535eed Added support for persisted retained messages. 2019-03-11 20:15:12 +01:00
Christian Kratky e1799ea6a3 Extend configuration. 2019-03-11 18:43:39 +01:00
Christian Kratky cd76f434e3 Fix breaking changes. 2019-03-10 20:12:04 +01:00
Christian Kratky fd91170aee Merge branch 'master' into develop 2019-03-10 20:00:49 +01:00
Christian Kratky cd1bfc3a10 Auto stash before merge of "develop" and "feature/server-project-bootstrap" 2019-03-10 19:58:02 +01:00
Christian Kratky f074e9ed04 Merge branch 'feature/server-project-bootstrap' into develop 2019-03-10 19:57:32 +01:00
Christian Kratky 562a5304f6 Add flag for secure connections. 2019-03-10 19:52:55 +01:00
Kiarash 1e697a94a1 Add Kesterl Settings into appsettings 2019-03-10 17:18:20 +01:00
Kiarash 0e2c3abd05 Add missing method for setting encrpted IPv6 address.
* Clean up
2019-03-10 16:34:18 +01:00
Kiarash 7321774c45 Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 16:02:45 +01:00
Kiarash 4a65cab769 Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 15:59:35 +01:00
Christian Kratky 510c3bd0bf Move logger into WebSocketServerAdapter instead of creating a new instance. 2019-03-10 15:58:55 +01:00
Kiarash 0c056b511e Fix and clean up 2019-03-10 15:56:11 +01:00
Christian Kratky 2ca6866c5e Remove obsolete code. 2019-03-10 14:55:17 +01:00
Kiarash ebcce9b8be Merge branch 'feature/server-project-bootstrap' of https://github.com/chkr1011/MQTTnet into feature/server-project-bootstrap 2019-03-10 13:58:37 +01:00
Kiarash 9e7c70e649 Add new configuartion model
Added new models for review
2019-03-10 13:58:18 +01:00
Christian Kratky bef0860e53 Add support for WebSocket connections. 2019-03-10 12:10:11 +01:00
Christian Kratky 67c9177731 Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2019-03-10 10:12:26 +01:00
Christian Kratky 007991f073 Update docs. 2019-03-10 10:11:43 +01:00
Christian 532dddeb6c Merge pull request #526 from JohBa/patch-2
Don't cancel token before stop session manager
2019-03-10 10:08:46 +01:00
Christian Kratky 9070087fad Add flag for indicating if application message processing has failed. 2019-03-10 09:51:49 +01:00
Christian Kratky de8bcb7f37 Update docs. 2019-03-09 19:24:04 +01:00
Christian 5090cfb411 Fix memory leak in AsyncAutoResetEvent. 2019-03-09 19:20:34 +01:00
Christian Kratky 6e64d653c5 Hide connect password from logs. 2019-03-08 23:48:49 +01:00
Christian Kratky 461bc6e594 Add MQTTnet.Server to NoUWP solution. 2019-03-08 23:48:28 +01:00
Christian Kratky 0d95dc563c Update documents. 2019-03-08 23:48:07 +01:00
Christian Kratky 03bfc5f00b Refactor event handler namings. 2019-03-08 23:47:51 +01:00
Christian Kratky 8708609498 Add more function mappings for MQTTnet Server. 2019-03-06 22:42:00 +01:00
Christian dffc27c1f4 Migrate events in server to async handlers. 2019-03-05 21:37:30 +01:00
Christian 6f5f507323 Extend MQTTnet.Server application. 2019-03-05 21:37:00 +01:00
Christian 26d6d817cd Fix memory leak in AsyncAutoResetEvent. 2019-03-05 07:47:31 +01:00
Kiarash Ghiaseddin b68247f56d WIP
First draft for MQTTnetServer project
* Basic support for settings
* Nasty code for setting up kestrel from appsettings.json
2019-03-04 21:13:22 +01:00
Christian 3b02a5f6aa Fix NullRefException when cancelling the server. 2019-02-23 10:40:17 +01:00
Christian 09718a00e7 Add handlers to variable before using to avoid NullRefExceptions. 2019-02-23 10:13:12 +01:00
Christian ecc2cd5f0c Merge pull request #555 from BennyM/develop
When no handlers are configured the client should not blow up
2019-02-23 10:07:24 +01:00
Christian 618580dc15 Merge pull request #553 from dpsenner/feature/MqttClient-add-missing-async-extensions
Add extension methods that provide a simpler api for IMqttClient and IManagedMqttClient
2019-02-22 20:28:53 +01:00
BennyM 4860cec6c7 When no handlers are configured the client should not blow up 2019-02-19 21:40:11 +01:00
Dominik Psenner b9e0dbf150 Add extension methods that provide a simpler api for IMqttClient and IManagedMqttClient connect/disconnect when the handlers do not need async/await 2019-02-18 08:02:09 +01:00
vbBerni 2a4eb460da StopAsync now waits until the managed client is stoped and more typical disposing of internal client 2019-02-16 22:23:45 +01:00
Christian 087c622122 Merge pull request #551 from dpsenner/feature/add-async-handlers-for-connected-and-disconnected
Add async handler interfaces for connected and disconnected to allow async code on connect
2019-02-16 19:04:06 +01:00
Dominik Psenner 2000de15e7 Add async handlers for connect and disconnect, too
.. this allows a client to properly async publish on connect.
2019-02-15 17:02:33 +01:00
Dominik Psenner 5e6b902430 Add convenience extensions to the managed client 2019-02-15 16:55:52 +01:00
Dominik Psenner a1f414a06d Add async handler interfaces for connected and disconnected to allow async code to execute on connect 2019-02-15 15:02:15 +01:00
Berni de3a39bdc2 Fix Managed Client should dispose inner mqtt client #527 2019-02-07 16:46:58 +01:00
Christian 6c5c9e5bf2 Merge pull request #540 from vbBerni/develop
fix logger logId not used in ManagedMqttClient
2019-01-31 19:57:09 +01:00
Berni 506873ed5b fix logger logId not used in ManagedMqttClient 2019-01-31 15:50:01 +01:00
Christian Kratky 6a2bded181 Refactor session and connection handling in server. Fix QoS level 2 issues. 2019-01-27 11:15:32 +01:00
Christian Kratky ebf0e91ab8 Refactor subscribe and unsubscribe to support MQTTv5. 2019-01-21 21:38:39 +01:00
Johannes Bäurle 107e96ff7d Don't cancel token before stop session manager 2019-01-07 11:54:10 +01:00
Christian Kratky 0d6e244f84 Refactor UnitTests. 2019-01-06 13:31:27 +01:00
Christian Kratky 96a67579e2 Improve session handling. 2019-01-01 19:18:54 +01:00
Christian Kratky 4cba814716 Cleanup. 2018-12-27 23:10:52 +01:00
Christian Kratky b527059b72 Fix session takeover. 2018-12-27 23:05:57 +01:00
Christian Kratky c0507fcc55 Refactor interceptors etc. to support async. 2018-12-27 22:41:41 +01:00
Christian 38f2453c92 Update README.md 2018-12-22 20:25:53 +01:00
Christian Kratky 058bb65d31 Merge from develop. 2018-12-22 09:40:47 +01:00
Christian Kratky 38b215e9b5 Merge branch 'develop' into feature/MQTTv5 2018-12-22 09:38:12 +01:00
Christian Kratky 45df33c9a5 Update nuspec. 2018-12-22 09:33:44 +01:00
Christian Kratky 89becaa191 Fix build script. 2018-12-22 09:28:51 +01:00
Christian Kratky 6c87e4e039 Replace nuget version with placeholder. 2018-12-22 09:26:52 +01:00
Christian Kratky cbe06d6b87 Merge from master. 2018-12-21 00:21:42 +01:00
Christian 4fed80c2d0 Update appveyor.yml 2018-12-20 21:08:07 +01:00
Christian Kratky 74e4fd8b3f Update test certificate. 2018-12-20 20:54:37 +01:00
Christian Kratky cc113a6c34 Refactor namespaces. 2018-12-20 20:53:29 +01:00
Christian fca9876111 Delete .travis.yml 2018-12-19 00:10:10 +01:00
Christian ac9f6a36f8 Update appveyor.yml 2018-12-19 00:06:51 +01:00
Christian 929b60e044 Update appveyor.yml 2018-12-18 21:32:46 +01:00
Christian acb433dd4c Update appveyor.yml 2018-12-18 20:23:18 +01:00
Christian c4e8bf7f39 Update appveyor.yml 2018-12-18 20:12:09 +01:00
Christian ba4fdfb51c Merge pull request #497 from cquesnel/feature/add-websocket-parameters
Add custom WebSocket parameters
2018-12-14 21:37:04 +01:00
Charles Quesnel dfda916283 Use default parameter instead of overload 2018-12-13 14:54:31 -05:00
Charles Quesnel 40326df9a9 Fix typo in 'Cookie' 2018-12-13 14:08:53 -05:00
Charles Quesnel a94444098a Remove unused usings 2018-12-13 13:01:34 -05:00
Charles Quesnel 0c13e7a504 Add overload to allow passing custom request headers and cookies when connecting with WS 2018-12-13 12:56:47 -05:00
Christian Kratky 0dba57fe75 Cleanup code. 2018-12-09 21:04:14 +01:00
Christian Kratky 6483f896c1 Merge from develop. 2018-12-09 20:48:46 +01:00
Christian Kratky 8fa9943c3d Merge branch 'master' into develop 2018-12-09 19:44:17 +01:00
Christian Kratky 195357835b Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2018-12-09 19:42:03 +01:00
Christian Kratky 28b2562112 Fix client session disposal in server. 2018-12-09 17:35:46 +01:00
Christian Kratky ab24368de1 Update docs. 2018-12-08 13:46:40 +01:00
Christian Kratky 9b51404b4d Add Unit Tests. 2018-12-06 21:35:42 +01:00
Christian Kratky 619eaf284d Add readonly property for client options. 2018-12-03 21:20:11 +01:00
Christian Kratky 86c348df58 Stop existing sessions before takeover from another client. 2018-12-02 21:50:16 +01:00
Christian Kratky fdb2ec897c Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-12-01 11:00:09 +01:00
Christian Kratky b091fee554 Reset the keep alive monitor if a session is being resumed from a different (or same) client. 2018-12-01 11:00:00 +01:00
Christian 14ec6ee793 Merge pull request #484 from fogzot/feature-msbuild-conditions
Feature msbuild conditions
2018-12-01 10:50:39 +01:00
Federico Di Gregorio 0cfef0649a Fixed appveyor configuration to use full solution 2018-11-30 09:38:10 +01:00
Federico Di Gregorio 7292af7db4 Added solution that does not include UWP 2018-11-30 09:26:22 +01:00
Federico Di Gregorio bc1a197c4f Align conditions in dependent project with conditions in MQTTnet 2018-11-30 09:26:02 +01:00
Christian Kratky ccc275902f Fix wrong retain flag when distributing messages. 2018-11-28 21:35:50 +01:00
Christian Kratky 0f5fb8aa3a Add more pacakges. 2018-11-28 21:11:23 +01:00
Christian Kratky 83eca982e9 Update nugets. 2018-11-24 20:21:05 +01:00
Christian Kratky 017f17a6b1 Fix UnitTests. 2018-11-24 20:19:16 +01:00
Christian Kratky b3564e01a4 Update docs. 2018-11-23 22:57:34 +01:00
Christian Kratky 43105f71d8 Refactor removal from blocking queue. 2018-11-23 22:56:10 +01:00
Christian Kratky 40c408a9c0 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-11-23 22:51:07 +01:00
Christian Kratky 7baff7c080 Refactor property definition for packets. 2018-11-23 22:50:44 +01:00
Christian 91a918d30b Merge pull request #479 from PaulFake/patch-1
Fix for two issues with the managed message queue cap
2018-11-23 22:48:40 +01:00
Paul Fake 2a93fc18e4 Made comparison function static 2018-11-21 21:44:26 -05:00
Paul Fake 31de6ee186 Delegate comparison function 2018-11-21 21:39:42 -05:00
Paul Fake 74d59673a8 Delegate for comparisons 2018-11-21 21:38:06 -05:00
Paul Fake d1c3d9b453 Removed unnecessary code 2018-11-21 21:37:01 -05:00
Paul Fake baa9241216 Revert "Changes to this file no longer needed"
This reverts commit 2c6c3ac6a4.
2018-11-21 21:35:15 -05:00
Paul Fake 2c6c3ac6a4 Changes to this file no longer needed 2018-11-21 20:47:12 -05:00
Paul Fake b2c31331b6 Peek-and-publish model
We had been seeing an issue in which the queue could grow larger than the configured cap.  I examined the code and saw that this could happen if _mqttClient.PublishAsync() throws an exception, in which case a message can be re-enqueued without honoring the cap.  Furthermore, I saw that it was possible for the DropOldestQueuedMessage strategy to drop messages that were not actually the oldest ones, because when re-enqueueing the messages in the queue are no longer ordered by the original time they entered the queue.  It made sense to us to peek at the message when publishing rather than dequeue it, so that when re-enqueueing after an exception 1) the cap is still honored and 2) the order of queued messages isn't altered.  It's ok if another thread removes the message that's currently being published from the queue due to the cap, because all we have to do then is check if it's already been removed before removing it ourselves.
2018-11-19 21:20:50 -05:00
Paul Fake 9ff39c1fd9 New functions
This is to support the peek-and-publish model for the managed client
2018-11-19 21:11:47 -05:00
Paul Fake 210d57b254 IEquatable for speed
IEquatable for speed in using EqualityComparer<TItem>.Default.Equals
2018-11-19 21:09:36 -05:00
Christian Kratky 7292cedd2f Encode ConnAck packet. 2018-11-19 00:17:19 +01:00
Christian Kratky 48d5afa799 Refactor namings of serializers etc. 2018-11-19 00:14:15 +01:00
Christian Kratky 3db22eea51 Remove dedicated V3 messages. 2018-11-18 22:04:39 +01:00
Christian Kratky 2fbb44ec66 Add more property implementations. 2018-11-18 21:54:40 +01:00
Christian Kratky d7b98080f5 Refactor unit test for server events. 2018-11-18 11:20:36 +01:00
Christian Kratky 3e7b41e712 Refactor code. 2018-11-17 20:24:23 +01:00
Christian Kratky 5f18f35e02 Refactor task usage in client. 2018-11-17 20:23:52 +01:00
Christian Kratky af39e87703 Refactor code. 2018-11-17 20:23:20 +01:00
Christian Kratky ace25af0e8 Added package properties. 2018-11-16 23:11:26 +01:00
Christian Kratky 8d78455414 Fix breaking changes. 2018-11-16 22:18:59 +01:00
Christian Kratky fed16d7710 Merge from develop. 2018-11-16 22:16:21 +01:00
Christian Kratky fcff3a2c8d Update docs. 2018-11-16 22:12:29 +01:00
Christian 803dd6f64e Merge pull request #476 from PaulFake/patch-1
Check for pending disconnect in ThrowIfNotConnected
2018-11-16 22:08:49 +01:00
Paul Fake a1e258eb24 Check for pending disconnect in ThrowIfNotConnected
This might be a little controversial, but it worked for us to correct a problem in which messages get stuck in the managed client storage queue (and are thrown out of the regular message queue without being published!) in the case of a failed connection.  What we were seeing was that ManagedMqttClient.TryPublishQueuedMessage() was discarding a dequeued message without ever removing it from the storage queue because of an OperationCancelledException thrown by MqttClient.PublishAsync().  Tracing the code back, we found that when the connection is interrupted, after the timeout period MqttClient.InitiateDisconnect() would set the cancellation token, and the managed client would continue to try to publish, eventually calling through to MqttClient.SendAndReceiveAsync(), which would throw because the cancellation token is set.  Looking back over the code, we saw that MqttClient.PublishAsync() has a call to ThrowIfNotConnected() at the top, which told us that the intent was to not allow this function to be called after a disconnect.  But the disconnect was still pending, and the function wasn't behaving correctly in this state, so we reasoned that it's best to throw if the disconnect is pending.
2018-11-14 11:25:12 -05:00
Christian Kratky e9df698a1f Update nuget versions. 2018-11-05 22:40:48 +01:00
Christian Kratky bddcbf6999 Refactor code. 2018-11-05 22:39:56 +01:00
Christian be22e2551d Merge pull request #471 from JanEggers/develop
updated nuget spec according to csproj
2018-11-05 22:24:31 +01:00
Jan Eggers 4e01c7f13d updated nuget spec according to csproj 2018-11-05 06:45:40 +01:00
Christian Kratky 7181813f12 Fix pending messages overflow strategy issue. 2018-11-04 20:33:44 +01:00
Christian Kratky 6fc9f12c34 Refactor task await. 2018-11-04 13:18:42 +01:00
Christian cc4e37fa40 Merge pull request #469 from JanEggers/fixedConcurrentWrites
fixed parallel writes
2018-11-04 13:16:18 +01:00
JanEggers ccadd4e41a updated release notes 2018-11-04 11:44:25 +01:00
JanEggers a5caab62f8 fixed parallel writes 2018-11-04 11:39:12 +01:00
Christian Kratky 2bff218806 Update docs. 2018-10-29 21:49:01 +01:00
Christian Kratky 95c30a2843 Update docs. 2018-10-29 21:48:12 +01:00
Christian Kratky 28efbcdb3d Add max pending messages options for ManagedClient. 2018-10-29 21:45:01 +01:00
Christian Kratky ca7952ab33 Remove wrong setter. 2018-10-29 20:35:22 +01:00
Christian Kratky 62693af196 Merge from master. 2018-10-20 00:34:28 +02:00
Christian Kratky 5abee2512f Update nuget packages. 2018-10-20 00:32:53 +02:00
Christian Kratky c9a6155834 Update docs. 2018-10-19 23:57:09 +02:00
Christian Kratky aad3ab903f Expose retained messages to server interface. 2018-10-19 23:56:32 +02:00
Christian Kratky 4c76a898b6 Add new UnitTests. 2018-10-19 23:55:02 +02:00
Christian d273148bc5 Update README.md
Reorder references alphabetically.
2018-10-14 12:05:08 +02:00
Christian 5314f5c67a Merge pull request #444 from keesschollaart81/patch-1
Referencing the MQTT Bindings for Azure Functions
2018-10-14 12:03:07 +02:00
Kees Schollaart 22aab44d49 Referencing my MQTT Bindings for Azure Functions
Hi, if you're interested, hereby a reference to my work on MQTT Bindings for Azure Functions where I used this library. Thanks for the excellent work. More background [over here](http://case.schollaart.net/2018/09/22/mqtt-and-azure-functions.html)
2018-10-14 11:46:32 +02:00
Christian b819746165 Merge pull request #430 from JanEggers/fix#421
fixed #421
2018-10-07 15:52:17 +02:00
JanEggers 73d33e2200 fixed #421 2018-10-07 15:20:13 +02:00
Christian 740bc3aa30 Merge pull request #429 from JanEggers/supportTlsProtolOptionOnServer
added ability to specify tls protocol version
2018-10-07 15:03:17 +02:00
JanEggers 583b32f17a updated release notes 2018-10-07 13:24:07 +02:00
JanEggers b7ab29473b added ability to specify tls protocol version 2018-10-07 12:10:26 +02:00
Christian Kratky ffc4f1408a Merge develop. 2018-10-06 13:13:40 +02:00
Christian Kratky c8b3066883 Update docs. 2018-10-06 13:12:15 +02:00
Christian Kratky fb4f89b412 Replace TaskCompletionSource in Client with Interlocked gate. 2018-10-04 22:30:03 +02:00
Christian Kratky 6bee6a0469 Update docs. 2018-10-04 20:58:15 +02:00
Christian Kratky 0c2ab9b231 Fix a deadlock when an exception is fired while connecting. 2018-10-04 20:53:02 +02:00
Christian Kratky 03bef4c15d Fix revocation checks in certificate validator. 2018-10-01 21:50:54 +02:00
Christian Kratky ba62ca7306 Update docs. 2018-10-01 21:36:15 +02:00
Christian Kratky 56a1530cee Add a method for clearing all retained messages at the server. 2018-09-29 11:49:02 +02:00
Christian Kratky 699cd5fc23 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-09-28 22:51:27 +02:00
Christian Kratky 381c59d1e5 Update readme. 2018-09-28 22:51:16 +02:00
Christian Kratky 70f4dc9e10 Change log level of retained message changes. 2018-09-28 22:51:05 +02:00
Christian 0367ad31f1 Merge pull request #422 from ifit/client-cancel-task
Client cancel task
2018-09-28 22:49:11 +02:00
Christian 5c6bcdbca6 Merge branch 'develop' into client-cancel-task 2018-09-28 22:49:00 +02:00
Andre Crabb 400c0f05ad * Adds false param to Cancel call. 2018-09-28 14:07:04 -04:00
Andre Crabb 00df7c9b7b * More change tabs to spaces. 2018-09-28 11:01:07 -04:00
Andre Crabb a272ed7daa * Change tabs to spaces. 2018-09-28 11:00:18 -04:00
Andre Crabb b2e7a2e370 Change from logging Info to Verbose 2018-09-21 15:44:31 -04:00
Andre Crabb 39bc70cbf0 * Cancel the TokenSource when disposing or nulling it out for the MqttClient 2018-09-20 11:08:33 -04:00
Christian Kratky 682298b69f Fix issue in pending messages handling for managed client. 2018-09-13 09:29:26 +02:00
Christian Kratky 028a39ec25 Update docs. 2018-09-13 09:19:15 +02:00
Christian Kratky 3b104049b4 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-08-25 17:33:58 +02:00
Christian dd83a360b4 Merge pull request #402 from JanEggers/AspNetMqttServerOptionsBuilder
added AspNetMqttServerOptionsBuilder
2018-08-25 16:56:34 +02:00
JanEggers 976c62d9c2 added back the old function and added new overload 2018-08-25 12:08:42 +02:00
JanEggers 4cc9f12a03 added AspNetMqttServerOptionsBuilder 2018-08-21 21:32:03 +02:00
Christian Kratky 0b5a751c56 Add all methods of the factory to the factory interfaces. 2018-08-15 17:48:28 +02:00
Christian Kratky 5a59cd278c Add serializer adapter. 2018-08-06 20:36:15 +02:00
Christian Kratky cdb05e5894 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-08-04 12:30:21 +02:00
Christian Kratky 6c08b5caf3 Update docs. 2018-08-04 12:30:08 +02:00
Christian d5b53f3712 Merge pull request #384 from cstichlberger/managed_client_fix_unsubscription_overtaking_subscription
Prevent unsubscription overtaking later subscription
2018-08-04 12:28:04 +02:00
Christoph Stichlberger 80fbb2f0b2 Prevent unsubscription overtaking later subscription 2018-08-02 16:25:14 +02:00
Christian Kratky b4f90decc7 Fix unit tests to allow release builds. 2018-07-27 17:20:19 +02:00
Christian Kratky 61b324043a Refactoring 2018-07-26 20:02:11 +02:00
Christian Kratky 2ced921008 Refactoring. 2018-07-26 14:48:40 +02:00
Christian 1e2fee0f33 Merge pull request #343 from JanEggers/ServerShutdown
Server shutdown
2018-07-26 14:45:44 +02:00
Christian ac36c9c406 Merge branch 'develop' into ServerShutdown 2018-07-26 14:45:25 +02:00
Christian Kratky f70c79aaf9 Refactor options. 2018-07-26 11:34:24 +02:00
Christian Kratky 0839fa5757 Update docs. 2018-07-26 10:43:40 +02:00
Christian Kratky 60bc4ebcee Refactor proxy usage and support. Refactor TLS parameter usage. 2018-07-26 10:35:52 +02:00
Christian 65e239652d Merge pull request #364 from PitySOFT/webproxy
Add proxy settings for WebSocket connections for .NET 451 and 461 and add option to specify the SSLProtocol and CertificateValidationCallback  in TLS options, SSLProtocol default is TLS1.2
2018-07-26 10:04:52 +02:00
Christian Kratky 6b9015a928 Fix order of ClientConnected and ClientDisconnected events. 2018-07-25 20:18:27 +02:00
Christian Kratky a740c38ee6 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-24 14:06:18 +02:00
Christian Kratky 603639126e Fix issue in processing of server messages. 2018-07-24 13:49:23 +02:00
JanEggers 043cfdb3f9 fixed deadlock and object disposed exception 2018-07-23 17:58:29 +02:00
Christian b0da4b2b2d Merge pull request #372 from jenscski/LogFix
Small fix for inconsistent client name in log
2018-07-22 21:10:05 +02:00
Christian 5402859a30 Merge pull request #368 from jenscski/ClientKeepAliveMonitor
Fix pause/resume of ClientKeepAliveMonitor
2018-07-22 21:09:21 +02:00
Jens-Christian Skibakk 2b10200101 Small fix for inconsistent client name in log 2018-07-22 20:09:37 +02:00
Jens-Christian Skibakk 55e8927ab7 Fix pause/resume of ClientKeepAliveMonitor 2018-07-20 14:13:21 +02:00
JanEggers d30fe61264 fixed missing waits 2018-07-19 21:13:29 +02:00
JanEggers f7ea2d29e1 prove its broken 2018-07-19 21:13:28 +02:00
JanEggers e6cfef5295 fixed disconnect to be triggered just once 2018-07-19 21:13:28 +02:00
JanEggers 0dea9e6a2b changed waiting condition 2018-07-19 21:13:28 +02:00
JanEggers ae80de26ec addressed feedback 2018-07-19 21:13:28 +02:00
JanEggers 53bd2a0960 fixed blocking code in networkstrem and reduced sleep in tests 2018-07-19 21:13:28 +02:00
JanEggers b55f5ff298 event is triggered but something is blocking 2018-07-19 21:13:27 +02:00
JanEggers 21048b51ae prove there is something wrong 2018-07-19 21:13:27 +02:00
Christian Kratky 773fd09166 Merge branch 'master' into develop 2018-07-19 21:02:37 +02:00
Christian 57532a290a Merge pull request #365 from jenscski/DotnetCliBuild
Skip build uap10.0 when using dotnet cli
2018-07-19 18:58:48 +02:00
Jens-Christian Skibakk 740a35b018 Skip build uap10.0 when using dotnet cli 2018-07-18 19:54:07 +02:00
Marius Ruginosu 6e995230a7 Created overload methods for WithTls default values 2018-07-18 16:54:19 +03:00
Marius Ruginosu 65a8b091b9 Add option to specify the SSLProtocol and CertificateValidationCallback in TLS options, SSLProtocol default is TLS1.2 2018-07-18 12:19:09 +03:00
Marius Ruginosu fa34908d82 Add proxy settings for WebSocket connections for .NET 451 and 461 2018-07-18 10:51:45 +03:00
Christian Kratky b09eb1213c Refactor logging. 2018-07-08 22:04:06 +02:00
Christian Kratky 23ae8ab3b5 Fix unit test. 2018-07-08 14:10:25 +02:00
Christian Kratky 0bdb7e9e44 Merge branch 'develop' 2018-07-08 14:02:35 +02:00
Christian Kratky 54e3cd7cb7 Update nuspecs. 2018-07-08 14:01:47 +02:00
Christian Kratky 16ad07cfc9 Add wrapper for WebSocket4Net. 2018-07-08 10:34:46 +02:00
Christian Kratky dee0adcd8c Add new overloads. 2018-07-07 22:46:07 +02:00
Christian Kratky acbf1226ab Fix a bug in the keep alive monitor. 2018-07-07 21:22:08 +02:00
Christian Kratky f002744d87 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-07 21:03:36 +02:00
Christian Kratky 9efee7af21 Refactoring. 2018-07-07 21:03:31 +02:00
Christian 9814b10496 Merge pull request #355 from JanEggers/ConnectionHandlerWithWebsockets
Connection handler with websockets
2018-07-07 21:00:32 +02:00
JanEggers 978694b3c0 set binary mode 2018-07-07 10:52:24 +02:00
JanEggers bc6f155f12 using connectionhandlers with websockets 2018-07-07 10:42:33 +02:00
Christian Kratky d494c2104b Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-07-05 21:20:14 +02:00
Christian Kratky 8035c6859f Update docs. 2018-07-05 21:20:08 +02:00
Christian Kratky 2f10295022 Fix message handling for UWP. 2018-07-05 21:20:01 +02:00
Christian e5f32730a7 Merge pull request #353 from JanEggers/hideoverloadthatdoesnotprovideoptions
hide overload that does not provide options
2018-07-05 21:13:35 +02:00
JanEggers cd257b4d25 hide overload that does not provide options 2018-07-05 20:31:01 +02:00
Christian Kratky ce534baa75 Move the connection check interval of the ManagedClient to the options. 2018-07-04 22:20:24 +02:00
Christian Kratky 2b420b8e66 Add support for disabling server endpoints (ipv4 or ipv6) 2018-07-04 22:20:02 +02:00
Christian Kratky 35300abfb5 Fix typo. 2018-07-04 22:03:36 +02:00
Christian Kratky 3d0ecc05ff Fix bug which prevents receiving large packets for UWP. 2018-07-04 22:03:19 +02:00
Christian Kratky bfb6ec8856 Update UWP test app. 2018-07-04 22:02:42 +02:00
Christian Kratky bf1d682a85 Update libs 2018-07-04 22:00:48 +02:00
Christian Kratky 7d9326a147 Extend MqttPacketReader constructor to allow more unit tests. 2018-07-04 22:00:34 +02:00
Christian Kratky 7fd09009e7 Update docs. 2018-07-04 21:58:00 +02:00
Christian Kratky 9fa5e2dc1f Add the adapter Endpoint to the connection validator. 2018-07-04 21:57:51 +02:00
Christian Kratky 15d4ee4d68 Merge branch 'develop' 2018-06-30 00:29:26 +02:00
Christian Kratky 6ca6a52ae8 Update docs. 2018-06-30 00:29:04 +02:00
Christian Kratky 3d643aa4cb Update versions. 2018-06-29 23:54:34 +02:00
Christian 9739d23b6f Merge pull request #340 from JanEggers/moreExtensionsForAspnetCoreConfiguration
more extensions for aspnetcore configuration
2018-06-29 21:03:10 +02:00
JanEggers c43acf7dac more extensions for aspnetcore configuration 2018-06-29 20:05:48 +02:00
Christian 995c226893 Merge pull request #339 from JanEggers/develop
fixed parsing issue and added test
2018-06-29 14:17:49 +02:00
Jan Eggers 8574bbb64f fixed parsing issue and added test 2018-06-29 13:37:26 +02:00
JanEggers b2bb545947 Update MQTTnet.AspNetCore.nuspec
added dependencies to nuspec
2018-06-29 13:06:46 +02:00
Christian Kratky bf8dae67de Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-06-25 20:10:10 +02:00
Christian c6309da015 Merge pull request #334 from JanEggers/improveErrorMessages
Improve error messages
2018-06-25 20:09:57 +02:00
Christian 2e83a1010e Merge pull request #330 from JanEggers/develop
fixed another build issue
2018-06-25 20:03:49 +02:00
Christian Kratky d5efb31e3a Fix build script. 2018-06-25 20:03:02 +02:00
Jan Eggers b77798f885 dont use thread static buffers they are overlapping on server due to async io 2018-06-25 15:31:49 +02:00
Jan Eggers 5923c7c408 fixed negative length for empty packages 2018-06-25 14:52:31 +02:00
Jan Eggers 7dfb6fdc52 fixed dup flag serialization and added roundtrip tests 2018-06-25 14:51:46 +02:00
Jan Eggers 4e40b2ddf3 added test to prove something is broken 2018-06-25 12:31:47 +02:00
Jan Eggers 4e9abd41c0 improve error messages 2018-06-25 12:31:19 +02:00
Jan Eggers 7240b86d98 fixed another build issue 2018-06-25 09:25:29 +02:00
Christian Kratky 211853d519 Fix wrong packet writer buffer length calculation. 2018-06-24 19:51:00 +02:00
Christian Kratky f39589a8c1 Add new publish overloads. 2018-06-22 20:45:30 +02:00
Christian e387971292 Merge pull request #326 from JanEggers/develop
Fixed build versions
2018-06-22 20:42:39 +02:00
Jan Eggers 4fc1912ee8 fixed assembly versions 2018-06-22 09:21:33 +02:00
Christian Kratky 31a704b675 Merge branch 'master' into develop 2018-06-21 23:21:00 +02:00
Christian Kratky c5c088300f Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2018-06-21 23:20:26 +02:00
Christian Kratky ccea8e6eb5 Update readme 2018-06-21 23:03:33 +02:00
Christian Kratky ac60ed4559 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-06-21 23:01:09 +02:00
Christian Kratky 8026263a27 Update nuspec 2018-06-21 23:00:52 +02:00
Christian Kratky 6fa6abe6f0 Update readme. 2018-06-21 20:42:49 +02:00
Christian Kratky e8d5bd7bfb Add new properties and events for the managed client. 2018-06-21 20:42:44 +02:00
Christian 2a03c1f1f4 Merge pull request #321 from asthomas/develop
Fix for incoming SSL connections
2018-06-21 19:26:13 +02:00
asthomas 0c6b92536e Merge pull request #1 from chkr1011/develop
Develop
2018-06-21 08:31:05 -04:00
Andrew dddc1ec112 Fix a bug where an incoming SSL client connection was being treated as a plain-text connection. 2018-06-21 08:12:55 -04:00
Christian Kratky 8b376874c0 Merge develop 2018-06-20 20:10:12 +02:00
Christian Kratky 0322660561 Refactor async/await and ConcurrentDictionary usage. 2018-06-20 20:07:25 +02:00
Christian a7205ddf02 Merge pull request #318 from JanEggers/perf
improve session manager
2018-06-20 20:05:25 +02:00
Jan Eggers 64b38487bc improve session manager 2018-06-20 08:20:54 +02:00
Christian Kratky bc20850fba Refactor serializer locking and thread instances. 2018-06-19 20:52:31 +02:00
Christian Kratky 66048931a2 Refactor ASP net Core integration and fix breaking change. 2018-06-17 17:19:08 +02:00
Christian 8444b6b3be Merge pull request #298 from JanEggers/transports
new Transports for AspnetCore 2.1
2018-06-17 15:38:23 +02:00
Christian Kratky baac26c5f6 Refactor package deserialization. 2018-06-17 14:36:32 +02:00
Christian Kratky 56e9e15ac0 Refactor Serializer memory usage. 2018-06-17 13:47:58 +02:00
Christian Kratky beb54acc2f Refactor serializer benchmark to allow fair comparisons. 2018-06-17 13:19:43 +02:00
JanEggers d573423372 downgrade dependencies to 2.0 2018-06-16 17:39:37 +02:00
JanEggers 410bc211a5 fixed packet reader 2018-06-16 17:39:04 +02:00
JanEggers e65c3f2f2b moved files into the correct place 2018-06-16 17:30:08 +02:00
JanEggers cf947415e8 enable abort exceptions 2018-06-16 17:21:58 +02:00
JanEggers c32a606a70 add memory diagnoser 2018-06-16 17:21:58 +02:00
JanEggers 78c6059668 enabled clients based on tcp to benefit from new api and added Benchmark for EndtoEnd with new API 2018-06-16 17:21:58 +02:00
JanEggers 7c2adf636f removed dead code and make new connection context an opt in so kestrel 2.0 still works 2018-06-16 17:20:01 +02:00
JanEggers d5ac8c7183 use final packages 2018-06-16 17:20:00 +02:00
JanEggers 7a7fab0907 fixed rebase 2018-06-16 17:20:00 +02:00
JanEggers c758ae89f4 first iteration 2018-06-16 17:20:00 +02:00
Christian Kratky caea7910b4 Refactor message processing and async/await usage. 2018-06-16 14:30:02 +02:00
Christian Kratky 6192685671 Remove batch sending of messages to prevent message reordering and several required awaits. 2018-06-15 00:19:51 +02:00
Christian Kratky 26eed30dbf Added custom exception for gracefully closed exceptions. 2018-06-11 00:26:38 +02:00
Christian Kratky 20779dfece Reorganize solution structure. 2018-06-11 00:00:30 +02:00
Christian Kratky 6bcfa436ea Fix TLS certificate loading. 2018-06-09 21:57:04 +02:00
Christian Kratky e62316105f Refactor server socket management for Linux support. 2018-06-09 15:31:47 +02:00
Christian Kratky 9e318fc40d Update BetterCodeHub config. 2018-06-06 22:10:34 +02:00
Christian Kratky 4b407d5213 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-06-06 22:08:55 +02:00
Christian Kratky 841a22b2b2 Refactor channel adapter. 2018-06-06 22:08:46 +02:00
Christian Kratky 840d8ab4fd Refactor TCP channel. 2018-06-06 22:04:37 +02:00
Christian 2e3e58ed73 Update .bettercodehub.yml 2018-06-06 21:56:47 +02:00
Christian Kratky eb48f87667 Update packages 2018-06-06 21:50:17 +02:00
Christian Kratky a164c120d5 Update solution file. 2018-06-06 21:47:59 +02:00
Christian 9dddd40dbe Update .bettercodehub.yml 2018-06-06 21:47:37 +02:00
Christian ad778636cf Delete MQTTnet.NetStandard.csproj 2018-06-06 21:45:58 +02:00
Christian Kratky 78360bc24a Add ID property for the ManagedMqttApplicationMessage. 2018-06-06 21:44:25 +02:00
Christian Kratky 3480d9ac35 Refactoring 2018-06-06 21:29:34 +02:00
Christian Kratky ae72bc3f99 Fix wrong exceptions during a clean disconnect. 2018-06-06 21:29:19 +02:00
Christian Kratky c8bf36044b Rerfactor package parsing. 2018-06-06 21:28:39 +02:00
Christian Kratky b05cb0d2ea Move managed client to separate nuget. 2018-06-06 21:27:39 +02:00
Christian Kratky fd1880f1ff Update better code hub config. 2018-06-06 21:26:56 +02:00
Christian Kratky 70c5bd1875 Remove obsolete files. 2018-06-05 23:41:02 +02:00
Christian Kratky 00ac9ce961 Fix wrong remaining length calculation. 2018-06-05 23:39:59 +02:00
Christian Kratky 1d455221e4 Clear awaiters after an exception has occured. 2018-06-05 21:28:11 +02:00
Christian Kratky 31b4eb7937 Optimize package serializing and dispatching. 2018-06-05 21:13:58 +02:00
Christian Kratky c88b46783b [Server] Add new interceptor before messages are added to a queue. 2018-06-04 22:33:13 +02:00
Christian Kratky 39edd22a9d Refactor thread management for incoming packets. 2018-06-04 22:19:07 +02:00
Christian Kratky afe25db0d3 Update docs. 2018-06-04 21:26:33 +02:00
Christian Kratky f86a5af794 Merge branch 'pr/301' into develop 2018-06-04 21:23:27 +02:00
Christian Kratky e6de4d014e Update client test app 2018-06-04 21:19:15 +02:00
Christoph Stichlberger b38df9eecd Respect keep alive interval after sending 2018-06-04 16:00:03 +02:00
Christian Kratky 54abf84e96 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-06-03 22:04:48 +02:00
Christian Kratky 66ebdfd61a Add test for simple server and client execution. 2018-06-03 22:04:43 +02:00
Christian 4fe7c13d8e Merge pull request #295 from JanEggers/moreBenchmarks
more benchmarks
2018-06-01 12:40:54 +02:00
Jan Eggers 2578b380f9 fixed sln change and moved options to seperate file 2018-06-01 12:27:06 +02:00
Jan Eggers cadf9f797f added pipe based benchmak 2018-06-01 08:47:00 +02:00
JanEggers fd50e4e260 more benchmarks 2018-06-01 07:14:03 +02:00
Christian Kratky 1cbec27b7f Fix projects 2018-05-31 21:48:09 +02:00
Christian Kratky 8d110c44f7 Merge master 2018-05-31 21:39:27 +02:00
Christian Kratky 66a77db851 Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2018-05-31 21:35:51 +02:00
Christian Kratky 0505efbac1 Refactor graceful socket close. 2018-05-31 21:34:51 +02:00
Christian Kratky 99614f2e15 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-05-31 21:28:10 +02:00
Christian 08e41244fc Merge pull request #294 from JanEggers/NewExtensionToReduceCodeForBuilderPattern
added extension method
2018-05-31 21:27:50 +02:00
JanEggers 4e74b59796 added extension method 2018-05-31 13:45:57 +02:00
Christian 2b6b268b4e Merge pull request #291 from JanEggers/BenchmarksSdkProject
use new project system for benchmarks
2018-05-31 10:58:55 +02:00
Jan Eggers 09aacf011e use new project system for benchmarks 2018-05-31 07:59:25 +02:00
Christian Kratky 9bea46adcb Remove unneeded _sealed_ keywords. Update docs. 2018-05-30 20:56:20 +02:00
Christian Kratky a10183628b Suspend keep alive checking while a packet is being received. 2018-05-29 23:13:53 +02:00
Christian Kratky 7e0017d14a Update docs. 2018-05-29 22:29:28 +02:00
Christian Kratky 62e9a333c7 Add several packet validations. 2018-05-29 22:21:16 +02:00
Christian Kratky 4838da48ef Replace a manual lock with the lock class. 2018-05-29 21:45:25 +02:00
Christian Kratky b5a43c416a Add validation of packet control type. 2018-05-29 21:39:40 +02:00
Christian Kratky c1297eadd4 Update docs 2018-05-29 21:22:46 +02:00
Christian Kratky 06886fe6c2 Update UWP version for RPC extension 2018-05-29 21:21:41 +02:00
Christian Kratky 137d1d181b Refactor ManagedMqttClientStorage 2018-05-29 21:21:30 +02:00
Christian 97d0286a31 Merge pull request #286 from JTrotta/master
ManagedClientStorage now works
2018-05-29 21:15:05 +02:00
Christian 782dcffc62 Update MQTTnet.sln 2018-05-29 21:08:32 +02:00
Christian 40f7a7c593 Delete duplicate file 2018-05-29 21:07:20 +02:00
Christian 44e5b2c2fd Merge pull request #274 from sebastienwarin/develop
Fix MqttProtocolVersion 3.1 client connection
2018-05-29 20:47:23 +02:00
JTrotta f844a8be5e ManagedMqttClietStorage now works 2018-05-29 11:32:16 +02:00
Gerardo 449d8aca65 Merge pull request #4 from chkr1011/master
merge last
2018-05-29 09:40:45 +02:00
Sébastien Warin 9b29f8c23a Fix MqttProtocolVersion 3.1 connection 2018-05-18 17:10:28 +02:00
Christian 5e79581662 Merge pull request #273 from sebastienwarin/develop
Adding delay between Pub&Sub in the test unit
2018-05-18 00:02:14 +02:00
Sébastien Warin 79a2952f94 Adding delay between Pub&Sub in the test unit 2018-05-17 12:29:50 +02:00
Christian 8077d8dfeb Refactor TopicFilterComparer 2018-05-16 23:07:39 +02:00
Christian d72ac9694e Merge pull request #270 from sebastienwarin/develop
Replace the Async coordination primitives & replace the MqttTopicFilterComparer to improve the performance
2018-05-16 21:45:59 +02:00
Sébastien Warin 5e0bc17341 Removing the debug log messages 2018-05-16 20:47:27 +02:00
Sébastien Warin 932aa1fd39 Fixes chkr1011's refactoing and pass all tests 2018-05-16 11:46:09 +02:00
Sébastien Warin 2c45e9fedd Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop
# Conflicts:
#	Frameworks/MQTTnet.NetStandard/Server/MqttClientPendingMessagesQueue.cs
#	Frameworks/MQTTnet.NetStandard/Server/MqttClientSessionsManager.cs
#	Frameworks/MQTTnet.NetStandard/Server/MqttRetainedMessagesManager.cs
2018-05-16 10:09:10 +02:00
Sébastien Warin c1352d50c1 Review code style to match with the existing code 2018-05-16 10:00:29 +02:00
Christian 2499d29196 Refactor events. 2018-05-16 00:12:09 +02:00
Christian fbf1cbc76e Refactor ConnectedClient statistics API 2018-05-16 00:08:42 +02:00
Christian 719838de3b Add new server option to disable/enable persistent sessions. 2018-05-15 22:04:05 +02:00
Sébastien Warin ba66c108fa Fixes and clean the new topic matcher from israellot 2018-05-15 17:39:45 +02:00
Sébastien Warin 5287bf5cac Codacy/PR Quality Review 2018-05-15 16:54:37 +02:00
Sébastien Warin 10740f12c4 Replace the Async coordination primitives 2018-05-15 15:28:14 +02:00
Christian 3e6edb92c5 Refactor ASP.NET integration. 2018-05-13 20:59:00 +02:00
Christian dc7b9414d9 Refactor logging. Remove TCP adapter from HTTP host if disabled. 2018-05-13 20:18:08 +02:00
Christian 8df8cb1eb6 Refactor logging and add benchmark. 2018-05-11 22:00:54 +02:00
Christian e14ea9a240 Add overflow strategy for pending messages queue. 2018-05-11 20:49:31 +02:00
Christian 57287a5303 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-05-11 20:06:16 +02:00
Christian febc8f774d Start a dedicated thread per client. 2018-05-11 20:06:10 +02:00
Christian e51042ed04 Update UWP version 2018-05-11 20:05:59 +02:00
Christian 910c123887 Merge pull request #266 from VladimirAkopyan/master
Limiting the growth of PendingMessagesQueue to a configurable Value
2018-05-11 20:05:36 +02:00
Christian e0899abaac Merge pull request #257 from JanEggers/AllocationBenchmark
[wip] improved serializer performance
2018-05-11 20:04:07 +02:00
Vladimir Akopyan 9df1bb2ff2 Merge branch 'develop' into master 2018-05-11 17:52:20 +02:00
VladimirAkopyan 7b987635f7 ref #230 Limiting the growth of PendingMessagesQueue to a configurable value. it will only store X lated messages, 250 by default.
https://github.com/chkr1011/MQTTnet/issues/230
2018-05-11 16:39:59 +01:00
JanEggers 8c37cf16c0 fixed tests 2018-05-10 22:28:01 +02:00
JanEggers c569c10740 dont use writer instance 2018-05-10 20:50:50 +02:00
Christian 325541642e Merge pull request #256 from JanEggers/AllocationBenchmark
added benchmark for serializers
2018-05-10 19:58:30 +02:00
JanEggers 97d91ec0f8 fixed code quality issues 2018-05-10 19:30:29 +02:00
JanEggers 17db90d5ab fixed build 2018-05-10 19:25:33 +02:00
JanEggers e7a7bb1a7b added benchmark for serializers 2018-05-10 19:18:31 +02:00
Christian b621806a7c Update build config 2018-05-10 16:27:27 +02:00
Christian 7720a3f091 Refactor thread management. 2018-05-10 16:27:12 +02:00
Christian b22b02a0b6 Refactor subscriptions manager 2018-05-03 22:22:07 +02:00
Christian d14088512b Refactoring 2018-05-03 20:47:15 +02:00
Christian 62527a91ac Complete merge 2018-05-03 20:44:41 +02:00
Christian f9e4a97eb8 Merge 2018-05-03 20:44:21 +02:00
Christian ff45be1f71 Update docs 2018-05-03 20:30:44 +02:00
Christian aaed2ed790 Process client messages in worker thread (extend options) 2018-05-03 20:30:40 +02:00
Christian d9501de252 Treat a connection handover as a clean disconnect. 2018-05-03 20:29:53 +02:00
Christian 9fdcb08364 Add benchmark app. 2018-05-03 20:29:02 +02:00
Christian 9f4f37bb51 Update nugets 2018-04-28 20:24:07 +02:00
Christian 49cf364352 Update docs 2018-04-28 13:05:45 +02:00
Christian b9a73cc23d Changed socket features. 2018-04-28 13:05:35 +02:00
Christian 357fd844d7 Fix TopicFilterComparer 2018-04-28 13:05:22 +02:00
Christian 74a5522965 Add topic filter tests from MQTT spec 2018-04-25 20:22:25 +02:00
Christian 84dab18c2a Fix broken UWP support. 2018-04-25 19:55:30 +02:00
Christian 9e90111b37 Fix several deadlocks 2018-04-24 20:54:18 +02:00
Christian ffb1645f14 Refactoring 2018-04-21 13:07:11 +02:00
Christian 6448b217d5 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-04-21 12:57:57 +02:00
Christian 1b84ab40ce Merge pull request #226 from israellot/develop
Remove useless sempahore object
2018-04-21 12:57:38 +02:00
Christian af8d1ec6be Refactoring 2018-04-21 12:55:09 +02:00
Israel Lot 04a4080768 removed performance section from sln file 2018-04-19 19:45:01 -03:00
Israel Lot 942bf70582 one less copy and allocation 2018-04-19 19:38:03 -03:00
Israel Lot b9f0ee2317 merge upstream 2018-04-19 19:07:03 -03:00
Christian cb09bac246 Refactor the WebSocket channel and remove the internal queue. 2018-04-18 23:10:00 +02:00
Christian 109e4b2cf1 Refactor the task timeout code to avoid still running tasks if the timeout is reached. 2018-04-18 21:14:31 +02:00
Israel Lot e4cf2978e6 Remove useless sempahore object 2018-04-17 21:43:10 -03:00
Christian 17b74f20c9 Migrate to Stream-less approach. 2018-04-17 22:29:23 +02:00
Christian ae11e31048 Refactoring 2018-04-17 20:37:56 +02:00
Christian e455ce9c78 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-04-17 20:16:08 +02:00
Christian 41df5cdd8b Update docs 2018-04-17 20:16:00 +02:00
Christian 383225d7f4 Merge pull request #225 from israellot/optmizations
Optmizations
2018-04-17 20:15:24 +02:00
Israel Lot a62c15ad1a Missing interface implementation 2018-04-16 14:46:46 -03:00
Israel Lot 5300742543 Avoid unnecessary enumeration for every packet 2018-04-16 14:30:52 -03:00
Israel Lot cd09a2f176 Fix code style 2018-04-16 14:08:04 -03:00
Israel Lot 11ba46d140 Remove useless stream flush 2018-04-16 14:01:07 -03:00
Israel Lot e006377e64 Fix zero lenght packets bug 2018-04-16 13:25:56 -03:00
Israel Lot 786fa53334 Fix unit tests for serializer 2018-04-16 13:07:35 -03:00
Israel Lot 9bc34e4406 Translate timeout exception 2018-04-16 13:07:19 -03:00
Israel Lot c915af8dad Disable Nagle on sockets, send packets in one shot. 2018-04-16 12:30:56 -03:00
Christian 98fbbc2864 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-04-15 21:07:48 +02:00
Christian d2049d63d6 Refactoring minor issues 2018-04-15 21:07:41 +02:00
Christian 63a12d4d40 Merge pull request #220 from israellot/optmizations
Replace double dictionary with a tuple key
2018-04-15 21:06:46 +02:00
Christian 9051f8275b Merge pull request #215 from biapar/patch-1
Update Startup.cs
2018-04-15 21:02:29 +02:00
Israel Lot a5f33bc244 Replace double dictionary with a tuple key 2018-04-13 23:00:36 -03:00
Christian b23d25217b Fix unit tests. 2018-04-11 23:12:27 +02:00
Christian 1df6798934 Fix issues in RPC extension. 2018-04-11 22:19:38 +02:00
Christian 9afff6d8a0 Merge branch 'develop' 2018-04-11 21:22:54 +02:00
Christian ec41efd860 Fix client dead lock and protocol version issues. 2018-04-11 21:22:08 +02:00
BP 580a431fbf Update Startup.cs 2018-04-09 10:59:34 +02:00
Christian c06d84e834 Renamed MqttServerAdapter to MqttTcpServerAdapter 2018-04-06 22:49:41 +02:00
Christian 06a299d212 Update README.md
Remove windows app
2018-04-05 23:40:05 +02:00
Christian f90985a1f9 Merge pull request #214 from JanEggers/Fix175
added tcp adapter
2018-04-05 23:39:10 +02:00
JanEggers 677beddf07 fixed code quality compliance 2018-04-05 16:03:28 +02:00
JanEggers 7154a7b3dc fixed tests 2018-04-05 15:55:08 +02:00
JanEggers 7de3d79d09 added tcp adapter 2018-04-05 14:58:13 +02:00
Christian 54a0265ef9 Fix UnitTests 2018-04-01 20:53:32 +02:00
Christian 8f96acaec4 Fixed a race condition in client and server. 2018-03-31 23:10:14 +02:00
Christian cea984cc2f Fix stream and socket handling. 2018-03-29 22:12:23 +02:00
Christian fcf748e980 Merge branch 'develop' 2018-03-25 14:45:35 +02:00
Christian e58cb3c9cd Update docs. 2018-03-25 14:42:43 +02:00
Christian 3587a8ebd1 Add new option which allows configuring the send interval for keep alive packets. 2018-03-25 14:42:34 +02:00
Christian 3193381b69 Refactor web socket stream. Add mqtt as default sub protocol. 2018-03-25 14:42:12 +02:00
Christian 7a9ddfc2b5 Fix packet identifier which is sent from the server. 2018-03-25 14:41:12 +02:00
Christian 447b2aa2c6 Add new extension methods. 2018-03-25 14:39:44 +02:00
Christian b3eaeea8a4 Fix log issue in UWP test app. 2018-03-25 14:38:36 +02:00
Christian 45b4c05867 Update version 2018-03-25 14:38:16 +02:00
Christian 49da66dcff Fix issue when disconnecting on UWP 2018-03-13 23:28:50 +01:00
Christian bb9d5586f0 Update nuspec 2018-03-13 20:31:01 +01:00
Christian c5d22f4b27 Update docs 2018-03-13 20:23:36 +01:00
Christian e57ec11ed8 Update libs 2018-03-13 20:23:31 +01:00
Christian 56acc82445 Fix null ref in server when using interceptor 2018-03-13 20:23:22 +01:00
Christian 6e828d091f Override ToString() for LogMessage 2018-03-13 20:23:07 +01:00
Christian e1d8697331 Fix wrong parsing and generating of MqttConnAck for version 3.1.0 2018-03-13 20:22:48 +01:00
Christian 90098c2006 Optimize dispatcher 2018-03-13 20:22:13 +01:00
Christian b3a25fb9e8 Fix subscription handling of _ManagedClient_. 2018-03-05 20:43:37 +01:00
Christian f85ad4965b Refactor keep alive monitoring and add unit tests. 2018-02-28 21:43:19 +01:00
Christian f5696b6fc0 Merge branch 'develop' 2018-02-21 21:33:01 +01:00
Christian c26555aca5 Refactor ManagedClient 2018-02-21 21:32:21 +01:00
Christian 0accb467b5 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-02-21 20:44:10 +01:00
Christian 3b34fd4750 Fix build 2018-02-21 20:44:05 +01:00
Christian abb216c055 Fix retained message handling 2018-02-21 20:43:22 +01:00
Christian 1760dc7d35 Fix async issues 2018-02-21 20:43:09 +01:00
Christian 034e7fd750 Add event for processed application message (managed client only) 2018-02-21 20:42:39 +01:00
Christian 76c7b319b8 Fix build errors 2018-02-21 20:42:05 +01:00
Christian 09010e95a2 Merge pull request #180 from lerppana/managed_unsubscribe_fix
Fix ManagedMqttClient missing call to unsubscribe topics
2018-02-21 20:09:10 +01:00
Lassi Laati 2341d66192 Fix ManagedMqttClient missing call to unsubscribe topics 2018-02-20 09:23:47 +02:00
Christian 21586b7710 Merge branch 'master' of https://github.com/chkr1011/MQTTnet 2018-02-04 20:10:11 +01:00
Christian b426ae1198 Update docs 2018-02-04 20:06:01 +01:00
Christian e9db9d65ac Update README.md 2018-02-04 20:05:34 +01:00
Christian 59dcbf4c0c Add server events for subscribed and unsubscribed topics. Add pending messages count for connected clients. 2018-02-02 22:44:21 +01:00
Christian a204d233f6 Update configs 2018-02-02 00:47:00 +01:00
Christian 26cd84c88c Fix generation of packet identifier. 2018-02-02 00:46:47 +01:00
Christian 5f77255893 Update docs 2018-01-27 14:12:54 +01:00
Christian 8856a7aa34 Fix broken package reader 2018-01-26 23:56:22 +01:00
Christian 30754433eb Add server methods for controlling the client subscriptions. 2018-01-26 22:06:21 +01:00
Christian 751ac19c4b Fix reading more data than required for the body. 2018-01-26 21:25:56 +01:00
Christian 1415e4b878 Covnert the body buffer to a memory stream which will grow automatically. 2018-01-24 20:49:47 +01:00
Christian e56203faac Update docs 2018-01-24 20:16:47 +01:00
Christian 64c997a4a2 Merge pull request #163 from kpreisser/fixInfiniteLoop
Fix infinite loop when the client closes the connection
2018-01-24 20:12:15 +01:00
Christian 391ee34a0f Merge pull request #166 from kpreisser/fixDecodeRemainingLength
Fix the algorithm for decoding the body length
2018-01-24 20:09:14 +01:00
kpreisser 88de5047bc Fix the algorithm for decoding the remaining length to allow a length greater than 2,097,151 bytes.
See: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os.html#_Toc442180732
2018-01-24 15:32:36 +01:00
kpreisser d020e809a1 Fix infinite loop that can occur when the client closes the connection before sending the complete packet body. 2018-01-23 10:45:58 +01:00
Christian 8b2b8d41df Update docs 2018-01-22 21:11:44 +01:00
Christian 40c33ac639 Refactoring 2018-01-22 21:11:35 +01:00
Christian 002e4b8d69 Fix broken unit tests 2018-01-22 20:55:50 +01:00
Christian c060c379d3 Add thrown exception for disconnected event 2018-01-22 20:55:06 +01:00
Christian 4d13407a83 Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2018-01-21 14:33:33 +01:00
Christian d737f550c7 Add encrypted code signing key 2018-01-21 14:33:29 +01:00
Christian 5e8d5b9219 Add documents 2018-01-21 14:29:43 +01:00
Christian f98f21ffdf Update libs 2018-01-21 14:29:36 +01:00
Christian ec9e64ebfb Update docs 2018-01-21 14:14:04 +01:00
Christian 39672970e2 Update 3rd-Partly libs 2018-01-21 14:13:50 +01:00
Christian 5becf7980a Merge pull request #157 from kpreisser/trueAsync
Use asynchronous methods for blocking operations
2018-01-21 14:12:29 +01:00
Christian c7c84ad39b Make clients interfaces disposable. 2018-01-21 14:10:23 +01:00
Christian 8773117493 Fix an issue which adds a delay after every accepted connection. 2018-01-21 14:09:34 +01:00
kpreisser bb697e1bd9 Follow-Up: Add missing ConfigureAwait() call. 2018-01-17 11:29:48 +01:00
kpreisser e1a9aa7d03 Adjust the MqttClientPendingMessagesQueue and the MqttPacketReader to use asynchronous methods for long-running/blocking operations.
Otherwise, Worker Threads from the .NET Threadpool are blocked while waiting for the next client message, and while waiting for the next message to send.
2018-01-17 11:10:39 +01:00
Christian Kratky 312773d054 Add password protected code signing certificate to enable build process. 2017-12-22 12:02:25 +01:00
Christian Kratky 1ee48a978f Merge develop 2017-12-18 14:17:31 +01:00
Christian Kratky 5ddb6b77e2 Update documentation 2017-12-14 13:24:50 +01:00
Christian Kratky e0284886b5 Added the bound IP address to the server options. 2017-12-14 13:23:12 +01:00
Christian Kratky 44c07c2034 Fix broken ASP.NET Core integration. 2017-12-14 13:12:18 +01:00
Christian Kratky f6b38081fc Update documents. 2017-12-12 14:30:28 +01:00
Christian c570509628 Merge pull request #139 from FourOnes/develop
fixed: Compile Source Code Occur Errors On Mac Machine
2017-12-12 14:27:04 +01:00
limingru e98ff1d6d6 uncomment code 2017-12-12 17:26:16 +08:00
limingru 0f54663789 fixed: Compile Source Code Occur Errors On Mac Machine 2017-12-12 17:21:22 +08:00
Christian Kratky f91d935708 Add the ClientId to the application message interceptor. 2017-12-11 17:10:27 +01:00
Christian Kratky fb8b60fccc Add overload for subscribing. 2017-12-08 21:12:05 +01:00
Christian Kratky ad8506cc30 Update documents 2017-12-07 20:41:44 +01:00
Christian Kratky d6f88acb8d Merge branch 'develop' of https://github.com/chkr1011/MQTTnet into develop 2017-12-07 20:37:49 +01:00
Christian Kratky 333fc4c387 Fixed an TLS issue in the MqttClientOptionsBuilder; Fix a subscription issue in the managed client. 2017-12-07 20:35:29 +01:00
Christian 5f9214e9a2 Merge pull request #134 from cvellan/patch-3
Serialized certificates loaded as X509Certificate2
2017-12-05 13:18:16 +01:00
cvellan f974dcb647 Serialized certificates loaded as X509Certificate2
Instances of X509Certificate2 passed into an MqttClientOptionsBuilder lose data and functionality by being loaded as an X509Certificate.
2017-12-05 10:13:07 +11:00
Christian Kratky 2cb1c544f5 Add extension method for subscriptions 2017-12-04 22:40:44 +01:00
Christian Kratky 644e948489 Fix keep alive checks in server 2017-12-04 13:52:14 +01:00
Christian Kratky d12d2648b7 Add extension for RPC calls; replace locks; Refactored storage in Managed Client 2017-12-04 10:21:37 +01:00
Christian Kratky 0ee3c8e135 Add statistics of last sent packets to the _ConnectedClient_. 2017-11-28 21:19:30 +01:00
Christian Kratky bc959a8c3d Performance optimizations 2017-11-27 00:25:45 +01:00
Christian Kratky 69781d822a Update docs, fix managed client connection issue 2017-11-26 22:57:56 +01:00
Christian Kratky 611fabcd01 Performance optimizations 2017-11-25 23:10:48 +01:00
Christian Kratky 24ab285066 Update project settings 2017-11-25 20:33:04 +01:00
Christian Kratky ee6ec14bf8 Add interface for server options. Add context class for connection validator (hide internal packets). 2017-11-25 20:12:50 +01:00
Christian Kratky f9d67e2cd2 Merge proces, enable signing of the assembly. 2017-11-25 19:55:26 +01:00
Christian a72516fdcc Update README.md 2017-11-25 19:50:31 +01:00
Christian Kratky ebfc6aab6b Fix nuget spec 2017-11-25 16:20:07 +01:00
Gerardo d076aac421 Merge pull request #3 from chkr1011/develop
Original Develop
2017-10-30 11:08:41 +01:00
Gerardo e6d811ea7c Merge pull request #2 from chkr1011/develop
From develop
2017-10-26 12:09:02 +02:00
501 changed files with 24121 additions and 6963 deletions
+1 -6
View File
@@ -1,8 +1,3 @@
exclude:
- /Frameworks/.*
- /MQTTnet.TestApp.NetCore/Program.cs
- /Tests/MQTTnet.TestApp.NetFramework/.*
- /Tests/MQTTnet.TestApp.UniversalWindows/.*
component_depth: 1
component_depth: 2
languages:
- csharp
+3 -2
View File
@@ -235,6 +235,7 @@ FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
/*/**/package-lock.json
# Typescript v1 declaration files
typings/
@@ -287,7 +288,7 @@ __pycache__/
*.odx.cs
*.xsd.cs
Build/nuget.exe
*.js
*.map
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
-10
View File
@@ -1,10 +0,0 @@
language: csharp
solution: MQTTnet.sln
matrix:
include:
- dotnet: 2.0.0
mono: none
dist: trusty
env: DOTNETCORE=1 # optional, can be used to take different code paths in your script
- mono: latest
+16 -11
View File
@@ -2,27 +2,32 @@
<package >
<metadata>
<id>MQTTnet.AspNetCore</id>
<version>2.5.3</version>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<license type="file">LICENSE</license>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is a support library to integrate MQTTnet into AspNetCore.</description>
<releaseNotes>* Updated to MQTTnet 2.5.3.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2017</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<dependencies>
<group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="2.5.3-rc1" />
</group>
<dependency id="MQTTnet" version="$nugetVersion" />
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="2.1.3" />
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.3" />
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.1.1" />
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="2.1.1" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- .NET Standard 2.0 -->
<file src="..\Frameworks\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\"/>
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\"/>
</files>
</package>
</package>
@@ -0,0 +1,43 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.Extensions.ManagedClient</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<license type="file">LICENSE</license>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- .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\"/>
<!-- 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\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net462\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net470\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net471\"/>
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net472\"/>
</files>
</package>
+43
View File
@@ -0,0 +1,43 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.Extensions.Rpc</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<license type="file">LICENSE</license>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<dependencies>
<dependency id="MQTTnet" version="$nugetVersion" />
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- .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\"/>
<!-- 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\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net462\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net470\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net471\"/>
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\net472\"/>
</files>
</package>
+42
View File
@@ -0,0 +1,42 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet.NETStandard</id>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<license type="file">LICENSE</license>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). This package contains the .NET Standard version of the library only.</description>
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<dependencies>
<group targetFramework="netstandard1.3">
<dependency id="NETStandard.Library" version="1.3.0" />
<dependency id="System.Net.Security" version="4.3.2" />
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="NETStandard.Library" version="2.0.0" />
<dependency id="System.Net.Security" version="4.3.2" />
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- .NET Standard 1.3 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
<!-- .NET Standard 2.0 -->
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
</files>
</package>
+49 -26
View File
@@ -2,68 +2,91 @@
<package >
<metadata>
<id>MQTTnet</id>
<version>2.5.3</version>
<version>0.0.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<license type="file">LICENSE</license>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
<releaseNotes>* [Core] Removed all dependencies to other libraries (BREAKING CHANGE!).
* [Core] Updated SDK libraries.
* [Client] Fixed broken support for WebSocketSecure connections (Thanks to @StAI).
<releaseNotes>
* [Core] Added support for MQTTv5 packages.
* [Core] Performance improvements.
* [Core] Removed obsolete methods.
* [Core] Fixed a memory leak when processing lots of messages (thanks to @tschanko)
* [Core] Added more overloads for MQTT factory.
* [Core] The client password is now hidden from the logs (replaced with **** if set).
* [Core] Fixed a memory leak when using SSL connections (thanks to @biovoid).
* [Client] Added validation of topics before publishing.
* [Client] Added new MQTTv5 features to options builder.
* [Client] Added uniform API across all supported MQTT versions (BREAKING CHANGE!)
* [Client] The client will now avoid sending an ACK if an exception has been thrown in message handler (thanks to @ramonsmits).
* [Client] Fixed issues in QoS 2 handling which leads to message loss.
* [Client] Replaced all events with proper async compatible handlers (BREAKING CHANGE!).
* [Client] Added more configuration values to TCP endpoint options.
* [Client] Added used PacketIdentifier to publish result.
* [ManagedClient] Replaced all events with proper async compatible handlers (BREAKING CHANGE!).
* [ManagedClient] The log ID is now propagated to the internal client (thanks to @vbBerni).
* [ManagedClient] Added validation of topics before publishing.
* [ManagedClient] The internal MQTT client is now closed properly (thanks to @vbBerni).
* [Server] Added support for MQTTv5 clients. The server will still return _success_ for all cases at the moment even if more granular codes are available.
* [Server] Fixed issues in QoS 2 handling which leads to message loss.
* [Server] Replaced all events with proper async compatible handlers (BREAKING CHANGE!).
* [Server] The used logger instance is now propagated to the WebSocket server adapter.
* [Server] Added the flag "IsSecureConnection" which is set to true when the connection is encrypted.
* [Server] Fixed wrong will message behavior when stopping server (thanks to @JohBa)
* [Server] Added validation of topics before publishing.
* [Server] Added more configuration values to TCP endpoint options.
* [MQTTnet Server] Added as first Alpha version of standalone cross platform MQTT server.
* [Note] Due to MQTTv5 a lot of new classes were introduced. This required adding new namespaces as well. Most classes are backward compatible but new namespaces must be added.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2017</copyright>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
<dependencies>
<group targetFramework="netstandard1.3">
<dependency id="NETStandard.Library" version="1.3.0" />
<dependency id="System.Net.Security" version="4.3.2" />
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.1" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="NETStandard.Library" version="2.0.0" />
<dependency id="System.Net.Security" version="4.3.2" />
<dependency id="System.Net.WebSockets" version="4.3.0" />
<dependency id="System.Net.WebSockets.Client" version="4.3.1" />
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
</group>
<group targetFramework="uap10.0">
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="5.4.1" />
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.8" />
</group>
<group targetFramework="net452">
</group>
<group targetFramework="net461">
</group>
</dependencies>
</metadata>
<files>
<!-- License -->
<file src="..\LICENSE" />
<!-- .NET Standard 1.3 -->
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\netstandard1.3\MQTTnet.Core.*" target="lib\netstandard1.3\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
<!-- .NET Standard 2.0 -->
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\netstandard2.0\MQTTnet.Core.*" target="lib\netstandard2.0\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
<!-- Universal Windows -->
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\uap10.0\MQTTnet.Core.*" target="lib\uap10.0\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\"/>
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\"/>
<!-- .NET Framework -->
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\net452\MQTTnet.Core.*" target="lib\net452\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\net452\MQTTnet.*" target="lib\net452\"/>
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\net461\MQTTnet.Core.*" target="lib\net461\"/>
<file src="..\Frameworks\MQTTnet.Netstandard\bin\Release\net461\MQTTnet.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net461\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net462\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net470\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net471\"/>
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\net472\"/>
</files>
</package>
+61 -16
View File
@@ -1,23 +1,68 @@
param([string]$assemblyVersion, [string]$nugetVersion)
if ([string]::IsNullOrEmpty($version)) {$version = "0.0.1"}
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
$path = &$vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath
if ($path) {
$msbuild = join-path $path 'MSBuild\15.0\Bin\MSBuild.exe'
Write-Host
Write-Host "Assembly version = $assemblyVersion"
Write-Host "Nuget version = $nugetVersion"
Write-Host "MSBuild path = $msbuild"
Write-Host
&$msbuild ..\Frameworks\MQTTnet.Netstandard\MQTTnet.Netstandard.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
&$msbuild ..\Frameworks\MQTTnet.Netstandard\MQTTnet.Netstandard.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
&$msbuild ..\Frameworks\MQTTnet.Netstandard\MQTTnet.Netstandard.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
&$msbuild ..\Frameworks\MQTTnet.Netstandard\MQTTnet.Netstandard.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
&$msbuild ..\Frameworks\MQTTnet.Netstandard\MQTTnet.Netstandard.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
&$msbuild ..\Frameworks\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m
# Build the core library
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
Remove-Item .\NuGet -Force -Recurse
New-Item -ItemType Directory -Force -Path .\NuGet
.\NuGet.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\NuGet.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
}
# Build the ASP.NET Core 2.0 extension
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# Build the RPC extension
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# Build the Managed Client extension
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
# Build MQTTnet.Server
Remove-Item ..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2 -Recurse -Force -ErrorAction SilentlyContinue
&$msbuild ..\Source\MQTTnet.Server\MQTTnet.Server.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp2.2" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2"
$destination = "..\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)
# Create NuGet packages.
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
(Get-Content MQTTnet.AspNetCore.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.AspNetCore.nuspec
Copy-Item MQTTnet.Extensions.Rpc.nuspec -Destination MQTTnet.Extensions.Rpc.nuspec.old -Force
(Get-Content MQTTnet.Extensions.Rpc.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.Rpc.nuspec
Copy-Item MQTTnet.Extensions.ManagedClient.nuspec -Destination MQTTnet.Extensions.ManagedClient.nuspec.old -Force
(Get-Content MQTTnet.Extensions.ManagedClient.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.ManagedClient.nuspec
New-Item -ItemType Directory -Force -Path .\NuGet
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.NETStandard.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
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
Binary file not shown.
BIN
View File
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
param([string]$apiKey)
$files = Get-ChildItem -Path ".\NuGet" -Filter "*.nupkg"
foreach ($file in $files)
{
Write-Host "Uploading: " $file
.\nuget.exe push $file.Fullname $apiKey -NoSymbols -Source https://api.nuget.org/v3/index.json
}
+9
View File
@@ -0,0 +1,9 @@
# Import codeSigningKey.pfx
In order to import the key for code signing on a new developer machine use the following command within the VS developer command line:
> sn –i codeSigningKey.pfx VS_KEY_EFCA4C5B6DFD4B4F
The container name may be different.
# Check if the assembly has a strong name
> sn -vf MQTTnet.dll
@@ -1,52 +0,0 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using MQTTnet.Core.Server;
using System.Linq;
namespace MQTTnet.AspNetCore
{
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseMqttEndpoint(this IApplicationBuilder app, string path = "/mqtt")
{
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.Request.Path == path && context.WebSockets.IsWebSocketRequest)
{
string subprotocol = null;
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues)
&& requestedSubProtocolValues.Count > 0
&& requestedSubProtocolValues.Any(v => v.ToLower() == "mqtt")
)
{
subprotocol = "mqtt";
}
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(subprotocol))
{
await adapter.AcceptWebSocketAsync(webSocket);
}
}
else
{
await next();
}
});
return app;
}
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
{
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
configure(server);
return app;
}
}
}
@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyVersion>2.5.2.0</AssemblyVersion>
<FileVersion>2.5.2.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj" />
</ItemGroup>
</Project>
@@ -1,42 +0,0 @@
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;
namespace MQTTnet.AspNetCore
{
public class MqttWebSocketServerAdapter : IMqttServerAdapter, IDisposable
{
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
public Task StartAsync(MqttServerOptions options)
{
return Task.CompletedTask;
}
public Task StopAsync()
{
return Task.CompletedTask;
}
public Task AcceptWebSocketAsync(WebSocket webSocket)
{
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
var channel = new MqttWebSocketServerChannel(webSocket);
var clientAdapter = new MqttChannelAdapter(channel, new MqttPacketSerializer(), new MqttNetLogger());
var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter);
ClientAccepted?.Invoke(this, eventArgs);
return eventArgs.SessionTask;
}
public void Dispose()
{
StopAsync();
}
}
}
@@ -1,60 +0,0 @@
using System;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Implementations;
namespace MQTTnet.AspNetCore
{
public class MqttWebSocketServerChannel : IMqttChannel, IDisposable
{
private WebSocket _webSocket;
public MqttWebSocketServerChannel(WebSocket webSocket)
{
_webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket));
SendStream = new WebSocketStream(_webSocket);
ReceiveStream = SendStream;
}
public Stream SendStream { get; private set; }
public Stream ReceiveStream { get; private set; }
public Task ConnectAsync()
{
return Task.CompletedTask;
}
public async Task DisconnectAsync()
{
if (_webSocket == null)
{
return;
}
try
{
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
finally
{
Dispose();
}
}
public void Dispose()
{
SendStream?.Dispose();
ReceiveStream?.Dispose();
_webSocket?.Dispose();
SendStream = null;
ReceiveStream = null;
_webSocket = null;
}
}
}
@@ -1,28 +0,0 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Server;
namespace MQTTnet.AspNetCore
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
services.AddSingleton(options);
services.AddSingleton<IMqttNetLogger>(new MqttNetLogger());
services.AddSingleton<MqttHostedServer>();
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
services.AddSingleton<IMqttServer>(s => s.GetService<MqttHostedServer>());
services.AddSingleton<MqttWebSocketServerAdapter>();
services.AddSingleton<IMqttServerAdapter>(s => s.GetService<MqttWebSocketServerAdapter>());
return services;
}
}
}
@@ -1,50 +0,0 @@
using System;
using System.Text;
using MQTTnet.Core.Diagnostics;
namespace MQTTnet.Diagnostics
{
public static class MqttNetConsoleLogger
{
private static readonly object Lock = new object();
public static void ForwardToConsole()
{
MqttNetGlobalLog.LogMessagePublished -= PrintToConsole;
MqttNetGlobalLog.LogMessagePublished += PrintToConsole;
}
private static void PrintToConsole(object sender, MqttNetLogMessagePublishedEventArgs e)
{
var output = new StringBuilder();
output.AppendLine($">> [{e.TraceMessage.Timestamp:O}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}");
if (e.TraceMessage.Exception != null)
{
output.AppendLine(e.TraceMessage.Exception.ToString());
}
lock (Lock)
{
var backupColor = Console.ForegroundColor;
switch (e.TraceMessage.Level)
{
case MqttNetLogLevel.Error:
Console.ForegroundColor = ConsoleColor.Red;
break;
case MqttNetLogLevel.Warning:
Console.ForegroundColor = ConsoleColor.Yellow;
break;
case MqttNetLogLevel.Info:
Console.ForegroundColor = ConsoleColor.Green;
break;
case MqttNetLogLevel.Verbose:
Console.ForegroundColor = ConsoleColor.Gray;
break;
}
Console.Write(output);
Console.ForegroundColor = backupColor;
}
}
}
}
@@ -1,26 +0,0 @@
using System;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Implementations
{
public class MqttClientAdapterFactory : IMqttClientAdapterFactory
{
public IMqttChannelAdapter CreateClientAdapter(IMqttClientChannelOptions options, IMqttNetLogger logger)
{
if (options == null) throw new ArgumentNullException(nameof(options));
switch (options)
{
case MqttClientTcpOptions tcpOptions:
return new MqttChannelAdapter(new MqttTcpChannel(tcpOptions), new MqttPacketSerializer(), logger);
case MqttClientWebSocketOptions webSocketOptions:
return new MqttChannelAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketSerializer(), logger);
default:
throw new NotSupportedException();
}
}
}
}
@@ -1,75 +0,0 @@
#if WINDOWS_UWP
using System;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server;
using Windows.Networking.Sockets;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Implementations
{
public class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private readonly IMqttNetLogger _logger;
private StreamSocketListener _defaultEndpointSocket;
public MqttServerAdapter(IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
public async Task StartAsync(MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (_defaultEndpointSocket != null) throw new InvalidOperationException("Server is already started.");
if (options.DefaultEndpointOptions.IsEnabled)
{
_defaultEndpointSocket = new StreamSocketListener();
await _defaultEndpointSocket.BindServiceNameAsync(options.GetDefaultEndpointPort().ToString(), SocketProtectionLevel.PlainSocket);
_defaultEndpointSocket.ConnectionReceived += AcceptDefaultEndpointConnectionsAsync;
}
if (options.TlsEndpointOptions.IsEnabled)
{
throw new NotSupportedException("TLS servers are not supported for UWP apps.");
}
}
public Task StopAsync()
{
if (_defaultEndpointSocket != null)
{
_defaultEndpointSocket.ConnectionReceived -= AcceptDefaultEndpointConnectionsAsync;
}
_defaultEndpointSocket?.Dispose();
_defaultEndpointSocket = null;
return Task.FromResult(0);
}
public void Dispose()
{
StopAsync();
}
private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket), new MqttPacketSerializer(), _logger);
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
}
catch (Exception exception)
{
_logger.Error<MqttServerAdapter>(exception, "Error while accepting connection at default endpoint.");
}
}
}
}
#endif
@@ -1,147 +0,0 @@
#if NET452 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Implementations
{
public class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private readonly IMqttNetLogger _logger;
private CancellationTokenSource _cancellationTokenSource;
private Socket _defaultEndpointSocket;
private Socket _tlsEndpointSocket;
private X509Certificate2 _tlsCertificate;
public MqttServerAdapter(IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
public Task StartAsync(MqttServerOptions options)
{
if (_cancellationTokenSource != null) throw new InvalidOperationException("Server is already started.");
_cancellationTokenSource = new CancellationTokenSource();
if (options.DefaultEndpointOptions.IsEnabled)
{
_defaultEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_defaultEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetDefaultEndpointPort()));
_defaultEndpointSocket.Listen(options.ConnectionBacklog);
Task.Run(() => AcceptDefaultEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}
if (options.TlsEndpointOptions.IsEnabled)
{
if (options.TlsEndpointOptions.Certificate == null)
{
throw new ArgumentException("TLS certificate is not set.");
}
_tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
if (!_tlsCertificate.HasPrivateKey)
{
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
}
_tlsEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_tlsEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetTlsEndpointPort()));
_tlsEndpointSocket.Listen(options.ConnectionBacklog);
Task.Run(() => AcceptTlsEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}
return Task.FromResult(0);
}
public Task StopAsync()
{
_cancellationTokenSource?.Cancel(false);
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
_defaultEndpointSocket?.Dispose();
_defaultEndpointSocket = null;
_tlsCertificate = null;
_tlsEndpointSocket?.Dispose();
_tlsEndpointSocket = null;
return Task.FromResult(0);
}
public void Dispose()
{
StopAsync();
}
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
//todo: else branch can be used with min dependency NET46
#if NET452 || NET461
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false);
#else
var clientSocket = await _defaultEndpointSocket.AcceptAsync().ConfigureAwait(false);
#endif
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer(), _logger);
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
}
catch (Exception exception)
{
_logger.Error<MqttServerAdapter>(exception, "Error while accepting connection at default endpoint.");
//excessive CPU consumed if in endless loop of socket errors
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
}
}
}
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
#if NET452 || NET461
var clientSocket = await Task.Factory.FromAsync(_tlsEndpointSocket.BeginAccept, _tlsEndpointSocket.EndAccept, null).ConfigureAwait(false);
#else
var clientSocket = await _tlsEndpointSocket.AcceptAsync().ConfigureAwait(false);
#endif
var sslStream = new SslStream(new NetworkStream(clientSocket));
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger);
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
}
catch (Exception exception)
{
_logger.Error<MqttServerAdapter>(exception, "Error while accepting connection at TLS endpoint.");
//excessive CPU consumed if in endless loop of socket errors
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
}
}
}
}
}
#endif
@@ -1,133 +0,0 @@
#if WINDOWS_UWP
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Security.Cryptography.Certificates;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
namespace MQTTnet.Implementations
{
public sealed class MqttTcpChannel : IMqttChannel, IDisposable
{
private readonly MqttClientTcpOptions _options;
private StreamSocket _socket;
public MqttTcpChannel(MqttClientTcpOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public MqttTcpChannel(StreamSocket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
CreateStreams();
}
public Stream SendStream { get; private set; }
public Stream ReceiveStream { get; private set; }
public static Func<MqttClientTcpOptions, IEnumerable<ChainValidationResult>> CustomIgnorableServerCertificateErrorsResolver { get; set; }
public async Task ConnectAsync()
{
if (_socket == null)
{
_socket = new StreamSocket();
}
if (!_options.TlsOptions.UseTls)
{
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString());
}
else
{
_socket.Control.ClientCertificate = LoadCertificate(_options);
foreach (var ignorableChainValidationResult in ResolveIgnorableServerCertificateErrors())
{
_socket.Control.IgnorableServerCertificateErrors.Add(ignorableChainValidationResult);
}
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), SocketProtectionLevel.Tls12);
}
CreateStreams();
}
public Task DisconnectAsync()
{
Dispose();
return Task.FromResult(0);
}
public void Dispose()
{
SendStream?.Dispose();
SendStream = null;
ReceiveStream?.Dispose();
ReceiveStream = null;
_socket?.Dispose();
_socket = null;
}
private void CreateStreams()
{
SendStream = _socket.OutputStream.AsStreamForWrite();
ReceiveStream = _socket.InputStream.AsStreamForRead();
}
private static Certificate LoadCertificate(MqttClientTcpOptions options)
{
if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any())
{
return null;
}
if (options.TlsOptions.Certificates.Count > 1)
{
throw new NotSupportedException("Only one client certificate is supported for UWP.");
}
return new Certificate(options.TlsOptions.Certificates.First().AsBuffer());
}
private IEnumerable<ChainValidationResult> ResolveIgnorableServerCertificateErrors()
{
if (CustomIgnorableServerCertificateErrorsResolver != null)
{
return CustomIgnorableServerCertificateErrorsResolver(_options);
}
var result = new List<ChainValidationResult>();
if (_options.TlsOptions.IgnoreCertificateRevocationErrors)
{
result.Add(ChainValidationResult.RevocationInformationMissing);
//_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked); Not supported.
result.Add(ChainValidationResult.RevocationFailure);
}
if (_options.TlsOptions.IgnoreCertificateChainErrors)
{
result.Add(ChainValidationResult.IncompleteChain);
}
if (_options.TlsOptions.AllowUntrustedCertificates)
{
result.Add(ChainValidationResult.Untrusted);
}
return result;
}
}
}
#endif
@@ -1,158 +0,0 @@
#if NET452 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using System.IO;
using System.Linq;
namespace MQTTnet.Implementations
{
public sealed class MqttTcpChannel : IMqttChannel, IDisposable
{
private readonly MqttClientTcpOptions _options;
//todo: this can be used with min dependency NetStandard1.6
#if NET452 || NET461
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
public static int BufferSize { get; set; } = 4096 * 20; // Can be changed for fine tuning by library user.
#endif
private Socket _socket;
private SslStream _sslStream;
/// <summary>
/// called on client sockets are created in connect
/// </summary>
public MqttTcpChannel(MqttClientTcpOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
/// called on server, sockets are passed in
/// connect will not be called
/// </summary>
public MqttTcpChannel(Socket socket, SslStream sslStream)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
_sslStream = sslStream;
CreateStreams(socket, sslStream);
}
public Stream SendStream { get; private set; }
public Stream ReceiveStream { get; private set; }
public static Func<X509Certificate, X509Chain, SslPolicyErrors, MqttClientTcpOptions, bool> CustomCertificateValidationCallback { get; set; }
public async Task ConnectAsync()
{
if (_socket == null)
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}
//todo: else brach can be used with min dependency NET46
#if NET452 || NET461
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, _options.Server, _options.GetPort(), null).ConfigureAwait(false);
#else
await _socket.ConnectAsync(_options.Server, _options.GetPort()).ConfigureAwait(false);
#endif
if (_options.TlsOptions.UseTls)
{
_sslStream = new SslStream(new NetworkStream(_socket, true), false, InternalUserCertificateValidationCallback);
await _sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(_options), SslProtocols.Tls12, _options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
}
CreateStreams(_socket, _sslStream);
}
public Task DisconnectAsync()
{
Dispose();
return Task.FromResult(0);
}
public void Dispose()
{
_socket?.Dispose();
_socket = null;
_sslStream?.Dispose();
_sslStream = null;
}
private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (CustomCertificateValidationCallback != null)
{
return CustomCertificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _options);
}
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.RevocationStatusUnknown || c.Status == X509ChainStatusFlags.Revoked || c.Status == X509ChainStatusFlags.RevocationStatusUnknown))
{
if (!_options.TlsOptions.IgnoreCertificateRevocationErrors)
{
return false;
}
}
if (chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.PartialChain))
{
if (!_options.TlsOptions.IgnoreCertificateChainErrors)
{
return false;
}
}
return _options.TlsOptions.AllowUntrustedCertificates;
}
private static X509CertificateCollection LoadCertificates(MqttClientTcpOptions options)
{
var certificates = new X509CertificateCollection();
if (options.TlsOptions.Certificates == null)
{
return certificates;
}
foreach (var certificate in options.TlsOptions.Certificates)
{
certificates.Add(new X509Certificate(certificate));
}
return certificates;
}
private void CreateStreams(Socket socket, Stream sslStream)
{
var stream = sslStream ?? new NetworkStream(socket);
//cannot use this as default buffering prevents from receiving the first connect message
//need two streams otherwise read and write have to be synchronized
//todo: if branch can be used with min dependency NetStandard1.6
#if NET452 || NET461
SendStream = new BufferedStream(stream, BufferSize);
ReceiveStream = new BufferedStream(stream, BufferSize);
#else
SendStream = stream;
ReceiveStream = stream;
#endif
}
}
}
#endif
@@ -1,103 +0,0 @@
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using System;
using System.IO;
using System.Net.WebSockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
namespace MQTTnet.Implementations
{
public sealed class MqttWebSocketChannel : IMqttChannel, IDisposable
{
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
public static int BufferSize { get; set; } = 4096 * 20; // Can be changed for fine tuning by library user.
private readonly MqttClientWebSocketOptions _options;
private ClientWebSocket _webSocket;
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public Stream SendStream { get; private set; }
public Stream ReceiveStream { get; private set; }
public async Task ConnectAsync()
{
var uri = _options.Uri;
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase) && !uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase))
{
if (_options.TlsOptions?.UseTls == false)
{
uri = "ws://" + uri;
}
else
{
uri = "wss://" + uri;
}
}
_webSocket = new ClientWebSocket();
if (_options.RequestHeaders != null)
{
foreach (var requestHeader in _options.RequestHeaders)
{
_webSocket.Options.SetRequestHeader(requestHeader.Key, requestHeader.Value);
}
}
if (_options.SubProtocols != null)
{
foreach (var subProtocol in _options.SubProtocols)
{
_webSocket.Options.AddSubProtocol(subProtocol);
}
}
if (_options.CookieContainer != null)
{
_webSocket.Options.Cookies = _options.CookieContainer;
}
if (_options.TlsOptions?.UseTls == true && _options.TlsOptions?.Certificates != null)
{
_webSocket.Options.ClientCertificates = new X509CertificateCollection();
foreach (var certificate in _options.TlsOptions.Certificates)
{
_webSocket.Options.ClientCertificates.Add(new X509Certificate(certificate));
}
}
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false);
SendStream = new WebSocketStream(_webSocket);
ReceiveStream = SendStream;
}
public async Task DisconnectAsync()
{
if (_webSocket == null)
{
return;
}
if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
{
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false);
}
Dispose();
}
public void Dispose()
{
_webSocket?.Dispose();
_webSocket = null;
}
}
}
@@ -1,129 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Exceptions;
namespace MQTTnet.Implementations
{
public class WebSocketStream : Stream
{
private readonly WebSocket _webSocket;
private readonly byte[] _chunkBuffer = new byte[MqttWebSocketChannel.BufferSize];
private readonly Queue<byte> _buffer = new Queue<byte>(MqttWebSocketChannel.BufferSize);
public WebSocketStream(WebSocket webSocket)
{
_webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket));
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => throw new NotSupportedException();
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override void Flush()
{
}
public override Task FlushAsync(CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
public override int Read(byte[] buffer, int offset, int count)
{
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
var bytesRead = 0;
// Use existing date from buffer.
while (count > 0 && _buffer.Any())
{
buffer[offset++] = _buffer.Dequeue();
count--;
bytesRead++;
}
if (count == 0)
{
return bytesRead;
}
while (_webSocket.State == WebSocketState.Open)
{
await FetchChunkAsync(cancellationToken);
while (count > 0 && _buffer.Any())
{
buffer[offset++] = _buffer.Dequeue();
count--;
bytesRead++;
}
if (count == 0)
{
return bytesRead;
}
}
if (_webSocket.State == WebSocketState.Closed)
{
throw new MqttCommunicationException("WebSocket connection closed.");
}
return bytesRead;
}
public override void Write(byte[] buffer, int offset, int count)
{
WriteAsync(buffer, offset, count).GetAwaiter().GetResult();
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _webSocket.SendAsync(new ArraySegment<byte>(buffer, offset, count), WebSocketMessageType.Binary, true, cancellationToken);
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
private async Task FetchChunkAsync(CancellationToken cancellationToken)
{
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(_chunkBuffer, 0, _chunkBuffer.Length), cancellationToken).ConfigureAwait(false);
for (var i = 0; i < response.Count; i++)
{
var @byte = _chunkBuffer[i];
_buffer.Enqueue(@byte);
}
if (response.MessageType == WebSocketMessageType.Close)
{
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
}
}
}
}
@@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Implementations;
using MQTTnet.Core.ManagedClient;
using MQTTnet.Core.Server;
using MQTTnet.Core.Diagnostics;
namespace MQTTnet
{
public class MqttFactory : IMqttClientFactory, IMqttServerFactory
{
public IMqttClient CreateMqttClient()
{
return CreateMqttClient(new MqttNetLogger());
}
public IMqttClient CreateMqttClient(IMqttNetLogger logger)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
return new MqttClient(new MqttClientAdapterFactory(), logger);
}
public IManagedMqttClient CreateManagedMqttClient()
{
return new ManagedMqttClient(CreateMqttClient(), new MqttNetLogger());
}
public IManagedMqttClient CreateManagedMqttClient(IMqttNetLogger logger)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
return new ManagedMqttClient(CreateMqttClient(), logger);
}
public IMqttServer CreateMqttServer()
{
var logger = new MqttNetLogger();
return CreateMqttServer(new List<IMqttServerAdapter> { new MqttServerAdapter(logger) }, logger);
}
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
{
if (adapters == null) throw new ArgumentNullException(nameof(adapters));
if (logger == null) throw new ArgumentNullException(nameof(logger));
return new MqttServer(adapters, logger);
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017 Christian Kratky
MQTTnet Copyright (c) 2016-2019 Christian Kratky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Adapter
{
public interface IMqttChannelAdapter
{
IMqttPacketSerializer PacketSerializer { get; }
Task ConnectAsync(TimeSpan timeout);
Task DisconnectAsync(TimeSpan timeout);
Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable<MqttBasePacket> packets);
Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken);
}
}
@@ -1,14 +0,0 @@
using System;
using System.Threading.Tasks;
using MQTTnet.Core.Server;
namespace MQTTnet.Core.Adapter
{
public interface IMqttServerAdapter
{
event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
Task StartAsync(MqttServerOptions options);
Task StopAsync();
}
}
-184
View File
@@ -1,184 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Internal;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Adapter
{
public class MqttChannelAdapter : IMqttChannelAdapter
{
private const uint ErrorOperationAborted = 0x800703E3;
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private readonly IMqttNetLogger _logger;
private readonly IMqttChannel _channel;
public MqttChannelAdapter(IMqttChannel channel, IMqttPacketSerializer serializer, IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_channel = channel ?? throw new ArgumentNullException(nameof(channel));
PacketSerializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}
public IMqttPacketSerializer PacketSerializer { get; }
public async Task ConnectAsync(TimeSpan timeout)
{
_logger.Info<MqttChannelAdapter>("Connecting [Timeout={0}]", timeout);
await ExecuteAndWrapExceptionAsync(() => _channel.ConnectAsync().TimeoutAfter(timeout));
}
public async Task DisconnectAsync(TimeSpan timeout)
{
_logger.Info<MqttChannelAdapter>("Disconnecting [Timeout={0}]", timeout);
await ExecuteAndWrapExceptionAsync(() => _channel.DisconnectAsync().TimeoutAfter(timeout));
}
public async Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable<MqttBasePacket> packets)
{
await ExecuteAndWrapExceptionAsync(async () =>
{
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
foreach (var packet in packets)
{
if (packet == null)
{
continue;
}
_logger.Trace<MqttChannelAdapter>("TX >>> {0} [Timeout={1}]", packet, timeout);
var writeBuffer = PacketSerializer.Serialize(packet);
await _channel.SendStream.WriteAsync(writeBuffer, 0, writeBuffer.Length, cancellationToken).ConfigureAwait(false);
}
if (timeout > TimeSpan.Zero)
{
await _channel.SendStream.FlushAsync(cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false);
}
else
{
await _channel.SendStream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
}
finally
{
_semaphore.Release();
}
});
}
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
MqttBasePacket packet = null;
await ExecuteAndWrapExceptionAsync(async () =>
{
ReceivedMqttPacket receivedMqttPacket = null;
try
{
if (timeout > TimeSpan.Zero)
{
receivedMqttPacket = await ReceiveAsync(_channel.ReceiveStream, cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false);
}
else
{
receivedMqttPacket = await ReceiveAsync(_channel.ReceiveStream, cancellationToken).ConfigureAwait(false);
}
if (receivedMqttPacket == null || cancellationToken.IsCancellationRequested)
{
throw new TaskCanceledException();
}
packet = PacketSerializer.Deserialize(receivedMqttPacket);
if (packet == null)
{
throw new MqttProtocolViolationException("Received malformed packet.");
}
_logger.Trace<MqttChannelAdapter>("RX <<< {0}", packet);
}
finally
{
receivedMqttPacket?.Dispose();
}
});
return packet;
}
private static async Task<ReceivedMqttPacket> ReceiveAsync(Stream stream, CancellationToken cancellationToken)
{
var header = MqttPacketReader.ReadHeaderFromSource(stream, cancellationToken);
if (header == null)
{
return null;
}
if (header.BodyLength == 0)
{
return new ReceivedMqttPacket(header, new MemoryStream(0));
}
var body = new byte[header.BodyLength];
var offset = 0;
do
{
var readBytesCount = await stream.ReadAsync(body, offset, body.Length - offset, cancellationToken).ConfigureAwait(false);
offset += readBytesCount;
} while (offset < header.BodyLength);
return new ReceivedMqttPacket(header, new MemoryStream(body, 0, body.Length));
}
private static async Task ExecuteAndWrapExceptionAsync(Func<Task> action)
{
try
{
await action().ConfigureAwait(false);
}
catch (TaskCanceledException)
{
throw;
}
catch (OperationCanceledException)
{
throw;
}
catch (MqttCommunicationTimedOutException)
{
throw;
}
catch (MqttCommunicationException)
{
throw;
}
catch (COMException comException)
{
if ((uint)comException.HResult == ErrorOperationAborted)
{
throw new OperationCanceledException();
}
throw new MqttCommunicationException(comException);
}
catch (Exception exception)
{
throw new MqttCommunicationException(exception);
}
}
}
}
@@ -1,17 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Adapter
{
public static class MqttChannelAdapterExtensions
{
public static Task SendPacketsAsync(this IMqttChannelAdapter adapter, TimeSpan timeout, CancellationToken cancellationToken, params MqttBasePacket[] packets)
{
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
return adapter.SendPacketsAsync(timeout, cancellationToken, packets);
}
}
}
@@ -1,16 +0,0 @@
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Adapter
{
public class MqttConnectingFailedException : MqttCommunicationException
{
public MqttConnectingFailedException(MqttConnectReturnCode returnCode)
: base($"Connecting with MQTT server failed ({returnCode}).")
{
ReturnCode = returnCode;
}
public MqttConnectReturnCode ReturnCode { get; }
}
}
@@ -1,17 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Core.Adapter
{
public class MqttServerAdapterClientAcceptedEventArgs : EventArgs
{
public MqttServerAdapterClientAcceptedEventArgs(IMqttChannelAdapter client)
{
Client = client ?? throw new ArgumentNullException(nameof(client));
}
public IMqttChannelAdapter Client { get; }
public Task SessionTask { get; set; }
}
}
@@ -1,24 +0,0 @@
using System;
using System.IO;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Adapter
{
public sealed class ReceivedMqttPacket : IDisposable
{
public ReceivedMqttPacket(MqttPacketHeader header, MemoryStream body)
{
Header = header ?? throw new ArgumentNullException(nameof(header));
Body = body ?? throw new ArgumentNullException(nameof(body));
}
public MqttPacketHeader Header { get; }
public MemoryStream Body { get; }
public void Dispose()
{
Body?.Dispose();
}
}
}
@@ -1,16 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Core
{
public static class ApplicationMessagePublisherExtensions
{
public static Task PublishAsync(this IApplicationMessagePublisher client, params MqttApplicationMessage[] applicationMessages)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
return client.PublishAsync(applicationMessages);
}
}
}
-14
View File
@@ -1,14 +0,0 @@
using System.Threading.Tasks;
using System.IO;
namespace MQTTnet.Core.Channel
{
public interface IMqttChannel
{
Stream SendStream { get; }
Stream ReceiveStream { get; }
Task ConnectAsync();
Task DisconnectAsync();
}
}
-21
View File
@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Client
{
public interface IMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher
{
bool IsConnected { get; }
event EventHandler<MqttClientConnectedEventArgs> Connected;
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options);
Task DisconnectAsync();
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
Task UnsubscribeAsync(IEnumerable<string> topicFilters);
}
}
@@ -1,10 +0,0 @@
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
namespace MQTTnet.Core.Client
{
public interface IMqttClientAdapterFactory
{
IMqttChannelAdapter CreateClientAdapter(IMqttClientChannelOptions options, IMqttNetLogger logger);
}
}
-16
View File
@@ -1,16 +0,0 @@
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.ManagedClient;
namespace MQTTnet.Core.Client
{
public interface IMqttClientFactory
{
IMqttClient CreateMqttClient();
IMqttClient CreateMqttClient(IMqttNetLogger logger);
IManagedMqttClient CreateManagedMqttClient();
IManagedMqttClient CreateManagedMqttClient(IMqttNetLogger logger);
}
}
-20
View File
@@ -1,20 +0,0 @@
using System;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Client
{
public interface IMqttClientOptions
{
string ClientId { get; }
IMqttClientCredentials Credentials { get; }
bool CleanSession { get; }
MqttApplicationMessage WillMessage { get; }
TimeSpan CommunicationTimeout { get; }
TimeSpan KeepAlivePeriod { get; }
MqttProtocolVersion ProtocolVersion { get; }
IMqttClientChannelOptions ChannelOptions { get; }
}
}
-487
View File
@@ -1,487 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Internal;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Client
{
public class MqttClient : IMqttClient
{
private readonly HashSet<ushort> _unacknowledgedPublishPackets = new HashSet<ushort>();
private readonly IMqttClientAdapterFactory _adapterFactory;
private readonly MqttPacketDispatcher _packetDispatcher;
private readonly IMqttNetLogger _logger;
private IMqttClientOptions _options;
private bool _isReceivingPackets;
private int _latestPacketIdentifier;
private CancellationTokenSource _cancellationTokenSource;
private IMqttChannelAdapter _adapter;
public MqttClient(IMqttClientAdapterFactory channelFactory, IMqttNetLogger logger)
{
_adapterFactory = channelFactory ?? throw new ArgumentNullException(nameof(channelFactory));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_packetDispatcher = new MqttPacketDispatcher(logger);
}
public event EventHandler<MqttClientConnectedEventArgs> Connected;
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
public bool IsConnected { get; private set; }
public async Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (options.ChannelOptions == null) throw new ArgumentException("ChannelOptions are not set.");
ThrowIfConnected("It is not allowed to connect with a server after the connection is established.");
try
{
_options = options;
_cancellationTokenSource = new CancellationTokenSource();
_latestPacketIdentifier = 0;
_packetDispatcher.Reset();
_adapter = _adapterFactory.CreateClientAdapter(options.ChannelOptions, _logger);
_logger.Trace<MqttClient>("Trying to connect with server.");
await _adapter.ConnectAsync(_options.CommunicationTimeout).ConfigureAwait(false);
_logger.Trace<MqttClient>("Connection with server established.");
await StartReceivingPacketsAsync(_cancellationTokenSource.Token).ConfigureAwait(false);
var connectResponse = await AuthenticateAsync(options.WillMessage).ConfigureAwait(false);
_logger.Trace<MqttClient>("MQTT connection with server established.");
if (_options.KeepAlivePeriod != TimeSpan.Zero)
{
StartSendingKeepAliveMessages(_cancellationTokenSource.Token);
}
IsConnected = true;
Connected?.Invoke(this, new MqttClientConnectedEventArgs(connectResponse.IsSessionPresent));
return new MqttClientConnectResult(connectResponse.IsSessionPresent);
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Error while connecting with server.");
await DisconnectInternalAsync().ConfigureAwait(false);
throw;
}
}
public async Task DisconnectAsync()
{
if (!IsConnected)
{
return;
}
try
{
await SendAsync(new MqttDisconnectPacket()).ConfigureAwait(false);
}
finally
{
await DisconnectInternalAsync().ConfigureAwait(false);
}
}
public async Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
{
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
ThrowIfNotConnected();
var subscribePacket = new MqttSubscribePacket
{
PacketIdentifier = GetNewPacketIdentifier(),
TopicFilters = topicFilters.ToList()
};
var response = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket).ConfigureAwait(false);
if (response.SubscribeReturnCodes.Count != subscribePacket.TopicFilters.Count)
{
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
}
return subscribePacket.TopicFilters.Select((t, i) => new MqttSubscribeResult(t, response.SubscribeReturnCodes[i])).ToList();
}
public async Task UnsubscribeAsync(IEnumerable<string> topicFilters)
{
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
ThrowIfNotConnected();
var unsubscribePacket = new MqttUnsubscribePacket
{
PacketIdentifier = GetNewPacketIdentifier(),
TopicFilters = topicFilters.ToList()
};
await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket);
}
public async Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
{
ThrowIfNotConnected();
var publishPackets = applicationMessages.Select(m => m.ToPublishPacket());
foreach (var qosGroup in publishPackets.GroupBy(p => p.QualityOfServiceLevel))
{
var qosPackets = qosGroup.ToArray();
switch (qosGroup.Key)
{
case MqttQualityOfServiceLevel.AtMostOnce:
{
// No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier]
await _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, qosPackets).ConfigureAwait(false);
break;
}
case MqttQualityOfServiceLevel.AtLeastOnce:
{
foreach (var publishPacket in qosPackets)
{
publishPacket.PacketIdentifier = GetNewPacketIdentifier();
await SendAndReceiveAsync<MqttPubAckPacket>(publishPacket).ConfigureAwait(false);
}
break;
}
case MqttQualityOfServiceLevel.ExactlyOnce:
{
foreach (var publishPacket in qosPackets)
{
publishPacket.PacketIdentifier = GetNewPacketIdentifier();
var pubRecPacket = await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket).ConfigureAwait(false);
await SendAndReceiveAsync<MqttPubCompPacket>(pubRecPacket.CreateResponse<MqttPubRelPacket>()).ConfigureAwait(false);
}
break;
}
default:
{
throw new InvalidOperationException();
}
}
}
}
private async Task<MqttConnAckPacket> AuthenticateAsync(MqttApplicationMessage willApplicationMessage)
{
var connectPacket = new MqttConnectPacket
{
ClientId = _options.ClientId,
Username = _options.Credentials?.Username,
Password = _options.Credentials?.Password,
CleanSession = _options.CleanSession,
KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds,
WillMessage = willApplicationMessage
};
var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket).ConfigureAwait(false);
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
{
throw new MqttConnectingFailedException(response.ConnectReturnCode);
}
return response;
}
private void ThrowIfNotConnected()
{
if (!IsConnected) throw new MqttCommunicationException("The client is not connected.");
}
private void ThrowIfConnected(string message)
{
if (IsConnected) throw new MqttProtocolViolationException(message);
}
private async Task DisconnectInternalAsync()
{
var clientWasConnected = IsConnected;
IsConnected = false;
var cts = _cancellationTokenSource;
if (cts == null || cts.IsCancellationRequested)
{
return;
}
cts.Cancel(false);
cts.Dispose();
_cancellationTokenSource = null;
try
{
await _adapter.DisconnectAsync(_options.CommunicationTimeout).ConfigureAwait(false);
_logger.Info<MqttClient>("Disconnected from adapter.");
}
catch (Exception exception)
{
_logger.Warning<MqttClient>(exception, "Error while disconnecting from adapter.");
}
finally
{
_logger.Info<MqttClient>("Disconnected.");
Disconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(clientWasConnected));
}
}
private async Task ProcessReceivedPacketAsync(MqttBasePacket packet)
{
try
{
_logger.Info<MqttClient>("Received <<< {0}", packet);
if (packet is MqttPingReqPacket)
{
await SendAsync(new MqttPingRespPacket());
return;
}
if (packet is MqttDisconnectPacket)
{
await DisconnectAsync();
return;
}
if (packet is MqttPublishPacket publishPacket)
{
await ProcessReceivedPublishPacket(publishPacket);
return;
}
if (packet is MqttPubRelPacket pubRelPacket)
{
await ProcessReceivedPubRelPacket(pubRelPacket);
return;
}
_packetDispatcher.Dispatch(packet);
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while processing received packet.");
}
}
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket)
{
try
{
var applicationMessage = publishPacket.ToApplicationMessage();
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(_options.ClientId, applicationMessage));
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while handling application message.");
}
}
private async Task ProcessReceivedPublishPacket(MqttPublishPacket publishPacket)
{
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
return;
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
await SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
return;
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
{
// QoS 2 is implement as method "B" [4.3.3 QoS 2: Exactly once delivery]
lock (_unacknowledgedPublishPackets)
{
_unacknowledgedPublishPackets.Add(publishPacket.PacketIdentifier);
}
FireApplicationMessageReceivedEvent(publishPacket);
await SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier });
return;
}
throw new MqttCommunicationException("Received a not supported QoS level.");
}
private Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket)
{
lock (_unacknowledgedPublishPackets)
{
_unacknowledgedPublishPackets.Remove(pubRelPacket.PacketIdentifier);
}
return SendAsync(pubRelPacket.CreateResponse<MqttPubCompPacket>());
}
private Task SendAsync(MqttBasePacket packet)
{
return _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, packet);
}
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket
{
var packetAwaiter = _packetDispatcher.WaitForPacketAsync(requestPacket, typeof(TResponsePacket), _options.CommunicationTimeout);
await _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, requestPacket).ConfigureAwait(false);
return (TResponsePacket)await packetAwaiter.ConfigureAwait(false);
}
private ushort GetNewPacketIdentifier()
{
return (ushort)Interlocked.Increment(ref _latestPacketIdentifier);
}
private async Task SendKeepAliveMessagesAsync(CancellationToken cancellationToken)
{
_logger.Info<MqttClient>("Start sending keep alive packets.");
try
{
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(_options.KeepAlivePeriod, cancellationToken).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return;
}
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket()).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
await DisconnectInternalAsync().ConfigureAwait(false);
}
catch (MqttCommunicationException exception)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
_logger.Warning<MqttClient>(exception, "MQTT communication exception while sending/receiving keep alive packets.");
await DisconnectInternalAsync().ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.Warning<MqttClient>(exception, "Unhandled exception while sending/receiving keep alive packets.");
await DisconnectInternalAsync().ConfigureAwait(false);
}
finally
{
_logger.Info<MqttClient>("Stopped sending keep alive packets.");
}
}
private async Task ReceivePacketsAsync(CancellationToken cancellationToken)
{
_logger.Info<MqttClient>("Start receiving packets.");
try
{
while (!cancellationToken.IsCancellationRequested)
{
_isReceivingPackets = true;
var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return;
}
StartProcessReceivedPacket(packet, cancellationToken);
}
}
catch (OperationCanceledException)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
await DisconnectInternalAsync().ConfigureAwait(false);
}
catch (MqttCommunicationException exception)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
_logger.Warning<MqttClient>(exception, "MQTT communication exception while receiving packets.");
await DisconnectInternalAsync().ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while receiving packets.");
await DisconnectInternalAsync().ConfigureAwait(false);
}
finally
{
_logger.Info<MqttClient>("Stopped receiving packets.");
}
}
private void StartProcessReceivedPacket(MqttBasePacket packet, CancellationToken cancellationToken)
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(
() => ProcessReceivedPacketAsync(packet),
cancellationToken).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
private async Task StartReceivingPacketsAsync(CancellationToken cancellationToken)
{
_isReceivingPackets = false;
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(
async () => await ReceivePacketsAsync(cancellationToken),
cancellationToken).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
while (!_isReceivingPackets && !cancellationToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken).ConfigureAwait(false);
}
}
private void StartSendingKeepAliveMessages(CancellationToken cancellationToken)
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(
async () => await SendKeepAliveMessagesAsync(cancellationToken),
cancellationToken).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
}
}
@@ -1,12 +0,0 @@
namespace MQTTnet.Core.Client
{
public class MqttClientConnectResult
{
public MqttClientConnectResult(bool isSessionPresent)
{
IsSessionPresent = isSessionPresent;
}
public bool IsSessionPresent { get; }
}
}
@@ -1,14 +0,0 @@
using System;
namespace MQTTnet.Core.Client
{
public class MqttClientConnectedEventArgs : EventArgs
{
public MqttClientConnectedEventArgs(bool isSessionPresent)
{
IsSessionPresent = isSessionPresent;
}
public bool IsSessionPresent { get; }
}
}
@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MQTTnet.Core.Client
{
public static class MqttClientExtensions
{
public static Task<IList<MqttSubscribeResult>> SubscribeAsync(this IMqttClient client, params TopicFilter[] topicFilters)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
return client.SubscribeAsync(topicFilters.ToList());
}
public static Task UnsubscribeAsync(this IMqttClient client, params string[] topicFilters)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
return client.UnsubscribeAsync(topicFilters.ToList());
}
}
}
-24
View File
@@ -1,24 +0,0 @@
using System;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Client
{
public class MqttClientOptions : IMqttClientOptions
{
public MqttApplicationMessage WillMessage { get; set; }
public string ClientId { get; set; } = Guid.NewGuid().ToString("N");
public bool CleanSession { get; set; } = true;
public IMqttClientCredentials Credentials { get; set; } = new MqttClientCredentials();
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);
public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
public IMqttClientChannelOptions ChannelOptions { get; set; }
}
}
@@ -1,135 +0,0 @@
using System;
using System.Linq;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Client
{
public class MqttClientOptionsBuilder
{
private readonly MqttClientOptions _options = new MqttClientOptions();
private MqttClientTcpOptions _tcpOptions;
private MqttClientWebSocketOptions _webSocketOptions;
private MqttClientTlsOptions _tlsOptions;
public MqttClientOptionsBuilder WithProtocolVersion(MqttProtocolVersion value)
{
_options.ProtocolVersion = value;
return this;
}
public MqttClientOptionsBuilder WithCommunicationTimeout(TimeSpan value)
{
_options.CommunicationTimeout = value;
return this;
}
public MqttClientOptionsBuilder WithCleanSession(bool value = true)
{
_options.CleanSession = value;
return this;
}
public MqttClientOptionsBuilder WithKeepAlivePeriod(TimeSpan value)
{
_options.KeepAlivePeriod = value;
return this;
}
public MqttClientOptionsBuilder WithClientId(string value)
{
_options.ClientId = value;
return this;
}
public MqttClientOptionsBuilder WithWillMessage(MqttApplicationMessage value)
{
_options.WillMessage = value;
return this;
}
public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
{
_options.Credentials = new MqttClientCredentials
{
Username = username,
Password = password
};
return this;
}
public MqttClientOptionsBuilder WithTcpServer(string server, int? port = null)
{
_tcpOptions = new MqttClientTcpOptions
{
Server = server,
Port = port
};
return this;
}
public MqttClientOptionsBuilder WithWebSocketServer(string uri)
{
_webSocketOptions = new MqttClientWebSocketOptions
{
Uri = uri
};
return this;
}
public MqttClientOptionsBuilder WithTls(
bool allowUntrustedCertificates = false,
bool ignoreCertificateChainErrors = false,
bool ignoreCertificateRevocationErrors = false,
params byte[][] certificates)
{
_tlsOptions = new MqttClientTlsOptions
{
UseTls = true,
AllowUntrustedCertificates = allowUntrustedCertificates,
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
Certificates = certificates?.ToList()
};
return this;
}
public MqttClientOptionsBuilder WithTls()
{
_tlsOptions = new MqttClientTlsOptions
{
UseTls = true
};
return this;
}
public IMqttClientOptions Build()
{
if (_tlsOptions != null)
{
if (_tcpOptions == null && _webSocketOptions == null)
{
throw new InvalidOperationException("A channel (TCP or WebSocket) must be set if TLS is configured.");
}
if (_tcpOptions != null)
{
_options.ChannelOptions = _tcpOptions;
}
else
{
_options.ChannelOptions = _webSocketOptions;
}
}
_options.ChannelOptions = (IMqttClientChannelOptions)_tcpOptions ?? _webSocketOptions;
return _options;
}
}
}
@@ -1,11 +0,0 @@
namespace MQTTnet.Core.Client
{
public class MqttClientTcpOptions : IMqttClientChannelOptions
{
public string Server { get; set; }
public int? Port { get; set; }
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
}
}
@@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace MQTTnet.Core.Client
{
public class MqttClientTlsOptions
{
public bool UseTls { get; set; }
public bool IgnoreCertificateRevocationErrors { get; set; }
public bool IgnoreCertificateChainErrors { get; set; }
public bool AllowUntrustedCertificates { get; set; }
public List<byte[]> Certificates { get; set; }
}
}
-103
View File
@@ -1,103 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Internal;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Client
{
public class MqttPacketDispatcher
{
private readonly ConcurrentDictionary<Type, TaskCompletionSource<MqttBasePacket>> _packetByResponseType = new ConcurrentDictionary<Type, TaskCompletionSource<MqttBasePacket>>();
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<ushort, TaskCompletionSource<MqttBasePacket>>> _packetByResponseTypeAndIdentifier = new ConcurrentDictionary<Type, ConcurrentDictionary<ushort, TaskCompletionSource<MqttBasePacket>>>();
private readonly IMqttNetLogger _logger;
public MqttPacketDispatcher(IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<MqttBasePacket> WaitForPacketAsync(MqttBasePacket request, Type responseType, TimeSpan timeout)
{
if (request == null) throw new ArgumentNullException(nameof(request));
var packetAwaiter = AddPacketAwaiter(request, responseType);
try
{
return await packetAwaiter.Task.TimeoutAfter(timeout).ConfigureAwait(false);
}
catch (MqttCommunicationTimedOutException)
{
_logger.Warning<MqttPacketDispatcher>("Timeout while waiting for packet of type '{0}'.", responseType.Name);
throw;
}
finally
{
RemovePacketAwaiter(request, responseType);
}
}
public void Dispatch(MqttBasePacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
var type = packet.GetType();
if (packet is IMqttPacketWithIdentifier withIdentifier)
{
if (_packetByResponseTypeAndIdentifier.TryGetValue(type, out var byid))
{
if (byid.TryRemove(withIdentifier.PacketIdentifier, out var tcs))
{
tcs.TrySetResult(packet);
return;
}
}
}
else if (_packetByResponseType.TryRemove(type, out var tcs))
{
tcs.TrySetResult(packet);
return;
}
throw new InvalidOperationException($"Packet of type '{type.Name}' not handled or dispatched.");
}
public void Reset()
{
_packetByResponseTypeAndIdentifier.Clear();
_packetByResponseType.Clear();
}
private TaskCompletionSource<MqttBasePacket> AddPacketAwaiter(MqttBasePacket request, Type responseType)
{
var tcs = new TaskCompletionSource<MqttBasePacket>();
if (request is IMqttPacketWithIdentifier requestWithIdentifier)
{
var byId = _packetByResponseTypeAndIdentifier.GetOrAdd(responseType, key => new ConcurrentDictionary<ushort, TaskCompletionSource<MqttBasePacket>>());
byId[requestWithIdentifier.PacketIdentifier] = tcs;
}
else
{
_packetByResponseType[responseType] = tcs;
}
return tcs;
}
private void RemovePacketAwaiter(MqttBasePacket request, Type responseType)
{
if (request is IMqttPacketWithIdentifier requestWithIdentifier)
{
var byId = _packetByResponseTypeAndIdentifier.GetOrAdd(responseType, key => new ConcurrentDictionary<ushort, TaskCompletionSource<MqttBasePacket>>());
byId.TryRemove(requestWithIdentifier.PacketIdentifier, out var _);
}
else
{
_packetByResponseType.TryRemove(responseType, out var _);
}
}
}
}
@@ -1,18 +0,0 @@
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Client
{
public class MqttSubscribeResult
{
public MqttSubscribeResult(TopicFilter topicFilter, MqttSubscribeReturnCode returnCode)
{
TopicFilter = topicFilter;
ReturnCode = returnCode;
}
public TopicFilter TopicFilter { get; }
public MqttSubscribeReturnCode ReturnCode { get; }
}
}
@@ -1,21 +0,0 @@
using System;
namespace MQTTnet.Core.Diagnostics
{
public interface IMqttNetLogger
{
event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
void Trace<TSource>(string message, params object[] parameters);
void Info<TSource>(string message, params object[] parameters);
void Warning<TSource>(Exception exception, string message, params object[] parameters);
void Warning<TSource>(string message, params object[] parameters);
void Error<TSource>(Exception exception, string message, params object[] parameters);
void Error<TSource>(string message, params object[] parameters);
}
}
-74
View File
@@ -1,74 +0,0 @@
using System;
namespace MQTTnet.Core.Diagnostics
{
public class MqttNetLogger : IMqttNetLogger
{
private readonly string _logId;
public MqttNetLogger(string logId = null)
{
_logId = logId;
}
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
public void Trace<TSource>(string message, params object[] parameters)
{
Publish<TSource>(MqttNetLogLevel.Verbose, null, message, parameters);
}
public void Info<TSource>(string message, params object[] parameters)
{
Publish<TSource>(MqttNetLogLevel.Info, null, message, parameters);
}
public void Warning<TSource>(Exception exception, string message, params object[] parameters)
{
Publish<TSource>(MqttNetLogLevel.Warning, exception, message, parameters);
}
public void Warning<TSource>(string message, params object[] parameters)
{
Warning<TSource>(null, message, parameters);
}
public void Error<TSource>(Exception exception, string message, params object[] parameters)
{
Publish<TSource>(MqttNetLogLevel.Error, exception, message, parameters);
}
public void Error<TSource>(string message, params object[] parameters)
{
Warning<TSource>(null, message, parameters);
}
private void Publish<TSource>(MqttNetLogLevel logLevel, Exception exception, string message, object[] parameters)
{
var hasLocalListeners = LogMessagePublished != null;
var hasGlobalListeners = MqttNetGlobalLog.HasListeners;
if (!hasLocalListeners && !hasGlobalListeners)
{
return;
}
if (parameters.Length > 0)
{
message = string.Format(message, parameters);
}
var traceMessage = new MqttNetLogMessage(_logId, DateTime.Now, Environment.CurrentManagedThreadId, typeof(TSource).Name, logLevel, message, exception);
if (hasGlobalListeners)
{
MqttNetGlobalLog.Publish(traceMessage);
}
if (hasLocalListeners)
{
LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(traceMessage));
}
}
}
}
@@ -1,6 +0,0 @@
namespace MQTTnet.Core.Exceptions
{
public sealed class MqttCommunicationTimedOutException : MqttCommunicationException
{
}
}
@@ -1,10 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MQTTnet.Core
{
public interface IApplicationMessagePublisher
{
Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages);
}
}
@@ -1,10 +0,0 @@
using System;
using MQTTnet.Core.Client;
namespace MQTTnet.Core
{
public interface IApplicationMessageReceiver
{
event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
}
}
@@ -1,35 +0,0 @@
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Internal
{
internal static class MqttApplicationMessageExtensions
{
public static MqttApplicationMessage ToApplicationMessage(this MqttPublishPacket publishPacket)
{
return new MqttApplicationMessage
{
Topic = publishPacket.Topic,
Payload = publishPacket.Payload,
QualityOfServiceLevel = publishPacket.QualityOfServiceLevel,
Retain = publishPacket.Retain
};
}
public static MqttPublishPacket ToPublishPacket(this MqttApplicationMessage applicationMessage)
{
if (applicationMessage == null)
{
return null;
}
return new MqttPublishPacket
{
Topic = applicationMessage.Topic,
Payload = applicationMessage.Payload,
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
Retain = applicationMessage.Retain,
Dup = false
};
}
}
}
-74
View File
@@ -1,74 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Exceptions;
namespace MQTTnet.Core.Internal
{
public static class TaskExtensions
{
public static async Task TimeoutAfter(this Task task, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
try
{
var timeoutTask = Task.Delay(timeout, cancellationTokenSource.Token);
var finishedTask = await Task.WhenAny(timeoutTask, task).ConfigureAwait(false);
if (finishedTask == timeoutTask)
{
throw new MqttCommunicationTimedOutException();
}
if (task.IsCanceled)
{
throw new TaskCanceledException();
}
if (task.IsFaulted)
{
throw new MqttCommunicationException(task.Exception.GetBaseException());
}
}
finally
{
cancellationTokenSource.Cancel();
}
}
}
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
try
{
var timeoutTask = Task.Delay(timeout, cancellationTokenSource.Token);
var finishedTask = await Task.WhenAny(timeoutTask, task).ConfigureAwait(false);
if (finishedTask == timeoutTask)
{
throw new MqttCommunicationTimedOutException();
}
if (task.IsCanceled)
{
throw new TaskCanceledException();
}
if (task.IsFaulted)
{
throw new MqttCommunicationException(task.Exception.GetBaseException());
}
return task.Result;
}
finally
{
cancellationTokenSource.Cancel();
}
}
}
}
}
-25
View File
@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<AssemblyName>MQTTnet.Core</AssemblyName>
<RootNamespace>MQTTnet.Core</RootNamespace>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<DebugType>Full</DebugType>
<Description></Description>
<Product></Product>
<Company></Company>
<Authors></Authors>
<Version>0.0.0.0</Version>
<PackageId></PackageId>
<Copyright></Copyright>
<PackageProjectUrl></PackageProjectUrl>
<PackageIconUrl></PackageIconUrl>
<RepositoryUrl></RepositoryUrl>
<PackageTags></PackageTags>
<FileVersion>2.5.3.0</FileVersion>
<AssemblyVersion>2.5.3.0</AssemblyVersion>
<PackageLicenseUrl></PackageLicenseUrl>
</PropertyGroup>
</Project>
@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.ManagedClient
{
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher
{
bool IsConnected { get; }
event EventHandler<MqttClientConnectedEventArgs> Connected;
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
Task StartAsync(IManagedMqttClientOptions options);
Task StopAsync();
Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
Task UnsubscribeAsync(IEnumerable<TopicFilter> topicFilters);
}
}
@@ -1,14 +0,0 @@
using System;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.ManagedClient
{
public interface IManagedMqttClientOptions
{
IMqttClientOptions ClientOptions { get; }
TimeSpan AutoReconnectDelay { get; }
IManagedMqttClientStorage Storage { get; }
}
}
@@ -1,12 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MQTTnet.Core.ManagedClient
{
public interface IManagedMqttClientStorage
{
Task SaveQueuedMessagesAsync(IList<MqttApplicationMessage> messages);
Task<IList<MqttApplicationMessage>> LoadQueuedMessagesAsync();
}
}
@@ -1,303 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Client;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.ManagedClient
{
public class ManagedMqttClient : IManagedMqttClient
{
private readonly ManagedMqttClientStorageManager _storageManager = new ManagedMqttClientStorageManager();
private readonly BlockingCollection<MqttApplicationMessage> _messageQueue = new BlockingCollection<MqttApplicationMessage>();
private readonly HashSet<TopicFilter> _subscriptions = new HashSet<TopicFilter>();
private readonly IMqttClient _mqttClient;
private readonly IMqttNetLogger _logger;
private CancellationTokenSource _connectionCancellationToken;
private CancellationTokenSource _publishingCancellationToken;
private IManagedMqttClientOptions _options;
private bool _subscriptionsNotPushed;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
_mqttClient.Connected += OnConnected;
_mqttClient.Disconnected += OnDisconnected;
_mqttClient.ApplicationMessageReceived += OnApplicationMessageReceived;
}
public bool IsConnected => _mqttClient.IsConnected;
public event EventHandler<MqttClientConnectedEventArgs> Connected;
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
public async Task StartAsync(IManagedMqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (options.ClientOptions == null) throw new ArgumentException("The client options are not set.", nameof(options));
if (!options.ClientOptions.CleanSession)
{
throw new NotSupportedException("The managed client does not support existing sessions.");
}
if (_connectionCancellationToken != null) throw new InvalidOperationException("The managed client is already started.");
_options = options;
await _storageManager.SetStorageAsync(_options.Storage).ConfigureAwait(false);
if (_options.Storage != null)
{
var loadedMessages = await _options.Storage.LoadQueuedMessagesAsync().ConfigureAwait(false);
foreach (var loadedMessage in loadedMessages)
{
_messageQueue.Add(loadedMessage);
}
}
_connectionCancellationToken = new CancellationTokenSource();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(async () => await MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_logger.Info<ManagedMqttClient>("Started");
}
public Task StopAsync()
{
_connectionCancellationToken?.Cancel(false);
_connectionCancellationToken = null;
_publishingCancellationToken?.Cancel(false);
_publishingCancellationToken = null;
while (_messageQueue.Any())
{
_messageQueue.Take();
}
return Task.FromResult(0);
}
public async Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
{
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
foreach (var applicationMessage in applicationMessages)
{
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
_messageQueue.Add(applicationMessage);
}
}
public Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
{
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
lock (_subscriptions)
{
foreach (var topicFilter in topicFilters)
{
if (_subscriptions.Add(topicFilter))
{
_subscriptionsNotPushed = true;
}
}
}
return Task.FromResult(0);
}
public Task UnsubscribeAsync(IEnumerable<TopicFilter> topicFilters)
{
lock (_subscriptions)
{
foreach (var topicFilter in topicFilters)
{
if (_subscriptions.Remove(topicFilter))
{
_subscriptionsNotPushed = true;
}
}
}
return Task.FromResult(0);
}
private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
var connectionState = await ReconnectIfRequiredAsync().ConfigureAwait(false);
if (connectionState == ReconnectionResult.NotConnected)
{
_publishingCancellationToken?.Cancel(false);
_publishingCancellationToken = null;
await Task.Delay(_options.AutoReconnectDelay, cancellationToken).ConfigureAwait(false);
continue;
}
if (connectionState == ReconnectionResult.Reconnected || _subscriptionsNotPushed)
{
await PushSubscriptionsAsync();
_publishingCancellationToken = new CancellationTokenSource();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(async () => await PublishQueuedMessagesAsync(_publishingCancellationToken.Token), _publishingCancellationToken.Token).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
continue;
}
if (connectionState == ReconnectionResult.StillConnected)
{
await Task.Delay(TimeSpan.FromSeconds(1), _connectionCancellationToken.Token).ConfigureAwait(false);
}
}
}
catch (OperationCanceledException)
{
}
catch (MqttCommunicationException exception)
{
_logger.Warning<ManagedMqttClient>(exception, "Communication exception while maintaining connection.");
}
catch (Exception exception)
{
_logger.Error<ManagedMqttClient>(exception, "Unhandled exception while maintaining connection.");
}
finally
{
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
_logger.Info<ManagedMqttClient>("Stopped");
}
}
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
var message = _messageQueue.Take(cancellationToken);
if (message == null)
{
continue;
}
if (cancellationToken.IsCancellationRequested)
{
continue;
}
await TryPublishQueuedMessageAsync(message).ConfigureAwait(false);
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
}
finally
{
_logger.Info<ManagedMqttClient>("Stopped publishing messages");
}
}
private async Task TryPublishQueuedMessageAsync(MqttApplicationMessage message)
{
try
{
await _mqttClient.PublishAsync(message).ConfigureAwait(false);
}
catch (MqttCommunicationException exception)
{
_logger.Warning<ManagedMqttClient>(exception, "Publishing application message failed.");
if (message.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
{
_messageQueue.Add(message);
}
}
catch (Exception exception)
{
_logger.Error<ManagedMqttClient>(exception, "Unhandled exception while publishing queued application message.");
}
}
private async Task PushSubscriptionsAsync()
{
_logger.Info<ManagedMqttClient>(nameof(ManagedMqttClient), "Synchronizing subscriptions");
List<TopicFilter> subscriptions;
lock (_subscriptions)
{
subscriptions = _subscriptions.ToList();
_subscriptionsNotPushed = false;
}
if (!_subscriptions.Any())
{
return;
}
try
{
await _mqttClient.SubscribeAsync(subscriptions).ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.Warning<ManagedMqttClient>(exception, "Synchronizing subscriptions failed");
_subscriptionsNotPushed = true;
}
}
private async Task<ReconnectionResult> ReconnectIfRequiredAsync()
{
if (_mqttClient.IsConnected)
{
return ReconnectionResult.StillConnected;
}
try
{
await _mqttClient.ConnectAsync(_options.ClientOptions).ConfigureAwait(false);
return ReconnectionResult.Reconnected;
}
catch (Exception)
{
return ReconnectionResult.NotConnected;
}
}
private void OnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs eventArgs)
{
ApplicationMessageReceived?.Invoke(this, eventArgs);
}
private void OnDisconnected(object sender, MqttClientDisconnectedEventArgs eventArgs)
{
Disconnected?.Invoke(this, eventArgs);
}
private void OnConnected(object sender, MqttClientConnectedEventArgs eventArgs)
{
Connected?.Invoke(this, eventArgs);
}
}
}
@@ -1,22 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MQTTnet.Core.ManagedClient
{
public static class ManagedMqttClientExtensions
{
public static Task SubscribeAsync(this IManagedMqttClient managedClient, params TopicFilter[] topicFilters)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
return managedClient.SubscribeAsync(topicFilters);
}
public static Task UnsubscribeAsync(this IManagedMqttClient managedClient, params TopicFilter[] topicFilters)
{
if (managedClient == null) throw new ArgumentNullException(nameof(managedClient));
return managedClient.UnsubscribeAsync(topicFilters);
}
}
}
@@ -1,14 +0,0 @@
using System;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.ManagedClient
{
public class ManagedMqttClientOptions : IManagedMqttClientOptions
{
public IMqttClientOptions ClientOptions { get; set; }
public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5);
public IManagedMqttClientStorage Storage { get; set; }
}
}
@@ -1,49 +0,0 @@
using System;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.ManagedClient
{
public class ManagedMqttClientOptionsBuilder
{
private readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
public ManagedMqttClientOptionsBuilder WithAutoReconnectDelay(TimeSpan value)
{
_options.AutoReconnectDelay = value;
return this;
}
public ManagedMqttClientOptionsBuilder WithStorage(IManagedMqttClientStorage value)
{
_options.Storage = value;
return this;
}
public ManagedMqttClientOptionsBuilder WithClientOptions(IMqttClientOptions value)
{
_options.ClientOptions = value ?? throw new ArgumentNullException(nameof(value));
return this;
}
public ManagedMqttClientOptionsBuilder WithClientOptions(Action<MqttClientOptionsBuilder> options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
var builder = new MqttClientOptionsBuilder();
options(builder);
_options.ClientOptions = builder.Build();
return this;
}
public ManagedMqttClientOptions Build()
{
if (_options.ClientOptions == null)
{
throw new InvalidOperationException("The ClientOptions cannot be null.");
}
return _options;
}
}
}
@@ -1,75 +0,0 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MQTTnet.Core.ManagedClient
{
public class ManagedMqttClientStorageManager
{
private readonly List<MqttApplicationMessage> _applicationMessages = new List<MqttApplicationMessage>();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private IManagedMqttClientStorage _storage;
public async Task SetStorageAsync(IManagedMqttClientStorage storage)
{
await _semaphore.WaitAsync().ConfigureAwait(false);
try
{
_storage = storage;
}
finally
{
_semaphore.Release();
}
}
public async Task AddAsync(MqttApplicationMessage applicationMessage)
{
await _semaphore.WaitAsync().ConfigureAwait(false);
try
{
if (_storage == null)
{
return;
}
_applicationMessages.Add(applicationMessage);
await SaveAsync().ConfigureAwait(false);
}
finally
{
_semaphore.Release();
}
}
public async Task RemoveAsync(MqttApplicationMessage applicationMessage)
{
await _semaphore.WaitAsync().ConfigureAwait(false);
try
{
if (_storage == null)
{
return;
}
var index = _applicationMessages.IndexOf(applicationMessage);
if (index == -1)
{
return;
}
_applicationMessages.RemoveAt(index);
await SaveAsync().ConfigureAwait(false);
}
finally
{
_semaphore.Release();
}
}
private Task SaveAsync()
{
return _storage.SaveQueuedMessagesAsync(_applicationMessages);
}
}
}
-29
View File
@@ -1,29 +0,0 @@
using System;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core
{
public sealed class MqttApplicationMessage
{
public MqttApplicationMessage()
{
}
[Obsolete("Use object initializer or _MqttApplicationMessageBuilder_ instead.")]
public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
{
Topic = topic ?? throw new ArgumentNullException(nameof(topic));
Payload = payload ?? throw new ArgumentNullException(nameof(payload));
QualityOfServiceLevel = qualityOfServiceLevel;
Retain = retain;
}
public string Topic { get; set; }
public byte[] Payload { get; set; }
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
public bool Retain { get; set; }
}
}
@@ -1,114 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core
{
public class MqttApplicationMessageBuilder
{
private MqttQualityOfServiceLevel _qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
private string _topic;
private byte[] _payload;
private bool _retain;
public MqttApplicationMessageBuilder WithTopic(string topic)
{
_topic = topic;
return this;
}
public MqttApplicationMessageBuilder WithPayload(IEnumerable<byte> payload)
{
if (payload == null)
{
_payload = null;
return this;
}
_payload = payload.ToArray();
return this;
}
public MqttApplicationMessageBuilder WithPayload(MemoryStream payload)
{
if (payload == null)
{
_payload = null;
return this;
}
if (payload.Length == 0)
{
_payload = new byte[0];
}
else
{
_payload = new byte[payload.Length - payload.Position];
payload.Read(_payload, 0, _payload.Length);
}
return this;
}
public MqttApplicationMessageBuilder WithPayload(string payload)
{
if (payload == null)
{
_payload = null;
return this;
}
_payload = string.IsNullOrEmpty(payload) ? new byte[0] : Encoding.UTF8.GetBytes(payload);
return this;
}
public MqttApplicationMessageBuilder WithQualityOfServiceLevel(MqttQualityOfServiceLevel qualityOfServiceLevel)
{
_qualityOfServiceLevel = qualityOfServiceLevel;
return this;
}
public MqttApplicationMessageBuilder WithRetainFlag(bool value = true)
{
_retain = value;
return this;
}
public MqttApplicationMessageBuilder WithAtLeastOnceQoS()
{
_qualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce;
return this;
}
public MqttApplicationMessageBuilder WithAtMostOnceQoS()
{
_qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
return this;
}
public MqttApplicationMessageBuilder WithExactlyOnceQoS()
{
_qualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce;
return this;
}
public MqttApplicationMessage Build()
{
if (string.IsNullOrEmpty(_topic))
{
throw new MqttProtocolViolationException("Topic is not set.");
}
return new MqttApplicationMessage
{
Topic = _topic,
Payload = _payload ?? new byte[0],
QualityOfServiceLevel = _qualityOfServiceLevel,
Retain = _retain
};
}
}
}
@@ -1,7 +0,0 @@
namespace MQTTnet.Core.Packets
{
public interface IMqttPacketWithIdentifier
{
ushort PacketIdentifier { get; set; }
}
}
-16
View File
@@ -1,16 +0,0 @@
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets
{
public sealed class MqttConnAckPacket : MqttBasePacket
{
public bool IsSessionPresent { get; set; }
public MqttConnectReturnCode ConnectReturnCode { get; set; }
public override string ToString()
{
return "ConnAck: [ConnectReturnCode=" + ConnectReturnCode + "] [IsSessionPresent=" + IsSessionPresent + "]";
}
}
}
-26
View File
@@ -1,26 +0,0 @@
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Packets
{
public sealed class MqttConnectPacket : MqttBasePacket
{
public MqttProtocolVersion ProtocolVersion { get; set; }
public string ClientId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public ushort KeepAlivePeriod { get; set; }
public bool CleanSession { get; set; }
public MqttApplicationMessage WillMessage { get; set; }
public override string ToString()
{
return "Connect: [ClientId=" + ClientId + "] [Username=" + Username + "] [Password=" + Password + "] [KeepAlivePeriod=" + KeepAlivePeriod + "] [CleanSession=" + CleanSession + "]";
}
}
}
@@ -1,10 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttDisconnectPacket : MqttBasePacket
{
public override string ToString()
{
return "Disconnect";
}
}
}
@@ -1,26 +0,0 @@
using System;
namespace MQTTnet.Core.Packets
{
public static class MqttPacketExtensions
{
public static TResponsePacket CreateResponse<TResponsePacket>(this MqttBasePacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
var responsePacket = Activator.CreateInstance<TResponsePacket>();
if (responsePacket is IMqttPacketWithIdentifier responsePacketWithIdentifier)
{
if (!(packet is IMqttPacketWithIdentifier requestPacketWithIdentifier))
{
throw new InvalidOperationException("Response packet has PacketIdentifier but request packet does not.");
}
responsePacketWithIdentifier.PacketIdentifier = requestPacketWithIdentifier.PacketIdentifier;
}
return responsePacket;
}
}
}
-13
View File
@@ -1,13 +0,0 @@
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets
{
public class MqttPacketHeader
{
public MqttControlPacketType ControlPacketType { get; set; }
public byte FixedHeader { get; set; }
public int BodyLength { get; set; }
}
}
-10
View File
@@ -1,10 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttPubAckPacket : MqttBasePublishPacket
{
public override string ToString()
{
return "PubAck";
}
}
}
-10
View File
@@ -1,10 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttPubCompPacket : MqttBasePublishPacket
{
public override string ToString()
{
return "PubComp";
}
}
}
-10
View File
@@ -1,10 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttPubRecPacket : MqttBasePublishPacket
{
public override string ToString()
{
return "PubRec";
}
}
}
-10
View File
@@ -1,10 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttPubRelPacket : MqttBasePublishPacket
{
public override string ToString()
{
return "PubRel";
}
}
}
-27
View File
@@ -1,27 +0,0 @@
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets
{
public sealed class MqttPublishPacket : MqttBasePublishPacket
{
public bool Retain { get; set; }
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
public bool Dup { get; set; }
public string Topic { get; set; }
public byte[] Payload { get; set; }
public override string ToString()
{
return "Publish: [Topic=" + Topic + "]" +
" [Payload.Length=" + Payload?.Length + "]" +
" [QoSLevel=" + QualityOfServiceLevel + "]" +
" [Dup=" + Dup + "]" +
" [Retain=" + Retain + "]" +
" [PacketIdentifier=" + PacketIdentifier + "]";
}
}
}
-19
View File
@@ -1,19 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets
{
public sealed class MqttSubAckPacket : MqttBasePacket, IMqttPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }
public IList<MqttSubscribeReturnCode> SubscribeReturnCodes { get; } = new List<MqttSubscribeReturnCode>();
public override string ToString()
{
var subscribeReturnCodesText = string.Join(",", SubscribeReturnCodes.Select(f => f.ToString()));
return "SubAck: [PacketIdentifier=" + PacketIdentifier + "] [SubscribeReturnCodes=" + subscribeReturnCodesText + "]";
}
}
}
@@ -1,18 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace MQTTnet.Core.Packets
{
public sealed class MqttSubscribePacket : MqttBasePacket, IMqttPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }
public IList<TopicFilter> TopicFilters { get; set; } = new List<TopicFilter>();
public override string ToString()
{
var topicFiltersText = string.Join(",", TopicFilters.Select(f => f.Topic + "@" + f.QualityOfServiceLevel));
return "Subscribe: [PacketIdentifier=" + PacketIdentifier + "] [TopicFilters=" + topicFiltersText + "]";
}
}
}
@@ -1,12 +0,0 @@
namespace MQTTnet.Core.Packets
{
public sealed class MqttUnsubAckPacket : MqttBasePacket, IMqttPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }
public override string ToString()
{
return "UnsubAck: [PacketIdentifier=" + PacketIdentifier + "]";
}
}
}
-17
View File
@@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace MQTTnet.Core.Packets
{
public sealed class MqttUnsubscribePacket : MqttBasePacket, IMqttPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }
public IList<string> TopicFilters { get; set; } = new List<string>();
public override string ToString()
{
var topicFiltersText = string.Join(",", TopicFilters);
return "Subscribe: [PacketIdentifier=" + PacketIdentifier + "] [TopicFilters=" + topicFiltersText + "]";
}
}
}
-48
View File
@@ -1,48 +0,0 @@
using System;
namespace MQTTnet.Core.Serializer
{
public sealed class ByteReader
{
private readonly int _source;
private int _index;
public ByteReader(int source)
{
_source = source;
}
public bool Read()
{
if (_index >= 8)
{
throw new InvalidOperationException("End of byte reached.");
}
var result = ((1 << _index) & _source) > 0;
_index++;
return result;
}
public int Read(int count)
{
if (_index + count > 8)
{
throw new InvalidOperationException("End of byte will be reached.");
}
var result = 0;
for (var i = 0; i < count; i++)
{
if (((1 << _index) & _source) > 0)
{
result |= 1 << i;
}
_index++;
}
return result;
}
}
}
-36
View File
@@ -1,36 +0,0 @@
using System;
namespace MQTTnet.Core.Serializer
{
public sealed class ByteWriter
{
private int _index;
private int _byte;
public byte Value => (byte)_byte;
public void Write(int @byte, int count)
{
for (var i = 0; i < count; i++)
{
var value = ((1 << i) & @byte) > 0;
Write(value);
}
}
public void Write(bool bit)
{
if (_index >= 8)
{
throw new InvalidOperationException("End of the byte reached.");
}
if (bit)
{
_byte |= 1 << _index;
}
_index++;
}
}
}
@@ -1,14 +0,0 @@
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Serializer
{
public interface IMqttPacketSerializer
{
MqttProtocolVersion ProtocolVersion { get; set; }
byte[] Serialize(MqttBasePacket mqttPacket);
MqttBasePacket Deserialize(ReceivedMqttPacket receivedMqttPacket);
}
}
-109
View File
@@ -1,109 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Protocol;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Serializer
{
public sealed class MqttPacketReader : BinaryReader
{
private readonly ReceivedMqttPacket _receivedMqttPacket;
public MqttPacketReader(ReceivedMqttPacket receivedMqttPacket)
: base(receivedMqttPacket.Body, Encoding.UTF8, true)
{
_receivedMqttPacket = receivedMqttPacket;
}
public bool EndOfRemainingData => BaseStream.Position == _receivedMqttPacket.Header.BodyLength;
public static MqttPacketHeader ReadHeaderFromSource(Stream stream, CancellationToken cancellationToken)
{
var buffer = stream.ReadByte();
if (buffer == -1)
{
return null;
}
var fixedHeader = (byte)buffer;
var controlPacketType = (MqttControlPacketType)(fixedHeader >> 4);
var bodyLength = ReadBodyLengthFromSource(stream, cancellationToken);
return new MqttPacketHeader
{
FixedHeader = fixedHeader,
ControlPacketType = controlPacketType,
BodyLength = bodyLength
};
}
public override ushort ReadUInt16()
{
var buffer = ReadBytes(2);
var temp = buffer[0];
buffer[0] = buffer[1];
buffer[1] = temp;
return BitConverter.ToUInt16(buffer, 0);
}
public string ReadStringWithLengthPrefix()
{
var buffer = ReadWithLengthPrefix();
return Encoding.UTF8.GetString(buffer, 0, buffer.Length);
}
public byte[] ReadWithLengthPrefix()
{
var length = ReadUInt16();
return ReadBytes(length);
}
public byte[] ReadRemainingData()
{
return ReadBytes(_receivedMqttPacket.Header.BodyLength - (int)BaseStream.Position);
}
private static int ReadBodyLengthFromSource(Stream stream, CancellationToken cancellationToken)
{
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
var multiplier = 1;
var value = 0;
byte encodedByte;
var readBytes = new List<int>();
do
{
if (cancellationToken.IsCancellationRequested)
{
throw new TaskCanceledException();
}
var buffer = stream.ReadByte();
readBytes.Add(buffer);
if (buffer == -1)
{
throw new MqttCommunicationException("Connection closed while reading remaining length data.");
}
encodedByte = (byte)buffer;
value += (byte)(encodedByte & 127) * multiplier;
multiplier *= 128;
if (multiplier > 128 * 128 * 128)
{
throw new MqttProtocolViolationException($"Remaining length is invalid (Data={string.Join(",", readBytes)}).");
}
} while ((encodedByte & 128) != 0);
return value;
}
}
}
@@ -1,514 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Serializer
{
public sealed class MqttPacketSerializer : IMqttPacketSerializer
{
private static byte[] ProtocolVersionV311Name { get; } = Encoding.UTF8.GetBytes("MQTT");
private static byte[] ProtocolVersionV310Name { get; } = Encoding.UTF8.GetBytes("MQIs");
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
public byte[] Serialize(MqttBasePacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
using (var stream = new MemoryStream())
using (var writer = new MqttPacketWriter(stream))
{
var fixedHeader = SerializePacket(packet, writer);
var headerBuffer = new List<byte> { fixedHeader };
MqttPacketWriter.WriteRemainingLength((int)stream.Length, headerBuffer);
var header = headerBuffer.ToArray();
var body = stream.ToArray();
var buffer = new byte[header.Length + body.Length];
Buffer.BlockCopy(header, 0, buffer, 0, header.Length);
Buffer.BlockCopy(body, 0, buffer, header.Length, body.Length);
return buffer;
}
}
public MqttBasePacket Deserialize(ReceivedMqttPacket receivedMqttPacket)
{
if (receivedMqttPacket == null) throw new ArgumentNullException(nameof(receivedMqttPacket));
using (var reader = new MqttPacketReader(receivedMqttPacket))
{
return Deserialize(receivedMqttPacket.Header, reader);
}
}
private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter writer)
{
switch (packet)
{
case MqttConnectPacket connectPacket: return Serialize(connectPacket, writer);
case MqttConnAckPacket connAckPacket: return Serialize(connAckPacket, writer);
case MqttDisconnectPacket _: return SerializeEmptyPacket(MqttControlPacketType.Disconnect);
case MqttPingReqPacket _: return SerializeEmptyPacket(MqttControlPacketType.PingReq);
case MqttPingRespPacket _: return SerializeEmptyPacket(MqttControlPacketType.PingResp);
case MqttPublishPacket publishPacket: return Serialize(publishPacket, writer);
case MqttPubAckPacket pubAckPacket: return Serialize(pubAckPacket, writer);
case MqttPubRecPacket pubRecPacket: return Serialize(pubRecPacket, writer);
case MqttPubRelPacket pubRelPacket: return Serialize(pubRelPacket, writer);
case MqttPubCompPacket pubCompPacket: return Serialize(pubCompPacket, writer);
case MqttSubscribePacket subscribePacket: return Serialize(subscribePacket, writer);
case MqttSubAckPacket subAckPacket: return Serialize(subAckPacket, writer);
case MqttUnsubscribePacket unsubscribePacket: return Serialize(unsubscribePacket, writer);
case MqttUnsubAckPacket unsubAckPacket: return Serialize(unsubAckPacket, writer);
default: throw new MqttProtocolViolationException("Packet type invalid.");
}
}
private static MqttBasePacket Deserialize(MqttPacketHeader header, MqttPacketReader reader)
{
switch (header.ControlPacketType)
{
case MqttControlPacketType.Connect: return DeserializeConnect(reader);
case MqttControlPacketType.ConnAck: return DeserializeConnAck(reader);
case MqttControlPacketType.Disconnect: return new MqttDisconnectPacket();
case MqttControlPacketType.Publish: return DeserializePublish(reader, header);
case MqttControlPacketType.PubAck: return DeserializePubAck(reader);
case MqttControlPacketType.PubRec: return DeserializePubRec(reader);
case MqttControlPacketType.PubRel: return DeserializePubRel(reader);
case MqttControlPacketType.PubComp: return DeserializePubComp(reader);
case MqttControlPacketType.PingReq: return new MqttPingReqPacket();
case MqttControlPacketType.PingResp: return new MqttPingRespPacket();
case MqttControlPacketType.Subscribe: return DeserializeSubscribe(reader);
case MqttControlPacketType.SubAck: return DeserializeSubAck(reader);
case MqttControlPacketType.Unsubscibe: return DeserializeUnsubscribe(reader);
case MqttControlPacketType.UnsubAck: return DeserializeUnsubAck(reader);
default: throw new MqttProtocolViolationException($"Packet type ({(int)header.ControlPacketType}) not supported.");
}
}
private static MqttBasePacket DeserializeUnsubAck(MqttPacketReader reader)
{
return new MqttUnsubAckPacket
{
PacketIdentifier = reader.ReadUInt16()
};
}
private static MqttBasePacket DeserializePubComp(MqttPacketReader reader)
{
return new MqttPubCompPacket
{
PacketIdentifier = reader.ReadUInt16()
};
}
private static MqttBasePacket DeserializePubRel(MqttPacketReader reader)
{
return new MqttPubRelPacket
{
PacketIdentifier = reader.ReadUInt16()
};
}
private static MqttBasePacket DeserializePubRec(MqttPacketReader reader)
{
return new MqttPubRecPacket
{
PacketIdentifier = reader.ReadUInt16()
};
}
private static MqttBasePacket DeserializePubAck(MqttPacketReader reader)
{
return new MqttPubAckPacket
{
PacketIdentifier = reader.ReadUInt16()
};
}
private static MqttBasePacket DeserializeUnsubscribe(MqttPacketReader reader)
{
var packet = new MqttUnsubscribePacket
{
PacketIdentifier = reader.ReadUInt16(),
};
while (!reader.EndOfRemainingData)
{
packet.TopicFilters.Add(reader.ReadStringWithLengthPrefix());
}
return packet;
}
private static MqttBasePacket DeserializeSubscribe(MqttPacketReader reader)
{
var packet = new MqttSubscribePacket
{
PacketIdentifier = reader.ReadUInt16()
};
while (!reader.EndOfRemainingData)
{
packet.TopicFilters.Add(new TopicFilter(
reader.ReadStringWithLengthPrefix(),
(MqttQualityOfServiceLevel)reader.ReadByte()));
}
return packet;
}
private static MqttBasePacket DeserializePublish(MqttPacketReader reader, MqttPacketHeader mqttPacketHeader)
{
var fixedHeader = new ByteReader(mqttPacketHeader.FixedHeader);
var retain = fixedHeader.Read();
var qualityOfServiceLevel = (MqttQualityOfServiceLevel)fixedHeader.Read(2);
var dup = fixedHeader.Read();
var topic = reader.ReadStringWithLengthPrefix();
ushort packetIdentifier = 0;
if (qualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
{
packetIdentifier = reader.ReadUInt16();
}
var packet = new MqttPublishPacket
{
Retain = retain,
QualityOfServiceLevel = qualityOfServiceLevel,
Dup = dup,
Topic = topic,
Payload = reader.ReadRemainingData(),
PacketIdentifier = packetIdentifier
};
return packet;
}
private static MqttBasePacket DeserializeConnect(MqttPacketReader reader)
{
reader.ReadBytes(2); // Skip 2 bytes
MqttProtocolVersion protocolVersion;
var protocolName = reader.ReadBytes(4);
if (protocolName.SequenceEqual(ProtocolVersionV310Name))
{
reader.ReadBytes(2);
protocolVersion = MqttProtocolVersion.V310;
}
else if (protocolName.SequenceEqual(ProtocolVersionV311Name))
{
protocolVersion = MqttProtocolVersion.V311;
}
else
{
throw new MqttProtocolViolationException("Protocol name is not supported.");
}
reader.ReadByte(); // Skip protocol level
var connectFlags = reader.ReadByte();
var connectFlagsReader = new ByteReader(connectFlags);
connectFlagsReader.Read(); // Reserved.
var packet = new MqttConnectPacket
{
ProtocolVersion = protocolVersion,
CleanSession = connectFlagsReader.Read()
};
var willFlag = connectFlagsReader.Read();
var willQoS = connectFlagsReader.Read(2);
var willRetain = connectFlagsReader.Read();
var passwordFlag = connectFlagsReader.Read();
var usernameFlag = connectFlagsReader.Read();
packet.KeepAlivePeriod = reader.ReadUInt16();
packet.ClientId = reader.ReadStringWithLengthPrefix();
if (willFlag)
{
packet.WillMessage = new MqttApplicationMessage
{
Topic = reader.ReadStringWithLengthPrefix(),
Payload = reader.ReadWithLengthPrefix(),
QualityOfServiceLevel = (MqttQualityOfServiceLevel)willQoS,
Retain = willRetain
};
}
if (usernameFlag)
{
packet.Username = reader.ReadStringWithLengthPrefix();
}
if (passwordFlag)
{
packet.Password = reader.ReadStringWithLengthPrefix();
}
ValidateConnectPacket(packet);
return packet;
}
private static MqttBasePacket DeserializeSubAck(MqttPacketReader reader)
{
var packet = new MqttSubAckPacket
{
PacketIdentifier = reader.ReadUInt16()
};
while (!reader.EndOfRemainingData)
{
packet.SubscribeReturnCodes.Add((MqttSubscribeReturnCode)reader.ReadByte());
}
return packet;
}
private static MqttBasePacket DeserializeConnAck(MqttPacketReader reader)
{
var variableHeader1 = reader.ReadByte();
var variableHeader2 = reader.ReadByte();
var packet = new MqttConnAckPacket
{
IsSessionPresent = new ByteReader(variableHeader1).Read(),
ConnectReturnCode = (MqttConnectReturnCode)variableHeader2
};
return packet;
}
private static void ValidateConnectPacket(MqttConnectPacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession)
{
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
}
}
private static void ValidatePublishPacket(MqttPublishPacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
{
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
}
}
private byte Serialize(MqttConnectPacket packet, MqttPacketWriter writer)
{
ValidateConnectPacket(packet);
// Write variable header
writer.Write(0x00, 0x04); // 3.1.2.1 Protocol Name
if (ProtocolVersion == MqttProtocolVersion.V311)
{
writer.Write(ProtocolVersionV311Name);
writer.Write(0x04); // 3.1.2.2 Protocol Level (4)
}
else
{
writer.Write(ProtocolVersionV310Name);
writer.Write(0x64, 0x70, 0x03); // Protocol Level (0x03)
}
var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags
connectFlags.Write(false); // Reserved
connectFlags.Write(packet.CleanSession);
connectFlags.Write(packet.WillMessage != null);
if (packet.WillMessage != null)
{
connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2);
connectFlags.Write(packet.WillMessage.Retain);
}
else
{
connectFlags.Write(0, 2);
connectFlags.Write(false);
}
connectFlags.Write(packet.Password != null);
connectFlags.Write(packet.Username != null);
writer.Write(connectFlags);
writer.Write(packet.KeepAlivePeriod);
writer.WriteWithLengthPrefix(packet.ClientId);
if (packet.WillMessage != null)
{
writer.WriteWithLengthPrefix(packet.WillMessage.Topic);
writer.WriteWithLengthPrefix(packet.WillMessage.Payload);
}
if (packet.Username != null)
{
writer.WriteWithLengthPrefix(packet.Username);
}
if (packet.Password != null)
{
writer.WriteWithLengthPrefix(packet.Password);
}
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect);
}
private byte Serialize(MqttConnAckPacket packet, MqttPacketWriter writer)
{
var connectAcknowledgeFlags = new ByteWriter();
if (ProtocolVersion == MqttProtocolVersion.V311)
{
connectAcknowledgeFlags.Write(packet.IsSessionPresent);
}
writer.Write(connectAcknowledgeFlags);
writer.Write((byte)packet.ConnectReturnCode);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck);
}
private static byte Serialize(MqttPubRelPacket packet, MqttPacketWriter writer)
{
writer.Write(packet.PacketIdentifier);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02);
}
private static byte Serialize(MqttPublishPacket packet, MqttPacketWriter writer)
{
ValidatePublishPacket(packet);
writer.WriteWithLengthPrefix(packet.Topic);
if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
{
writer.Write(packet.PacketIdentifier);
}
else
{
if (packet.PacketIdentifier > 0)
{
throw new MqttProtocolViolationException("Packet identifier must be empty if QoS == 0 [MQTT-2.3.1-5].");
}
}
if (packet.Payload?.Length > 0)
{
writer.Write(packet.Payload);
}
byte fixedHeader = 0;
if (packet.Retain)
{
fixedHeader |= 0x01;
}
fixedHeader |= (byte)((byte)packet.QualityOfServiceLevel << 1);
if (packet.Dup)
{
fixedHeader |= 0x08;
}
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader);
}
private static byte Serialize(MqttPubAckPacket packet, MqttPacketWriter writer)
{
writer.Write(packet.PacketIdentifier);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubAck);
}
private static byte Serialize(MqttPubRecPacket packet, MqttPacketWriter writer)
{
writer.Write(packet.PacketIdentifier);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRec);
}
private static byte Serialize(MqttPubCompPacket packet, MqttPacketWriter writer)
{
writer.Write(packet.PacketIdentifier);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp);
}
private static byte Serialize(MqttSubscribePacket packet, MqttPacketWriter writer)
{
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
writer.Write(packet.PacketIdentifier);
if (packet.TopicFilters?.Count > 0)
{
foreach (var topicFilter in packet.TopicFilters)
{
writer.WriteWithLengthPrefix(topicFilter.Topic);
writer.Write((byte)topicFilter.QualityOfServiceLevel);
}
}
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02);
}
private static byte Serialize(MqttSubAckPacket packet, MqttPacketWriter writer)
{
writer.Write(packet.PacketIdentifier);
if (packet.SubscribeReturnCodes?.Any() == true)
{
foreach (var packetSubscribeReturnCode in packet.SubscribeReturnCodes)
{
writer.Write((byte)packetSubscribeReturnCode);
}
}
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck);
}
private static byte Serialize(MqttUnsubscribePacket packet, MqttPacketWriter writer)
{
if (!packet.TopicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
writer.Write(packet.PacketIdentifier);
if (packet.TopicFilters?.Any() == true)
{
foreach (var topicFilter in packet.TopicFilters)
{
writer.WriteWithLengthPrefix(topicFilter);
}
}
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
}
private static byte Serialize(IMqttPacketWithIdentifier packet, BinaryWriter writer)
{
writer.Write(packet.PacketIdentifier);
return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck);
}
private static byte SerializeEmptyPacket(MqttControlPacketType type)
{
return MqttPacketWriter.BuildFixedHeader(type);
}
}
}
@@ -1,82 +0,0 @@
using System;
using System.IO;
using System.Text;
using MQTTnet.Core.Protocol;
using System.Collections.Generic;
namespace MQTTnet.Core.Serializer
{
public sealed class MqttPacketWriter : BinaryWriter
{
public MqttPacketWriter(Stream stream)
: base(stream, Encoding.UTF8, true)
{
}
public static byte BuildFixedHeader(MqttControlPacketType packetType, byte flags = 0)
{
var fixedHeader = (int)packetType << 4;
fixedHeader |= flags;
return (byte)fixedHeader;
}
public override void Write(ushort value)
{
var buffer = BitConverter.GetBytes(value);
Write(buffer[1], buffer[0]);
}
public new void Write(params byte[] values)
{
base.Write(values);
}
public new void Write(byte value)
{
base.Write(value);
}
public void Write(ByteWriter value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
Write(value.Value);
}
public void WriteWithLengthPrefix(string value)
{
WriteWithLengthPrefix(Encoding.UTF8.GetBytes(value ?? string.Empty));
}
public void WriteWithLengthPrefix(byte[] value)
{
var length = (ushort)value.Length;
Write(length);
Write(value);
}
public static void WriteRemainingLength(int length, List<byte> target)
{
if (length == 0)
{
target.Add(0);
return;
}
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
var x = length;
do
{
var encodedByte = x % 128;
x = x / 128;
if (x > 0)
{
encodedByte = encodedByte | 128;
}
target.Add((byte)encodedByte);
} while (x > 0);
}
}
}
@@ -1,8 +0,0 @@
namespace MQTTnet.Core.Serializer
{
public enum MqttProtocolVersion
{
V311,
V310
}
}
@@ -1,11 +0,0 @@
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Server
{
public class ConnectedMqttClient
{
public string ClientId { get; set; }
public MqttProtocolVersion ProtocolVersion { get; set; }
}
}
@@ -1,9 +0,0 @@
namespace MQTTnet.Core.Server
{
public sealed class GetOrCreateClientSessionResult
{
public bool IsExistingSession { get; set; }
public MqttClientSession Session { get; set; }
}
}
-18
View File
@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MQTTnet.Core.Server
{
public interface IMqttServer : IApplicationMessageReceiver, IApplicationMessagePublisher
{
event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
event EventHandler<MqttServerStartedEventArgs> Started;
Task<IList<ConnectedMqttClient>> GetConnectedClientsAsync();
Task StartAsync(MqttServerOptions options);
Task StopAsync();
}
}
@@ -1,7 +0,0 @@
namespace MQTTnet.Core.Server
{
public class MqttApplicationMessageInterceptorContext
{
public MqttApplicationMessage ApplicationMessage { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
namespace MQTTnet.Core.Server
{
public class MqttClientConnectedEventArgs : EventArgs
{
public MqttClientConnectedEventArgs(ConnectedMqttClient client)
{
Client = client ?? throw new ArgumentNullException(nameof(client));
}
public ConnectedMqttClient Client { get; }
}
}
@@ -1,14 +0,0 @@
using System;
namespace MQTTnet.Core.Server
{
public class MqttClientDisconnectedEventArgs : EventArgs
{
public MqttClientDisconnectedEventArgs(ConnectedMqttClient client)
{
Client = client ?? throw new ArgumentNullException(nameof(client));
}
public ConnectedMqttClient Client { get; }
}
}
@@ -1,103 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server
{
public sealed class MqttClientPendingMessagesQueue
{
private readonly BlockingCollection<MqttPublishPacket> _pendingPublishPackets = new BlockingCollection<MqttPublishPacket>();
private readonly MqttServerOptions _options;
private readonly MqttClientSession _session;
private readonly IMqttNetLogger _logger;
public MqttClientPendingMessagesQueue(MqttServerOptions options, MqttClientSession session, IMqttNetLogger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_session = session ?? throw new ArgumentNullException(nameof(session));
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public void Start(IMqttChannelAdapter adapter, CancellationToken cancellationToken)
{
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
if (cancellationToken.IsCancellationRequested)
{
return;
}
Task.Run(async () => await SendPendingPublishPacketsAsync(adapter, cancellationToken), cancellationToken).ConfigureAwait(false);
}
public void Enqueue(MqttPublishPacket publishPacket)
{
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
_pendingPublishPackets.Add(publishPacket);
_logger.Trace<MqttClientPendingMessagesQueue>("Enqueued packet (ClientId: {0}).", _session.ClientId);
}
private async Task SendPendingPublishPacketsAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
await SendPendingPublishPacketAsync(adapter, cancellationToken);
}
}
catch (OperationCanceledException)
{
}
catch (Exception exception)
{
_logger.Error<MqttClientPendingMessagesQueue>(exception, "Unhandled exception while sending enqueued packet (ClientId: {0}).", _session.ClientId);
}
}
private async Task SendPendingPublishPacketAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken)
{
MqttPublishPacket packet = null;
try
{
packet = _pendingPublishPackets.Take(cancellationToken);
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, packet).ConfigureAwait(false);
_logger.Trace<MqttClientPendingMessagesQueue>("Enqueued packet sent (ClientId: {0}).", _session.ClientId);
}
catch (Exception exception)
{
if (exception is MqttCommunicationTimedOutException)
{
_logger.Warning<MqttClientPendingMessagesQueue>(exception, "Sending publish packet failed due to timeout (ClientId: {0}).", _session.ClientId);
}
else if (exception is MqttCommunicationException)
{
_logger.Warning<MqttClientPendingMessagesQueue>(exception, "Sending publish packet failed due to communication exception (ClientId: {0}).", _session.ClientId);
}
else if (exception is OperationCanceledException)
{
}
else
{
_logger.Error<MqttClientPendingMessagesQueue>(exception, "Sending publish packet failed (ClientId: {0}).", _session.ClientId);
}
if (packet != null && packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
{
packet.Dup = true;
_pendingPublishPackets.Add(packet, CancellationToken.None);
}
await _session.StopAsync();
}
}
}
}
-266
View File
@@ -1,266 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Internal;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Server
{
public sealed class MqttClientSession
{
private readonly HashSet<ushort> _unacknowledgedPublishPackets = new HashSet<ushort>();
private readonly MqttClientSubscriptionsManager _subscriptionsManager;
private readonly MqttClientSessionsManager _sessionsManager;
private readonly MqttClientPendingMessagesQueue _pendingMessagesQueue;
private readonly MqttServerOptions _options;
private readonly IMqttNetLogger _logger;
private IMqttChannelAdapter _adapter;
private CancellationTokenSource _cancellationTokenSource;
private MqttApplicationMessage _willMessage;
public MqttClientSession(
string clientId,
MqttServerOptions options,
MqttClientSessionsManager sessionsManager,
IMqttNetLogger logger)
{
_sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
ClientId = clientId;
_options = options;
_subscriptionsManager = new MqttClientSubscriptionsManager(_options);
_pendingMessagesQueue = new MqttClientPendingMessagesQueue(_options, this, _logger);
}
public string ClientId { get; }
public MqttProtocolVersion? ProtocolVersion => _adapter?.PacketSerializer.ProtocolVersion;
public bool IsConnected => _adapter != null;
public async Task RunAsync(MqttApplicationMessage willMessage, IMqttChannelAdapter adapter)
{
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
try
{
var cancellationTokenSource = new CancellationTokenSource();
_willMessage = willMessage;
_adapter = adapter;
_cancellationTokenSource = cancellationTokenSource;
_pendingMessagesQueue.Start(adapter, cancellationTokenSource.Token);
await ReceivePacketsAsync(adapter, cancellationTokenSource.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
}
catch (MqttCommunicationException exception)
{
_logger.Warning<MqttClientSession>(exception, "Client '{0}': Communication exception while processing client packets.", ClientId);
}
catch (Exception exception)
{
_logger.Error<MqttClientSession>(exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId);
}
}
public async Task StopAsync()
{
try
{
_cancellationTokenSource?.Cancel(false);
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
if (_adapter != null)
{
await _adapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false);
_adapter = null;
}
_logger.Info<MqttClientSession>("Client '{0}': Session stopped.", ClientId);
}
finally
{
var willMessage = _willMessage;
if (willMessage != null)
{
_willMessage = null; //clear willmessage so it is send just once
await _sessionsManager.DispatchApplicationMessageAsync(this, willMessage);
}
}
}
public void EnqueuePublishPacket(MqttPublishPacket publishPacket)
{
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
var result = _subscriptionsManager.CheckSubscriptions(publishPacket);
if (!result.IsSubscribed)
{
return;
}
publishPacket.QualityOfServiceLevel = result.QualityOfServiceLevel;
_pendingMessagesQueue.Enqueue(publishPacket);
}
private async Task ReceivePacketsAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false);
await ProcessReceivedPacketAsync(adapter, packet, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
}
catch (MqttCommunicationException exception)
{
_logger.Warning<MqttClientSession>(exception, "Client '{0}': Communication exception while processing client packets.", ClientId);
await StopAsync();
}
catch (Exception exception)
{
_logger.Error<MqttClientSession>(exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId);
await StopAsync();
}
}
private Task ProcessReceivedPacketAsync(IMqttChannelAdapter adapter, MqttBasePacket packet, CancellationToken cancellationToken)
{
if (packet is MqttPingReqPacket)
{
return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, new MqttPingRespPacket());
}
if (packet is MqttPublishPacket publishPacket)
{
return HandleIncomingPublishPacketAsync(adapter, publishPacket, cancellationToken);
}
if (packet is MqttPubRelPacket pubRelPacket)
{
return HandleIncomingPubRelPacketAsync(adapter, pubRelPacket, cancellationToken);
}
if (packet is MqttPubRecPacket pubRecPacket)
{
return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, pubRecPacket.CreateResponse<MqttPubRelPacket>());
}
if (packet is MqttPubAckPacket || packet is MqttPubCompPacket)
{
// Discard message.
return Task.FromResult(0);
}
if (packet is MqttSubscribePacket subscribePacket)
{
return HandleIncomingSubscribePacketAsync(adapter, subscribePacket, cancellationToken);
}
if (packet is MqttUnsubscribePacket unsubscribePacket)
{
return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, _subscriptionsManager.Unsubscribe(unsubscribePacket));
}
if (packet is MqttDisconnectPacket || packet is MqttConnectPacket)
{
return StopAsync();
}
_logger.Warning<MqttClientSession>("Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet);
return StopAsync();
}
private async Task HandleIncomingSubscribePacketAsync(IMqttChannelAdapter adapter, MqttSubscribePacket subscribePacket, CancellationToken cancellationToken)
{
var subscribeResult = _subscriptionsManager.Subscribe(subscribePacket, ClientId);
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, subscribeResult.ResponsePacket).ConfigureAwait(false);
await EnqueueSubscribedRetainedMessagesAsync(subscribePacket).ConfigureAwait(false);
if (subscribeResult.CloseConnection)
{
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, new MqttDisconnectPacket()).ConfigureAwait(false);
await StopAsync();
}
}
private async Task EnqueueSubscribedRetainedMessagesAsync(MqttSubscribePacket subscribePacket)
{
var retainedMessages = await _sessionsManager.GetRetainedMessagesAsync(subscribePacket).ConfigureAwait(false);
foreach (var publishPacket in retainedMessages)
{
EnqueuePublishPacket(publishPacket.ToPublishPacket());
}
}
private async Task HandleIncomingPublishPacketAsync(IMqttChannelAdapter adapter, MqttPublishPacket publishPacket, CancellationToken cancellationToken)
{
var applicationMessage = publishPacket.ToApplicationMessage();
switch (applicationMessage.QualityOfServiceLevel)
{
case MqttQualityOfServiceLevel.AtMostOnce:
{
await _sessionsManager.DispatchApplicationMessageAsync(this, applicationMessage);
return;
}
case MqttQualityOfServiceLevel.AtLeastOnce:
{
await _sessionsManager.DispatchApplicationMessageAsync(this, applicationMessage);
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken,
new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
return;
}
case MqttQualityOfServiceLevel.ExactlyOnce:
{
// QoS 2 is implement as method "B" [4.3.3 QoS 2: Exactly once delivery]
lock (_unacknowledgedPublishPackets)
{
_unacknowledgedPublishPackets.Add(publishPacket.PacketIdentifier);
}
await _sessionsManager.DispatchApplicationMessageAsync(this, applicationMessage);
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken,
new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }).ConfigureAwait(false);
return;
}
default:
throw new MqttCommunicationException("Received a not supported QoS level.");
}
}
private Task HandleIncomingPubRelPacketAsync(IMqttChannelAdapter adapter, MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
{
lock (_unacknowledgedPublishPackets)
{
_unacknowledgedPublishPackets.Remove(pubRelPacket.PacketIdentifier);
}
return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, new MqttPubCompPacket { PacketIdentifier = pubRelPacket.PacketIdentifier });
}
}
}

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