Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5e6ee897 | ||
|
|
2e019f372c | ||
|
|
cc9bc2d3a0 | ||
|
|
306bce5a58 | ||
|
|
6fe7ce7a0c | ||
|
|
8f1d4e3c22 | ||
|
|
77338527b4 | ||
|
|
962622a9f7 | ||
|
|
899ed7b1da | ||
|
|
10f7d809f2 | ||
|
|
324fb7e48c | ||
|
|
d913d4402e | ||
|
|
df262b5588 | ||
|
|
27daf37ba4 | ||
|
|
e5e10eee6d | ||
|
|
e174546b5a | ||
|
|
f99daee4d1 | ||
|
|
9b10eadb24 | ||
|
|
c39da42ef2 | ||
|
|
85b339e6f0 | ||
|
|
fbb5cd45a0 | ||
|
|
d430ca0250 | ||
|
|
cf8ea872d3 | ||
|
|
d4440f3be1 | ||
|
|
b97d01b78b | ||
|
|
375ee5c4ac | ||
|
|
90b37a1e2d | ||
|
|
0978f6cc75 | ||
|
|
e7c51e8dbc | ||
|
|
aab4448980 | ||
|
|
52139c6a99 | ||
|
|
f3d121120b | ||
|
|
413c68de44 | ||
|
|
f0919487f2 | ||
|
|
ffa7c51899 | ||
|
|
493cad087f | ||
|
|
4d94e1a318 | ||
|
|
28ff08ceb9 | ||
|
|
0f3d461c37 | ||
|
|
4285169108 | ||
|
|
1b1f2db1e6 | ||
|
|
d7248c0f64 | ||
|
|
d2e1b12186 | ||
|
|
dafcfb47d2 | ||
|
|
897f0f36d1 | ||
|
|
9cb12ac2ce | ||
|
|
312fb2bb3c | ||
|
|
3ee785c781 | ||
|
|
0ea4ae7501 | ||
|
|
7e764c7f0f | ||
|
|
5c2879029b | ||
|
|
6cbb8d42e3 | ||
|
|
d8d50f6dcb | ||
|
|
a01dc9fef8 | ||
|
|
3427d82efc | ||
|
|
5915285522 | ||
|
|
12f346115f | ||
|
|
05827341d4 | ||
|
|
1e88d6a05b | ||
|
|
8261ba9dc1 | ||
|
|
b766c1bebb | ||
|
|
6c188899fb | ||
|
|
23c5270c3f | ||
|
|
2d4ea8ee9b | ||
|
|
15d3761843 | ||
|
|
ed520455d0 | ||
|
|
cfc4ebe6a3 | ||
|
|
120b7fb7d1 | ||
|
|
8b164a4846 | ||
|
|
fda4272611 | ||
|
|
88cc79d52f | ||
|
|
8ba960343c | ||
|
|
0976fa682a | ||
|
|
18cc454842 | ||
|
|
e342a51d50 | ||
|
|
57652c76cf | ||
|
|
bb52159e49 | ||
|
|
109acccd19 | ||
|
|
deb2c3dec6 | ||
|
|
63ca6086d5 | ||
|
|
3f92f2ca2b | ||
|
|
a13874d8a5 | ||
|
|
c91a1f8572 | ||
|
|
b103718bd9 | ||
|
|
b88924bce5 | ||
|
|
f3f1d81b52 | ||
|
|
031b60878d | ||
|
|
1fbf20a569 | ||
|
|
b1bf7698aa | ||
|
|
fbf7d9bb5c | ||
|
|
822f582e41 | ||
|
|
f8eaf02516 | ||
|
|
df45540d6b | ||
|
|
2abcf6d8bc | ||
|
|
c1001db450 | ||
|
|
fcbe2e32f6 | ||
|
|
f955b4a3e6 | ||
|
|
3d8d06f9b3 | ||
|
|
d804b805c1 | ||
|
|
bba04e2b5d | ||
|
|
5eab337e13 | ||
|
|
e1d39a3fef | ||
|
|
3f5d627e9e | ||
|
|
2047f44554 | ||
|
|
75845d6416 | ||
|
|
74e952bb03 | ||
|
|
3773048bc5 | ||
|
|
f9aec0c067 | ||
|
|
91c8a15f65 | ||
|
|
b95d6b08bc | ||
|
|
a44ea74739 | ||
|
|
02e65bca67 | ||
|
|
37b783908a | ||
|
|
72211ae85a | ||
|
|
1f78a92c4d | ||
|
|
f92cfcd293 | ||
|
|
86256d1b10 | ||
|
|
c3e65390ab | ||
|
|
b0699003e2 | ||
|
|
1214b15260 | ||
|
|
322067466b | ||
|
|
ef2ed1c897 | ||
|
|
9fddfb3e77 | ||
|
|
ec015e7620 | ||
|
|
7738c5faa1 | ||
|
|
01bb09ff4b | ||
|
|
e1494c1004 | ||
|
|
1e2231c461 | ||
|
|
de0f5dc1f0 | ||
|
|
a93f44217b | ||
|
|
f9c3014e52 | ||
|
|
483c2d8b10 | ||
|
|
02ab0e4903 | ||
|
|
0bc25571e0 | ||
|
|
5b29b8cfd8 | ||
|
|
dd9dc054e8 | ||
|
|
b7c178b85c | ||
|
|
f8e29f8dc0 | ||
|
|
3d68951f68 | ||
|
|
7eb6d2d1e3 | ||
|
|
0446635ed6 | ||
|
|
4514348821 | ||
|
|
7b32abe625 | ||
|
|
0febc12b3d | ||
|
|
d0a848c8b4 | ||
|
|
fe69f5a633 | ||
|
|
ca95754fc3 | ||
|
|
cc405c3e90 | ||
|
|
315206f05e | ||
|
|
f252374437 | ||
|
|
38d3531db6 | ||
|
|
da5a172504 | ||
|
|
f894622884 | ||
|
|
88b0af9b21 | ||
|
|
e1bf9de347 | ||
|
|
6c15693456 | ||
|
|
4608930a37 | ||
|
|
eaf1195f95 | ||
|
|
a35dee9352 | ||
|
|
6cef746ed9 | ||
|
|
344cf674e6 | ||
|
|
26af205ab0 | ||
|
|
06c9d27c87 | ||
|
|
14224e4180 | ||
|
|
b954c9512e | ||
|
|
fb2be79673 | ||
|
|
44b7133a1c | ||
|
|
2f0513212e | ||
|
|
1a9460776b | ||
|
|
2716db04e3 | ||
|
|
3e4f4a59a8 | ||
|
|
24f0ea01f5 | ||
|
|
1625aadae9 | ||
|
|
e800901b4c | ||
|
|
34ae54d542 | ||
|
|
838d50c1d3 | ||
|
|
558d281a33 | ||
|
|
f8c956a9e2 | ||
|
|
9a6823597e | ||
|
|
42c1155bee | ||
|
|
f773257c86 | ||
|
|
4e9df98817 | ||
|
|
3208045baa | ||
|
|
7274f4390c | ||
|
|
11c8abfd54 | ||
|
|
f606a5996b | ||
|
|
58ad599783 | ||
|
|
ccd102a59f | ||
|
|
05101f0e0e | ||
|
|
f9630ef347 | ||
|
|
c5b7735a2c | ||
|
|
12fca2f05a | ||
|
|
b7fb0c1002 | ||
|
|
3ea281ff84 | ||
|
|
c778cd7a0f | ||
|
|
adce5662eb | ||
|
|
a26b641284 | ||
|
|
7be3685850 | ||
|
|
1a6be47144 | ||
|
|
5d73de2a86 | ||
|
|
2eaebe0e6a | ||
|
|
d7b552fce2 | ||
|
|
bea6d75251 | ||
|
|
f7db00c08e | ||
|
|
f259bbcc9b | ||
|
|
252772007b | ||
|
|
21a9974e5d | ||
|
|
d63143bdc9 | ||
|
|
aad9eac361 | ||
|
|
e8a683b936 | ||
|
|
e475e36ce7 | ||
|
|
611c230da2 | ||
|
|
18839de083 | ||
|
|
194664bc9c | ||
|
|
10a33fd153 | ||
|
|
868aa7d89a | ||
|
|
1f8792cf87 | ||
|
|
7bb99c8b37 | ||
|
|
7f5504b01b | ||
|
|
fd789417e7 | ||
|
|
f1f9924bce | ||
|
|
b0c603082b | ||
|
|
f3f10e9f65 | ||
|
|
beb228cc05 | ||
|
|
7a7f0640ba | ||
|
|
55d009ce6b | ||
|
|
e23ac4f703 | ||
|
|
fc367ddb64 | ||
|
|
cf217034fa | ||
|
|
6b6627f823 | ||
|
|
4f51a238b3 | ||
|
|
733c587e45 | ||
|
|
3260920828 | ||
|
|
4e6aeb91a4 | ||
|
|
5056843611 | ||
|
|
a65c015a58 | ||
|
|
e63f26789f | ||
|
|
9a598892a7 | ||
|
|
857ab005be | ||
|
|
33e4ec1943 | ||
|
|
6a564a0c72 | ||
|
|
3a4dce5080 | ||
|
|
4e6118d324 | ||
|
|
269bfa09ac | ||
|
|
59dd6b98a3 | ||
|
|
9f37306f20 | ||
|
|
85b000c6b7 | ||
|
|
5a919ce5d2 | ||
|
|
57ab8e5abc | ||
|
|
8f6d48be81 | ||
|
|
38cfa15cc3 | ||
|
|
6adf7096ec | ||
|
|
df149eb0b3 | ||
|
|
63c9329190 | ||
|
|
246a10649a | ||
|
|
0a76ac15c6 | ||
|
|
d801af5616 | ||
|
|
257211fc7a | ||
|
|
a407fc381b | ||
|
|
4fa275bf2b | ||
|
|
7cf12dc751 | ||
|
|
40aefd0ad3 | ||
|
|
c20142671f | ||
|
|
75dfe68a94 | ||
|
|
92518fc4ec | ||
|
|
16180e83ba | ||
|
|
c779b394f1 | ||
|
|
e60a732b61 | ||
|
|
7ea9415c63 | ||
|
|
13c399bc9a | ||
|
|
4565c3990a | ||
|
|
2bd2648b48 | ||
|
|
1b56155f1c | ||
|
|
626930cfae | ||
|
|
6cf9cb0af2 | ||
|
|
60941c04e5 | ||
|
|
ba68b1274b | ||
|
|
dbe12b9c48 | ||
|
|
52b79a140b | ||
|
|
c270225e9e | ||
|
|
3f5d4e9825 | ||
|
|
e80d19ba9b | ||
|
|
48837529a2 | ||
|
|
43e3ad4c00 | ||
|
|
08c9ecb011 | ||
|
|
763f0e7934 | ||
|
|
9d381c2cf9 | ||
|
|
17ceb20169 | ||
|
|
683bb43486 | ||
|
|
d25b51740b | ||
|
|
a58ab607ad | ||
|
|
0a7d450f3b | ||
|
|
999fa7a468 | ||
|
|
f0a1f9ca93 | ||
|
|
89e9cb224f | ||
|
|
fe48c9c837 | ||
|
|
2a421d1d42 | ||
|
|
48d0344a40 | ||
|
|
db5ed594f7 | ||
|
|
f85bc9b956 | ||
|
|
eec46dd9bc | ||
|
|
9c9e2293c8 | ||
|
|
856861e1b1 | ||
|
|
4b481b4833 | ||
|
|
c05f11a495 | ||
|
|
e798c91ff3 | ||
|
|
5df4fc3d5d | ||
|
|
c6236c0865 | ||
|
|
85c0cb3bcc | ||
|
|
9810e52bcb | ||
|
|
948a5eaae3 | ||
|
|
31df8247fa | ||
|
|
229418100c | ||
|
|
93d8679bbc | ||
|
|
6cec126862 | ||
|
|
9749f790ea | ||
|
|
fbbc638c75 | ||
|
|
bf679adb6b | ||
|
|
cf7e59a774 | ||
|
|
e9724c0202 | ||
|
|
7931af7487 | ||
|
|
bb5f023b74 | ||
|
|
c2ac4fffaf | ||
|
|
4b78710705 | ||
|
|
2e69f8be78 | ||
|
|
2d6c44e45b | ||
|
|
fc3965f5a3 | ||
|
|
1d553c5ece | ||
|
|
07ad9fc557 | ||
|
|
f001d7aecc | ||
|
|
d49a4384c0 | ||
|
|
4e6658e014 | ||
|
|
2b2b30912c | ||
|
|
79d95c8516 | ||
|
|
88e8691ce0 | ||
|
|
28641892f5 | ||
|
|
4b08bb41f5 | ||
|
|
c89918a890 | ||
|
|
6546175ea2 | ||
|
|
b9e9fe64ac | ||
|
|
9fd7c7bc1e | ||
|
|
fcd6b7ff52 | ||
|
|
54870adc64 | ||
|
|
892e4842ed | ||
|
|
fc358f9015 | ||
|
|
b93cd5b673 | ||
|
|
aafc99f39e | ||
|
|
b14d7affe5 | ||
|
|
67d56644b2 | ||
|
|
6e0d3ec0fb | ||
|
|
2c6613a7b7 | ||
|
|
d464bfb7c5 | ||
|
|
7a24970035 | ||
|
|
db906eca24 | ||
|
|
ad128c7889 | ||
|
|
3e096bc353 | ||
|
|
f0be8404cf | ||
|
|
6de28d32e4 | ||
|
|
2ede7df38a | ||
|
|
2a35108a73 | ||
|
|
774d49a908 | ||
|
|
c83bec6e81 | ||
|
|
763d9778bb | ||
|
|
9368eebfd5 | ||
|
|
81b547f386 | ||
|
|
e33c5ccb4c | ||
|
|
0ca4c88e69 | ||
|
|
04ccdcd562 | ||
|
|
aafd4ea658 | ||
|
|
4eb65fc3d2 | ||
|
|
f7f00f4e06 | ||
|
|
af0b98eace | ||
|
|
0da2ab9de6 | ||
|
|
ea22ef4164 | ||
|
|
cb5a0cf38b | ||
|
|
55dc940abb | ||
|
|
c40e3c64aa | ||
|
|
87c4fa14ee | ||
|
|
0653b89701 | ||
|
|
561474c572 | ||
|
|
c10145f743 | ||
|
|
dca2af47d8 | ||
|
|
9ed80daf83 | ||
|
|
0d39bbbc0c | ||
|
|
52faf6d76a | ||
|
|
20eda96921 | ||
|
|
f6a814c6d7 | ||
|
|
8e0bce7734 | ||
|
|
72fa13ca5b | ||
|
|
45e3455e6c | ||
|
|
160da00f55 | ||
|
|
6b4b829cf6 | ||
|
|
e7fa465616 | ||
|
|
799005803e | ||
|
|
a20c845a5a | ||
|
|
5f59aca62c | ||
|
|
76ddf8c503 | ||
|
|
122034296c | ||
|
|
6f71aaf1ce | ||
|
|
fd8caed9af | ||
|
|
313f90a526 | ||
|
|
4d27f42e72 | ||
|
|
8ae318fd5c | ||
|
|
7dde2f1f4c | ||
|
|
49c5278ba0 | ||
|
|
ce51d12a03 | ||
|
|
b1559a8fa5 | ||
|
|
457143c840 | ||
|
|
c60bf51b1e | ||
|
|
630400da53 | ||
|
|
a152066ed3 | ||
|
|
138cd16c8d | ||
|
|
27a61819d3 | ||
|
|
9c378fb088 | ||
|
|
d4088420cf | ||
|
|
2e7d074174 | ||
|
|
328ffc734f | ||
|
|
8ecf658059 | ||
|
|
7b25c6f274 | ||
|
|
069c19aab9 | ||
|
|
35e729bd7b | ||
|
|
ac06a001e2 | ||
|
|
a77e0b8dde | ||
|
|
698f0b66d2 | ||
|
|
14419e4d63 | ||
|
|
3600ebbc62 | ||
|
|
55676965d9 | ||
|
|
f949d54aef | ||
|
|
624fafc662 | ||
|
|
23e93212a4 | ||
|
|
f9b2c91ddb | ||
|
|
9fb1cc3320 | ||
|
|
1c89a8bc75 | ||
|
|
8be9ce8024 | ||
|
|
002ba27fd3 | ||
|
|
9aaa94e821 | ||
|
|
e8ff48bfd3 | ||
|
|
5db05f186f | ||
|
|
b2c2209b4f | ||
|
|
c490e83c91 | ||
|
|
ac326babdf | ||
|
|
a38623cb5a | ||
|
|
a63489fa5e | ||
|
|
4b7409240b | ||
|
|
896e9ed0aa | ||
|
|
0950dfbb8b | ||
|
|
4105beb7e6 | ||
|
|
5c25905510 | ||
|
|
e3f6b579b2 | ||
|
|
c467c9c818 | ||
|
|
78b57531b6 | ||
|
|
84d9f533bd | ||
|
|
7479e320ee | ||
|
|
152303dfbd | ||
|
|
a495668f2b | ||
|
|
82b714d4c7 | ||
|
|
44d71b884c | ||
|
|
781c5d4d7d | ||
|
|
b175119008 | ||
|
|
cfcb858423 | ||
|
|
5fa12649bf | ||
|
|
a9a09f4ecd | ||
|
|
3ff5806dbb | ||
|
|
0ec78cf5cc | ||
|
|
c3193c568a | ||
|
|
a1f02284e9 | ||
|
|
851db2e808 | ||
|
|
073cd5243f | ||
|
|
699558e47a | ||
|
|
15ff03c136 | ||
|
|
b12e3bc611 | ||
|
|
61c3e02242 | ||
|
|
5618c4c1f7 | ||
|
|
ba9ceed7ce | ||
|
|
ad1c198e43 | ||
|
|
2918be18c6 | ||
|
|
248e2a5bdd | ||
|
|
1a41415dd1 | ||
|
|
9302e80d73 | ||
|
|
cf6f0ece0e | ||
|
|
50d65f2fed | ||
|
|
4614df7fa5 | ||
|
|
22aedcba09 | ||
|
|
2767d897a4 | ||
|
|
a4420063c0 | ||
|
|
2320352124 | ||
|
|
c0b4155ab4 | ||
|
|
b09f31d654 | ||
|
|
30c33d46f9 | ||
|
|
651b79a124 | ||
|
|
2e3cf54f11 | ||
|
|
d7948afd98 | ||
|
|
4cefa1dfa9 | ||
|
|
0cfb8b4020 | ||
|
|
9ac726b271 | ||
|
|
232605304e | ||
|
|
6c53677e7d | ||
|
|
6d0e2c2022 | ||
|
|
8ad1fb2871 | ||
|
|
4a7ff9e9ed | ||
|
|
f54598c201 | ||
|
|
2300e68fff | ||
|
|
6996824157 | ||
|
|
524f695829 | ||
|
|
72faa067cc | ||
|
|
01aa75471c | ||
|
|
048206eb1e | ||
|
|
ad5b0caa4d | ||
|
|
0f14ddcf79 | ||
|
|
59d2a8e551 | ||
|
|
8607ceb3b7 | ||
|
|
b82e5a48a4 | ||
|
|
30c5147c62 | ||
|
|
9d63500f95 | ||
|
|
a03bdc7616 | ||
|
|
413daee551 | ||
|
|
f3ea7008e5 | ||
|
|
8bfbbd2b29 | ||
|
|
ab8c7df0b9 | ||
|
|
975eb60e90 | ||
|
|
6076151222 | ||
|
|
9cc96f1888 | ||
|
|
7aa4d5159c | ||
|
|
9b021c4093 | ||
|
|
54c303369e | ||
|
|
8f30042e49 | ||
|
|
4c33270d26 | ||
|
|
5c40577bec | ||
|
|
3d404f9755 | ||
|
|
1b5e0197e4 | ||
|
|
1dab729d84 | ||
|
|
3eac5bcaf3 | ||
|
|
8eb23f0f1d | ||
|
|
1fd1a12fce | ||
|
|
349d506b37 | ||
|
|
a981b05aa7 | ||
|
|
654f06d20d | ||
|
|
c92cd10499 | ||
|
|
ed06ea6bc9 | ||
|
|
3d531151c6 | ||
|
|
e1590fc0c8 | ||
|
|
dbb227406b | ||
|
|
b891e1d1f4 | ||
|
|
1d697e3b87 | ||
|
|
128484c55a | ||
|
|
ff22c34bb2 | ||
|
|
e7ba3f76dc | ||
|
|
1ae3324581 | ||
|
|
ba8ce15ab4 | ||
|
|
87b4ce5185 | ||
|
|
4eb2b77138 | ||
|
|
70ee49f3c6 | ||
|
|
f223a26748 | ||
|
|
4574fdc951 | ||
|
|
4f66614cdd | ||
|
|
6608172719 | ||
|
|
6c8db47e25 | ||
|
|
3eb5e82d10 | ||
|
|
8563230f9c | ||
|
|
019f428f0a | ||
|
|
1847af13d2 | ||
|
|
8916df8d7b | ||
|
|
f66da92299 | ||
|
|
979df5f17e | ||
|
|
d50c8153b2 | ||
|
|
b3ab7a1069 | ||
|
|
6af58ad90d | ||
|
|
5c36a2d402 | ||
|
|
6df70cc5ed | ||
|
|
d5b0893e90 |
@@ -0,0 +1,84 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
|
||||||
|
# CA1031: Do not catch general exception types
|
||||||
|
|
||||||
|
# Microsoft .NET properties
|
||||||
|
csharp_new_line_before_members_in_object_initializers = false
|
||||||
|
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
|
||||||
|
csharp_style_var_elsewhere = true:suggestion
|
||||||
|
csharp_style_var_for_built_in_types = true:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
dotnet_naming_rule.constants_rule.severity = warning
|
||||||
|
dotnet_naming_rule.constants_rule.style = upper_camel_case_style
|
||||||
|
dotnet_naming_rule.constants_rule.symbols = constants_symbols
|
||||||
|
dotnet_naming_rule.public_fields_rule.severity = warning
|
||||||
|
dotnet_naming_rule.public_fields_rule.style = lower_camel_case_style
|
||||||
|
dotnet_naming_rule.public_fields_rule.symbols = public_fields_symbols
|
||||||
|
dotnet_naming_rule.static_readonly_rule.severity = warning
|
||||||
|
dotnet_naming_rule.static_readonly_rule.style = upper_camel_case_style
|
||||||
|
dotnet_naming_rule.static_readonly_rule.symbols = static_readonly_symbols
|
||||||
|
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
|
||||||
|
dotnet_naming_style.lower_camel_case_style.required_prefix = _
|
||||||
|
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
|
||||||
|
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||||
|
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.constants_symbols.required_modifiers = const
|
||||||
|
dotnet_naming_symbols.public_fields_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||||
|
dotnet_naming_symbols.public_fields_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.static_readonly_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||||
|
dotnet_naming_symbols.static_readonly_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.static_readonly_symbols.required_modifiers = static,readonly
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
dotnet_style_qualification_for_event = false:suggestion
|
||||||
|
dotnet_style_qualification_for_field = false:suggestion
|
||||||
|
dotnet_style_qualification_for_method = false:suggestion
|
||||||
|
dotnet_style_qualification_for_property = false:suggestion
|
||||||
|
|
||||||
|
# ReSharper properties
|
||||||
|
resharper_autodetect_indent_settings = true
|
||||||
|
resharper_default_private_modifier = implicit
|
||||||
|
resharper_place_accessorholder_attribute_on_same_line = false
|
||||||
|
resharper_use_indent_from_vs = false
|
||||||
|
|
||||||
|
# ReSharper inspection severities
|
||||||
|
resharper_arrange_redundant_parentheses_highlighting = hint
|
||||||
|
resharper_arrange_this_qualifier_highlighting = hint
|
||||||
|
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
|
||||||
|
resharper_built_in_type_reference_style_highlighting = hint
|
||||||
|
resharper_redundant_base_qualifier_highlighting = warning
|
||||||
|
resharper_suggest_var_or_type_built_in_types_highlighting = hint
|
||||||
|
resharper_suggest_var_or_type_elsewhere_highlighting = hint
|
||||||
|
resharper_suggest_var_or_type_simple_types_highlighting = hint
|
||||||
|
resharper_web_config_module_not_resolved_highlighting = warning
|
||||||
|
resharper_web_config_type_not_resolved_highlighting = warning
|
||||||
|
resharper_web_config_wrong_module_highlighting = warning
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = crlf
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[{tsconfig.app.json,tsconfig.e2e.json,tsconfig.json,tsconfig.lib.json,tsconfig.spec.json}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve.
|
||||||
|
title: ''
|
||||||
|
labels: 'bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
### Which project is your bug related to?
|
||||||
|
<!-- Remove the items which don't apply from the following list -->
|
||||||
|
- Client
|
||||||
|
- ManagedClient
|
||||||
|
- MQTTnet.Server standalone
|
||||||
|
- Server
|
||||||
|
- Generic
|
||||||
|
|
||||||
|
### To Reproduce
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Using this version of MQTTnet '...'.
|
||||||
|
2. Run this code '....'.
|
||||||
|
3. With these arguments '....'.
|
||||||
|
4. See error.
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
### Additional context / logging
|
||||||
|
Add any other context about the problem here.
|
||||||
|
Include debugging or logging information here:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
\\ Put your logging output here.
|
||||||
|
```
|
||||||
|
### Code example
|
||||||
|
Please provide full code examples below where possible to make it easier for the developers to check your issues.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
\\ Put your code here.
|
||||||
|
```
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: Custom issue template
|
||||||
|
about: Do you have a question related to the project? Use this template.
|
||||||
|
title: ''
|
||||||
|
labels: 'question'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Describe your question
|
||||||
|
A clear and concise description of what you want to know.
|
||||||
|
|
||||||
|
### Which project is your question related to?
|
||||||
|
<!-- Remove the items which don't apply from the following list -->
|
||||||
|
- Client
|
||||||
|
- ManagedClient
|
||||||
|
- MQTTnet.Server standalone
|
||||||
|
- Server
|
||||||
|
- Generic
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project.
|
||||||
|
title: ''
|
||||||
|
labels: 'feature-request'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Describe the feature request
|
||||||
|
Is your feature request related to a problem? Please describe.
|
||||||
|
A clear and concise description of what the problem is. Example. I'm am trying to do [...] but [...]
|
||||||
|
|
||||||
|
### Which project is your feature request related to?
|
||||||
|
<!-- Remove the items which don't apply from the following list -->
|
||||||
|
- Client
|
||||||
|
- ManagedClient
|
||||||
|
- MQTTnet.Server standalone
|
||||||
|
- Server
|
||||||
|
- Generic
|
||||||
|
|
||||||
|
### Describe the solution you'd like
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
### Describe alternatives you've considered
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ master ]
|
||||||
|
schedule:
|
||||||
|
- cron: '23 9 * * 6'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'csharp' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||||
|
# Learn more:
|
||||||
|
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# This is a basic workflow to help you get started with Actions
|
||||||
|
|
||||||
|
name: Deb Packaging
|
||||||
|
|
||||||
|
# Controls when the action will run.
|
||||||
|
on:
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Parse version
|
||||||
|
run: echo VERSION=$(grep '<Version>' Source/MQTTnet.Server/MQTTnet.Server.csproj | grep [0-9\.]* -o) >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build MQTTnetServer
|
||||||
|
run: dotnet publish Source/MQTTnet.Server/MQTTnet.Server.csproj --configuration Release --self-contained --runtime linux-x64 --framework net5.0
|
||||||
|
|
||||||
|
- name: Set up installation directory
|
||||||
|
run: mkdir -p packaging/opt/MQTTnetServer
|
||||||
|
|
||||||
|
- name: Copy meta data
|
||||||
|
run: |
|
||||||
|
cp -R Build/deb-meta/* packaging/
|
||||||
|
chmod 755 packaging/DEBIAN/postinst
|
||||||
|
chmod 755 packaging/DEBIAN/postrm
|
||||||
|
chmod 755 packaging/DEBIAN/prerm
|
||||||
|
|
||||||
|
- name: Move artifacts to packaging directory
|
||||||
|
run: cp -R Source/MQTTnet.Server/bin/Release/net5.0/linux-x64/publish/* packaging/opt/MQTTnetServer
|
||||||
|
|
||||||
|
- name: Adjust files
|
||||||
|
run: |
|
||||||
|
rm packaging/opt/MQTTnetServer/appsettings.Development.json
|
||||||
|
mv packaging/opt/MQTTnetServer/appsettings.json packaging/opt/MQTTnetServer/appsettings.template.json
|
||||||
|
|
||||||
|
- name: Adjust permissions
|
||||||
|
run: |
|
||||||
|
cd packaging/opt/MQTTnetServer
|
||||||
|
find . -type f | xargs chmod -R 644
|
||||||
|
chmod 755 MQTTnet.Server
|
||||||
|
|
||||||
|
- name: Generate MD5s
|
||||||
|
run: |
|
||||||
|
cd packaging/
|
||||||
|
md5sum $(find * -type f -not -path 'DEBIAN/*') > DEBIAN/md5sums
|
||||||
|
|
||||||
|
- name: Patch meta
|
||||||
|
run: sed -i 's/\VERSIONPLACEHOLDER/${{ env.VERSION }}/' packaging/DEBIAN/control
|
||||||
|
|
||||||
|
- name: Package everything
|
||||||
|
run: dpkg-deb -v --build packaging/ mqttnet-server_${{ env.VERSION }}-1_amd64.deb
|
||||||
|
|
||||||
|
- name: Save artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: mqttnet-server
|
||||||
|
path: mqttnet-server_${{ env.VERSION }}-1_amd64.deb
|
||||||
@@ -292,3 +292,7 @@ __pycache__/
|
|||||||
*.map
|
*.map
|
||||||
|
|
||||||
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
|
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
|
||||||
|
|
||||||
|
Build/NuGet/
|
||||||
|
|
||||||
|
Build/nuget.exe
|
||||||
|
|||||||
@@ -3,23 +3,30 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.AspNetCore</id>
|
<id>MQTTnet.AspNetCore</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is a support library to integrate MQTTnet into AspNetCore.</description>
|
<description>This is a support library to integrate MQTTnet into AspNetCore.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<group targetFramework="netstandard2.0">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.0" />
|
||||||
|
</group>
|
||||||
|
|
||||||
<dependency id="Microsoft.AspNetCore.Connections.Abstractions" version="2.1.3" />
|
<group targetFramework="netcoreapp3.1">
|
||||||
<dependency id="Microsoft.AspNetCore.Http.Connections" version="1.0.3" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
<dependency id="Microsoft.AspNetCore.WebSockets" version="2.1.1" />
|
</group>
|
||||||
<dependency id="Microsoft.Extensions.Hosting.Abstractions" version="2.1.1" />
|
|
||||||
|
<group targetFramework="net5.0">
|
||||||
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
</group>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
@@ -27,7 +34,16 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<file src="..\LICENSE" />
|
<file src="..\LICENSE" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<file src="..\Images\Logo_128x128.png" target="images\" />
|
||||||
|
|
||||||
|
<!-- .NET 5.0 -->
|
||||||
|
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\net5.0\MQTTnet.AspNetCore.*" target="lib\net5.0\" />
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netstandard2.0\MQTTnet.AspNetCore.*" target="lib\netstandard2.0\" />
|
||||||
|
|
||||||
|
<!-- .NET Core App 3.1 -->
|
||||||
|
<file src="..\Source\MQTTnet.AspNetCore\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.*" target="lib\netcoreapp3.1\" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
||||||
|
|||||||
@@ -3,16 +3,17 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.ManagedClient</id>
|
<id>MQTTnet.Extensions.ManagedClient</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description>
|
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -22,20 +23,29 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<file src="..\LICENSE" />
|
<file src="..\LICENSE" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<file src="..\Images\Logo_128x128.png" target="images\" />
|
||||||
|
|
||||||
|
<!-- .NET 5.0 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net5.0\MQTTnet.Extensions.ManagedClient.*" target="lib\net5.0\" />
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
<!-- .NET Standard 1.3 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\"/>
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard1.3\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard1.3\" />
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.0\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.0\" />
|
||||||
|
|
||||||
|
<!-- .NET Standard 2.1 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\netstandard2.1\MQTTnet.Extensions.ManagedClient.*" target="lib\netstandard2.1\" />
|
||||||
|
|
||||||
<!-- Universal Windows -->
|
<!-- Universal Windows -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\uap10.0\MQTTnet.Extensions.ManagedClient.*" target="lib\uap10.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\uap10.0\MQTTnet.Extensions.ManagedClient.*" target="lib\uap10.0\" />
|
||||||
|
|
||||||
<!-- .NET Framework -->
|
<!-- .NET Framework -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net452\MQTTnet.Extensions.ManagedClient.*" target="lib\net452\"/>
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net452\MQTTnet.Extensions.ManagedClient.*" target="lib\net452\" />
|
||||||
|
|
||||||
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
|
<file src="..\Source\MQTTnet.Extensions.ManagedClient\bin\Release\net461\MQTTnet.Extensions.ManagedClient.*" target="lib\net461\" />
|
||||||
|
|
||||||
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
||||||
</files>
|
</files>
|
||||||
|
|||||||
@@ -3,16 +3,17 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.Rpc</id>
|
<id>MQTTnet.Extensions.Rpc</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
|
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -22,20 +23,29 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<file src="..\LICENSE" />
|
<file src="..\LICENSE" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<file src="..\Images\Logo_128x128.png" target="images\" />
|
||||||
|
|
||||||
|
<!-- .NET 5.0 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net5.0\MQTTnet.Extensions.Rpc.*" target="lib\net5.0\" />
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
<!-- .NET Standard 1.3 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\"/>
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard1.3\MQTTnet.Extensions.Rpc.*" target="lib\netstandard1.3\" />
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.0\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.0\" />
|
||||||
|
|
||||||
|
<!-- .NET Standard 2.1 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\netstandard2.1\MQTTnet.Extensions.Rpc.*" target="lib\netstandard2.1\" />
|
||||||
|
|
||||||
<!-- Universal Windows -->
|
<!-- Universal Windows -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\uap10.0\MQTTnet.Extensions.Rpc.*" target="lib\uap10.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\uap10.0\MQTTnet.Extensions.Rpc.*" target="lib\uap10.0\" />
|
||||||
|
|
||||||
<!-- .NET Framework -->
|
<!-- .NET Framework -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net452\MQTTnet.Extensions.Rpc.*" target="lib\net452\"/>
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net452\MQTTnet.Extensions.Rpc.*" target="lib\net452\" />
|
||||||
|
|
||||||
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\"/>
|
<file src="..\Source\MQTTnet.Extensions.Rpc\bin\Release\net461\MQTTnet.Extensions.Rpc.*" target="lib\net461\" />
|
||||||
|
|
||||||
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
||||||
</files>
|
</files>
|
||||||
|
|||||||
@@ -3,18 +3,20 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet.Extensions.WebSocket4Net</id>
|
<id>MQTTnet.Extensions.WebSocket4Net</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description>
|
<description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description>
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MQTTnet" version="$nugetVersion" />
|
<dependency id="MQTTnet" version="$nugetVersion" />
|
||||||
|
<dependency id="WebSocket4Net" version="0.15.2" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
@@ -22,20 +24,29 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<file src="..\LICENSE" />
|
<file src="..\LICENSE" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<file src="..\Images\Logo_128x128.png" target="images\" />
|
||||||
|
|
||||||
|
<!-- .NET 5.0 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net5.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net5.0\" />
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
<!-- .NET Standard 1.3 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\"/>
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\" />
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\" />
|
||||||
|
|
||||||
|
<!-- .NET Standard 2.1 -->
|
||||||
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.1\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.1\" />
|
||||||
|
|
||||||
<!-- Universal Windows -->
|
<!-- Universal Windows -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\uap10.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\uap10.0\"/>
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\uap10.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\uap10.0\" />
|
||||||
|
|
||||||
<!-- .NET Framework -->
|
<!-- .NET Framework -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net452\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net452\"/>
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net452\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net452\" />
|
||||||
|
|
||||||
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
||||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net461\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net461\"/>
|
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net461\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net461\" />
|
||||||
|
|
||||||
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
||||||
</files>
|
</files>
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<package >
|
|
||||||
<metadata>
|
|
||||||
<id>MQTTnet.NETStandard</id>
|
|
||||||
<version>0.0.0</version>
|
|
||||||
<authors>Christian Kratky</authors>
|
|
||||||
<owners>Christian Kratky</owners>
|
|
||||||
<license type="file">LICENSE</license>
|
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
|
||||||
<description>This package contains the .NET Standard version of MQTTnet only.</description>
|
|
||||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes>
|
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
|
||||||
<dependencies>
|
|
||||||
<group targetFramework="netstandard1.3">
|
|
||||||
<dependency id="NETStandard.Library" version="1.3.0" />
|
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
|
||||||
</group>
|
|
||||||
<group targetFramework="netstandard2.0">
|
|
||||||
<dependency id="NETStandard.Library" version="2.0.0" />
|
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
|
||||||
</group>
|
|
||||||
</dependencies>
|
|
||||||
</metadata>
|
|
||||||
|
|
||||||
<files>
|
|
||||||
<!-- License -->
|
|
||||||
<file src="..\LICENSE" />
|
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
|
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
@@ -3,48 +3,43 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>MQTTnet</id>
|
<id>MQTTnet</id>
|
||||||
<version>0.0.0</version>
|
<version>0.0.0</version>
|
||||||
<authors>Christian Kratky</authors>
|
<authors>The contributors of MQTTnet</authors>
|
||||||
<owners>Christian Kratky</owners>
|
<owners>Christian Kratky</owners>
|
||||||
<license type="file">LICENSE</license>
|
<license type="file">LICENSE</license>
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<icon>images\Logo_128x128.png</icon>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
|
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
|
||||||
<releaseNotes>
|
<releaseNotes>
|
||||||
* [Core] Fixed issues in MQTTv5 message encoding and decoding.
|
* [Core] Fixed _DISCONNECT_ packet reading for protocol version 3.1.0.DisconnectPacket
|
||||||
* [Core] Added extension method to allow usage of _WebSocket4Net_ in clients to fix issues with AWS and Xamarin.
|
* [Client] Added support for deferred message approval (#1075, thanks to @tkurucsai).
|
||||||
* [Core] Fixed usage of wrong data type for passwords (string -> byte[]).
|
* [Client] Exposed missing APIs for .NET 5.0 build (thanks to @yyjdelete).
|
||||||
* [Core] Fixed an _ObjectDisposedException_ when sending data using a WebSocket channel.
|
* [Client] Improved disconnect handling (#1134, thanks to @yyjdelete).
|
||||||
* [Core] Performance optimizations.
|
* [Client] Fix TLS parameter options builder (#1104).
|
||||||
* [Client] Added support for extended authentication exchange.
|
* [Server] Add new overload for options builder.
|
||||||
* [Client] Exposed MQTTv5 CONNACK values to client.
|
* [Server] Exposed endpoint in _MqttServerClientDisconnectedEventArgs_.
|
||||||
* [Client] Added _MqttClientSubscribeOptionsBuilder_.
|
* [Server] Remove client disconnected handler from wrong implementation location (BREAKING CHANGE).
|
||||||
* [Client] The disconnected handler is now executed in a new task to prevent deadlocks when reconnecting etc. (thanks to @lizziebeans).
|
|
||||||
* [Client] Converted option _DualMode_ into nullable boolean to preserve original value and avoid exceptions in IPv4 only networks (thanks to @lavaflo).
|
Git commit: $gitCommit
|
||||||
* [Server] Exposed _ClientCertificateRequired_ and _CheckCertificateRevocation_ at TLS options.
|
|
||||||
* [Server] Exposed client certificate at client connection validator.
|
|
||||||
* [Server] The subscription interceptor now supports altering the entire topic filter.
|
|
||||||
* [Server] Exposed more properties to the connection validator context.
|
|
||||||
* [MQTTnet.Server] Added authentication support via Python script file.
|
|
||||||
* [MQTTnet.Server] Migrated the result of connection validations to _ReasonCode_ (MQTTv5) instead of _ReturnCode_ (MQTTv3 only) (BREAKING CHANGE!).
|
|
||||||
</releaseNotes>
|
</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2019</copyright>
|
<copyright>Copyright Christian Kratky 2016-2020</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<group targetFramework="net452" />
|
||||||
|
<group targetFramework="net461" />
|
||||||
<group targetFramework="netstandard1.3">
|
<group targetFramework="netstandard1.3">
|
||||||
<dependency id="NETStandard.Library" version="1.3.0" />
|
<dependency id="NETStandard.Library" version="1.6.1" />
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
|
||||||
</group>
|
|
||||||
<group targetFramework="netstandard2.0">
|
|
||||||
<dependency id="NETStandard.Library" version="2.0.0" />
|
|
||||||
<dependency id="System.Net.Security" version="4.3.2" />
|
<dependency id="System.Net.Security" version="4.3.2" />
|
||||||
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
<dependency id="System.Net.WebSockets" version="4.3.0" />
|
||||||
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
<dependency id="System.Net.WebSockets.Client" version="4.3.2" />
|
||||||
</group>
|
</group>
|
||||||
|
<group targetFramework="netstandard2.0" />
|
||||||
|
<group targetFramework="netstandard2.1" />
|
||||||
|
<group targetFramework="netcoreapp3.1" />
|
||||||
|
<group targetFramework="net5.0" />
|
||||||
<group targetFramework="uap10.0">
|
<group targetFramework="uap10.0">
|
||||||
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.8" />
|
<dependency id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.2.10" />
|
||||||
</group>
|
</group>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
@@ -53,21 +48,33 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<file src="..\LICENSE" />
|
<file src="..\LICENSE" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<file src="..\Images\Logo_128x128.png" target="images\" />
|
||||||
|
|
||||||
|
<!-- .NET 5.0 -->
|
||||||
|
<file src="..\Source\MQTTnet\bin\Release\net5.0\MQTTnet.*" target="lib\net5.0\" />
|
||||||
|
|
||||||
<!-- .NET Standard 1.3 -->
|
<!-- .NET Standard 1.3 -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\"/>
|
<file src="..\Source\MQTTnet\bin\Release\netstandard1.3\MQTTnet.*" target="lib\netstandard1.3\" />
|
||||||
|
|
||||||
<!-- .NET Standard 2.0 -->
|
<!-- .NET Standard 2.0 -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\"/>
|
<file src="..\Source\MQTTnet\bin\Release\netstandard2.0\MQTTnet.*" target="lib\netstandard2.0\" />
|
||||||
|
|
||||||
|
<!-- .NET Standard 2.1 -->
|
||||||
|
<file src="..\Source\MQTTnet\bin\Release\netstandard2.1\MQTTnet.*" target="lib\netstandard2.1\" />
|
||||||
|
|
||||||
|
<!-- .NET Standard 3.1 -->
|
||||||
|
<file src="..\Source\MQTTnet\bin\Release\netcoreapp3.1\MQTTnet.*" target="lib\netcoreapp3.1\" />
|
||||||
|
|
||||||
<!-- Universal Windows -->
|
<!-- Universal Windows -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\"/>
|
<file src="..\Source\MQTTnet\bin\Release\uap10.0\MQTTnet.*" target="lib\uap10.0\" />
|
||||||
|
|
||||||
<!-- .NET Framework -->
|
<!-- .NET Framework -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\"/>
|
<file src="..\Source\MQTTnet\bin\Release\net452\MQTTnet.*" target="lib\net452\" />
|
||||||
|
|
||||||
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. -->
|
||||||
<file src="..\Source\MQTTnet\bin\Release\net461\MQTTnet.*" target="lib\net461\"/>
|
<file src="..\Source\MQTTnet\bin\Release\net461\MQTTnet.*" target="lib\net461\" />
|
||||||
|
|
||||||
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. -->
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
||||||
|
|||||||
@@ -12,89 +12,67 @@ Write-Host "Nuget version = $nugetVersion"
|
|||||||
Write-Host "MSBuild path = $msbuild"
|
Write-Host "MSBuild path = $msbuild"
|
||||||
Write-Host
|
Write-Host
|
||||||
|
|
||||||
|
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
|
||||||
|
|
||||||
|
.\nuget.exe restore ..\MQTTnet.sln
|
||||||
|
|
||||||
|
# Build and execute tests
|
||||||
|
&$msbuild ..\Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
|
||||||
|
&$msbuild ..\Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /verbosity:m
|
||||||
|
|
||||||
|
vstest.console.exe ..\Tests\MQTTnet.Core.Tests\bin\Release\netcoreapp3.1\MQTTnet.Tests.dll
|
||||||
|
vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.Tests.dll
|
||||||
|
|
||||||
# Build the core library
|
# 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="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="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet\MQTTnet.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the ASP.NET Core 2.0 extension
|
# Build the ASP.NET Core 2.0 extension
|
||||||
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp3.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.AspNetCore\MQTTnet.AspNetCore.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the RPC extension
|
# Build the RPC extension
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the Managed Client extension
|
# 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="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="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
|
||||||
# Build the WebSocket4Net extension
|
# Build the WebSocket4Net extension
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.1" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
|
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net5.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
|
||||||
####################################################################
|
|
||||||
|
|
||||||
# Build MQTTnet.Server Portable
|
|
||||||
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion
|
|
||||||
|
|
||||||
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\publish"
|
|
||||||
$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)
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
|
|
||||||
# Build MQTTnet.Server Linux-x64
|
|
||||||
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-x64
|
|
||||||
|
|
||||||
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\linux-x64\publish"
|
|
||||||
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-x64-v$nugetVersion.zip"
|
|
||||||
If(Test-path $destination) {Remove-item $destination}
|
|
||||||
Add-Type -assembly "system.io.compression.filesystem"
|
|
||||||
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
|
|
||||||
# Build MQTTnet.Server Linux-ARM
|
|
||||||
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-arm
|
|
||||||
|
|
||||||
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\linux-ARM\publish"
|
|
||||||
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-ARM-v$nugetVersion.zip"
|
|
||||||
If(Test-path $destination) {Remove-item $destination}
|
|
||||||
Add-Type -assembly "system.io.compression.filesystem"
|
|
||||||
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
|
|
||||||
# Build MQTTnet.Server Windows-x64
|
|
||||||
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime win-x64
|
|
||||||
|
|
||||||
$source = "..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2\win-x64\publish"
|
|
||||||
$destination = "..\Source\MQTTnet.Server\bin\MQTTnet.Server-Windows-x64-v$nugetVersion.zip"
|
|
||||||
If(Test-path $destination) {Remove-item $destination}
|
|
||||||
Add-Type -assembly "system.io.compression.filesystem"
|
|
||||||
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
|
|
||||||
# Create NuGet packages.
|
# Create NuGet packages.
|
||||||
|
|
||||||
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
|
|
||||||
|
|
||||||
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
|
Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$gitCommit = git log -1 --format=%h
|
||||||
|
|
||||||
|
Copy-Item MQTTnet.nuspec -Destination MQTTnet.nuspec.old -Force
|
||||||
|
(Get-Content MQTTnet.nuspec) -replace '\$gitCommit', $gitCommit | Set-Content MQTTnet.nuspec
|
||||||
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
|
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
|
||||||
(Get-Content MQTTnet.AspNetCore.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.AspNetCore.nuspec
|
(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
|
Copy-Item MQTTnet.Extensions.Rpc.nuspec -Destination MQTTnet.Extensions.Rpc.nuspec.old -Force
|
||||||
@@ -105,16 +83,62 @@ Copy-Item MQTTnet.Extensions.WebSocket4Net.nuspec -Destination MQTTnet.Extension
|
|||||||
(Get-Content MQTTnet.Extensions.WebSocket4Net.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.WebSocket4Net.nuspec
|
(Get-Content MQTTnet.Extensions.WebSocket4Net.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.WebSocket4Net.nuspec
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path .\NuGet
|
New-Item -ItemType Directory -Force -Path .\NuGet
|
||||||
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.NETStandard.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
.\nuget.exe pack MQTTnet.Extensions.WebSocket4Net.nuspec -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -OutputDir "NuGet" -Version $nugetVersion
|
||||||
.\nuget.exe pack MQTTnet.Extensions.WebSocket4Net.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion
|
|
||||||
|
|
||||||
|
Move-Item MQTTnet.nuspec.old -Destination MQTTnet.nuspec -Force
|
||||||
Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force
|
Move-Item MQTTnet.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.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force
|
||||||
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force
|
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force
|
||||||
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force
|
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force
|
||||||
|
|
||||||
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
|
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
# Build MQTTnet.Server Portable
|
||||||
|
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --framework net5.0
|
||||||
|
|
||||||
|
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\publish"
|
||||||
|
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Portable-v$nugetVersion.zip"
|
||||||
|
If(Test-path $destination) {Remove-item $destination}
|
||||||
|
Add-Type -assembly "system.io.compression.filesystem"
|
||||||
|
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
# Build MQTTnet.Server Linux-x64
|
||||||
|
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-x64 --framework net5.0
|
||||||
|
|
||||||
|
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\linux-x64\publish"
|
||||||
|
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-x64-v$nugetVersion.zip"
|
||||||
|
If(Test-path $destination) {Remove-item $destination}
|
||||||
|
Add-Type -assembly "system.io.compression.filesystem"
|
||||||
|
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
# Build MQTTnet.Server Linux-ARM
|
||||||
|
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime linux-arm --framework net5.0
|
||||||
|
|
||||||
|
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\linux-ARM\publish"
|
||||||
|
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Linux-ARM-v$nugetVersion.zip"
|
||||||
|
If(Test-path $destination) {Remove-item $destination}
|
||||||
|
Add-Type -assembly "system.io.compression.filesystem"
|
||||||
|
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
# Build MQTTnet.Server Windows-x64
|
||||||
|
&dotnet publish ..\Source\MQTTnet.Server\MQTTnet.Server.csproj --configuration Release /p:FileVersion=$assemblyVersion /p:Version=$nugetVersion --self-contained --runtime win-x64 --framework net5.0
|
||||||
|
|
||||||
|
$source = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\Release\net5.0\win-x64\publish"
|
||||||
|
$destination = (Convert-Path .) + "\..\Source\MQTTnet.Server\bin\MQTTnet.Server-Windows-x64-v$nugetVersion.zip"
|
||||||
|
If(Test-path $destination) {Remove-item $destination}
|
||||||
|
Add-Type -assembly "system.io.compression.filesystem"
|
||||||
|
[io.compression.zipfile]::CreateFromDirectory($source, $destination)
|
||||||
|
|
||||||
|
####################################################################
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Package: mqttnet-server
|
||||||
|
Version: VERSIONPLACEHOLDER
|
||||||
|
Section: base
|
||||||
|
Priority: optional
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: libssl1.1
|
||||||
|
Suggests:
|
||||||
|
Maintainer: Damian Wolgast <packages@asymetrixs.net>
|
||||||
|
Description:
|
||||||
|
MQTTnet Server is a standalone cross platform MQTT server (like mosquitto) basing on this library.
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
The source of MQTTnet is at:
|
||||||
|
https://github.com/chkr1011/MQTTnet
|
||||||
|
Project is maintained by Christian Kratky
|
||||||
|
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Damian Wolgast
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if user exits
|
||||||
|
USER=mqttnetsrv
|
||||||
|
USEREXISTS=$(id -u $USER >/dev/null 2>&1; echo $?)
|
||||||
|
EC=0
|
||||||
|
BASEPATH=/opt
|
||||||
|
INSTALLPATH=$BASEPATH/MQTTnetServer
|
||||||
|
|
||||||
|
# If user does not exist, create it
|
||||||
|
if (( $USEREXISTS == 1 )); then
|
||||||
|
useradd -d $INSTALLPATH -r $USER
|
||||||
|
EC=$(echo $?)
|
||||||
|
|
||||||
|
if (( $EC == 1 )); then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set permissions on files
|
||||||
|
chown -R root:root $INSTALLPATH
|
||||||
|
|
||||||
|
# Check if config does not exist and create it
|
||||||
|
if [ ! -f "$INSTALLPATH/appsettings.json" ]; then
|
||||||
|
cp $INSTALLPATH/appsettings.template.json $INSTALLPATH/appsettings.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Check if setcap exists, does not exist in docker containers
|
||||||
|
SCAP=$(which setcap >/dev/null; echo $?)
|
||||||
|
if [ "$SCAP" -eq "0" ]; then
|
||||||
|
# Enable MQTTServer.NET to bind to IP interface
|
||||||
|
setcap CAP_NET_BIND_SERVICE=+eip $INSTALLPATH/MQTTnet.Server
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 644 /etc/systemd/system/mqttnet-server.service
|
||||||
|
|
||||||
|
# Check if systemctl exists, does not exist in docker containers
|
||||||
|
SCTL=$(which systemctl >/dev/null; echo $?)
|
||||||
|
|
||||||
|
if [ "$SCTL" -eq "0" ]; then
|
||||||
|
# Reload systemd because of new service file
|
||||||
|
systemctl daemon-reload
|
||||||
|
fi
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if systemctl exists, does not exist in docker containers
|
||||||
|
SCTL=$(which systemctl >/dev/null; echo $?)
|
||||||
|
if [ "$SCTL" -eq "0" ]; then
|
||||||
|
# Reload systemd because of new service file
|
||||||
|
systemctl daemon-reload
|
||||||
|
fi
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BASEPATH=/opt
|
||||||
|
INSTALLPATH=$BASEPATH/MQTTnetServer
|
||||||
|
|
||||||
|
# Check if systemctl exists, does not exist in docker containers
|
||||||
|
SCTL=$(which systemctl >/dev/null; echo $?)
|
||||||
|
if [ "$SCTL" -eq "0" ]; then
|
||||||
|
# Stop service before uninstalling
|
||||||
|
systemctl stop mqttnet-server
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if setcap exists, does not exist in docker containers
|
||||||
|
SCAP=$(which setcap >/dev/null; echo $?)
|
||||||
|
if [ "$SCAP" -eq "0" ]; then
|
||||||
|
# Remove permission to open ports
|
||||||
|
setcap CAP_NET_BIND_SERVICE=-eip $INSTALLPATH/MQTTnet.Server
|
||||||
|
fi
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=MQTTnetServer
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/MQTTnetServer/MQTTnet.Server
|
||||||
|
WorkingDirectory=/opt/MQTTnetServer
|
||||||
|
StandardOutput=inherit
|
||||||
|
StandardError=inherit
|
||||||
|
Restart=always
|
||||||
|
User=mqttnetsrv
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -7,7 +7,7 @@ foreach ($file in $files)
|
|||||||
{
|
{
|
||||||
Write-Host "Uploading: " $file
|
Write-Host "Uploading: " $file
|
||||||
|
|
||||||
.\nuget.exe push $file.Fullname $apiKey -NoSymbols -Source https://api.nuget.org/v3/index.json
|
.\nuget.exe push $file.Fullname $apiKey -Source https://api.nuget.org/v3/index.json
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
|
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# Import codeSigningKey.pfx
|
# 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:
|
In order to import the key for code signing on a new developer machine use the following command within the VS developer command line:
|
||||||
|
|
||||||
> sn –i codeSigningKey.pfx VS_KEY_EFCA4C5B6DFD4B4F
|
sn –i .\codeSigningKey.pfx VS_KEY_62CA73019ED23333
|
||||||
|
|
||||||
The container name may be different.
|
The container name may be different.
|
||||||
|
|
||||||
# Check if the assembly has a strong name
|
# Check if the assembly has a strong name
|
||||||
> sn -vf MQTTnet.dll
|
sn -vf MQTTnet.dll
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,239 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="MQTT.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<filter
|
||||||
|
inkscape:label="Blur Double"
|
||||||
|
inkscape:menu="Blurs"
|
||||||
|
inkscape:menu-tooltip="Overlays two copies with different blur amounts and modifiable blend and composite"
|
||||||
|
style="color-interpolation-filters:sRGB;"
|
||||||
|
id="filter3801">
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="5"
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
id="feGaussianBlur3793" />
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="0.01"
|
||||||
|
in="SourceGraphic"
|
||||||
|
result="result1"
|
||||||
|
id="feGaussianBlur3795" />
|
||||||
|
<feComposite
|
||||||
|
in2="result1"
|
||||||
|
operator="arithmetic"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
k2="0.5"
|
||||||
|
k3="0.5"
|
||||||
|
result="result2"
|
||||||
|
id="feComposite3797" />
|
||||||
|
<feBlend
|
||||||
|
in2="fbSourceGraphic"
|
||||||
|
mode="normal"
|
||||||
|
result="result3"
|
||||||
|
id="feBlend3799" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.24748737"
|
||||||
|
inkscape:cx="955.72999"
|
||||||
|
inkscape:cy="295.38958"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2066"
|
||||||
|
inkscape:window-x="2989"
|
||||||
|
inkscape:window-y="-11"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
ry="50"
|
||||||
|
rx="50"
|
||||||
|
style="fill:#000000;stroke-width:0.26458332;filter:url(#filter3801)"
|
||||||
|
y="92.501205"
|
||||||
|
x="56.367012"
|
||||||
|
height="512"
|
||||||
|
width="512"
|
||||||
|
id="rect3791"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<rect
|
||||||
|
id="rect3713"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="53.721176"
|
||||||
|
y="88.797035"
|
||||||
|
style="fill:#aa0000;stroke-width:0.26458332"
|
||||||
|
rx="50"
|
||||||
|
ry="50"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:0.28100395"
|
||||||
|
id="rect3806"
|
||||||
|
width="143.25298"
|
||||||
|
height="9.0714283"
|
||||||
|
x="270.81995"
|
||||||
|
y="554.02386"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4638"
|
||||||
|
d="m 494.14104,142.00092 -5.35736,41.28822 67.77684,374.38977 a 263.46279,229.17651 36.835702 0 1 4.98278,-0.4605 263.46279,229.17651 36.835702 0 1 7.77403,0.0471 z"
|
||||||
|
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:0.59952348"
|
||||||
|
inkscape:transform-center-x="-28.818481"
|
||||||
|
inkscape:transform-center-y="146.97441"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<path
|
||||||
|
style="fill:#d40000;stroke-width:1.76103246"
|
||||||
|
d="m 2138.1582,1411.377 a 995.76488,866.17897 0 0 0 -842.3984,854.3418 995.76488,866.17897 0 0 0 0.2988,5.0097 h 653.123 c 104.693,0 188.9766,-84.2836 188.9766,-188.9765 z"
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="path3715-5-8"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#d40000;stroke-width:0.06901014"
|
||||||
|
id="path3715-5"
|
||||||
|
cx="492.58557"
|
||||||
|
cy="170.58017"
|
||||||
|
rx="39.021355"
|
||||||
|
ry="33.94323"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<path
|
||||||
|
style="fill:#ce0000;fill-opacity:0.60591131;stroke-width:2.26591563"
|
||||||
|
d="M 464.66602,532.89453 542.01562,669.92969 1595.373,1648.873 a 995.76487,866.17896 0 0 1 14.0293,-12.6835 995.76487,866.17896 0 0 1 23.6231,-17.4727 z"
|
||||||
|
id="rect3806-2"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="102.34985"
|
||||||
|
y="320.75201"
|
||||||
|
id="text3774"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3772"
|
||||||
|
x="102.34985"
|
||||||
|
y="320.75201"
|
||||||
|
style="font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332">MQTT</tspan></text>
|
||||||
|
<ellipse
|
||||||
|
ry="33.94323"
|
||||||
|
rx="39.021355"
|
||||||
|
cy="148.56271"
|
||||||
|
cx="124.47787"
|
||||||
|
id="ellipse3768"
|
||||||
|
style="fill:#d40000;stroke-width:0.06901014"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#d40000;stroke-width:0.06901014"
|
||||||
|
id="ellipse3770"
|
||||||
|
cx="234.9953"
|
||||||
|
cy="556.91571"
|
||||||
|
rx="39.021355"
|
||||||
|
ry="33.94323"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001" />
|
||||||
|
<text
|
||||||
|
id="text3778"
|
||||||
|
y="474.73837"
|
||||||
|
x="194.57605"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-xdpi="2.6500001"
|
||||||
|
inkscape:export-ydpi="2.6500001"><tspan
|
||||||
|
style="font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332"
|
||||||
|
y="474.73837"
|
||||||
|
x="194.57605"
|
||||||
|
id="tspan3776"
|
||||||
|
sodipodi:role="line">net</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="50"
|
||||||
|
rx="50"
|
||||||
|
style="fill:#aa0000;stroke-width:0.26458332"
|
||||||
|
y="97.349655"
|
||||||
|
x="-672.18286"
|
||||||
|
height="512"
|
||||||
|
width="512"
|
||||||
|
id="rect4642"
|
||||||
|
inkscape:export-xdpi="6.3499999"
|
||||||
|
inkscape:export-ydpi="6.3499999" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4648"
|
||||||
|
d="m -160.18302,381.97945 a 263.46279,229.17652 0 0 0 -222.88457,226.0446 263.46279,229.17652 0 0 0 0.0791,1.32549 h 172.80546 c 27.70002,0 50.00005,-22.30004 50.00005,-50.00004 z"
|
||||||
|
style="fill:#d40000;stroke-width:0.46593982"
|
||||||
|
inkscape:export-xdpi="6.3499999"
|
||||||
|
inkscape:export-ydpi="6.3499999" />
|
||||||
|
<text
|
||||||
|
id="text4656"
|
||||||
|
y="329.30466"
|
||||||
|
x="-639.42944"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-xdpi="6.3499999"
|
||||||
|
inkscape:export-ydpi="6.3499999"><tspan
|
||||||
|
style="font-weight:bold;font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332"
|
||||||
|
y="329.30466"
|
||||||
|
x="-639.42944"
|
||||||
|
id="tspan4654"
|
||||||
|
sodipodi:role="line">MQTT</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-550.90747"
|
||||||
|
y="482.23267"
|
||||||
|
id="text4664"
|
||||||
|
inkscape:export-xdpi="6.3499999"
|
||||||
|
inkscape:export-ydpi="6.3499999"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4662"
|
||||||
|
x="-550.90747"
|
||||||
|
y="482.23267"
|
||||||
|
style="font-weight:bold;font-size:141.1111145px;fill:#ffffff;stroke-width:0.26458332">net</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
MQTTnet Copyright (c) 2016-2019 Christian Kratky
|
Copyright (c) 2016-2019 Christian Kratky
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.UniversalWindows", "Tests\MQTTnet.TestApp.UniversalWindows\MQTTnet.TestApp.UniversalWindows.csproj", "{FF1F72D6-9524-4422-9497-3CC0002216ED}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
|
||||||
@@ -20,7 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1
|
|||||||
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
|
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec
|
||||||
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
|
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec
|
||||||
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec
|
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec
|
||||||
Build\MQTTnet.NETStandard.nuspec = Build\MQTTnet.NETStandard.nuspec
|
|
||||||
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
|
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec
|
||||||
Build\upload.ps1 = Build\upload.ps1
|
Build\upload.ps1 = Build\upload.ps1
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
@@ -28,6 +25,7 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.bettercodehub.yml = .bettercodehub.yml
|
.bettercodehub.yml = .bettercodehub.yml
|
||||||
|
.editorconfig = .editorconfig
|
||||||
appveyor.yml = appveyor.yml
|
appveyor.yml = appveyor.yml
|
||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
@@ -53,6 +51,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQ
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{2BD01D53-4CA5-4142-BE8D-313876395E3E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{2BD01D53-4CA5-4142-BE8D-313876395E3E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{A56E3128-1639-4F31-873A-325E14BB6295}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Server", "Tests\MQTTnet.Test.BlazorApp\Server\MQTTnet.Test.BlazorApp.Server.csproj", "{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Client", "Tests\MQTTnet.Test.BlazorApp\Client\MQTTnet.Test.BlazorApp.Client.csproj", "{D260D63D-7902-4C55-9665-84C5CACBBB24}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Test.BlazorApp.Shared", "Tests\MQTTnet.Test.BlazorApp\Shared\MQTTnet.Test.BlazorApp.Shared.csproj", "{DDB069BA-6E1A-48C7-B374-5D903B553CAD}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -81,29 +89,6 @@ Global
|
|||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
|
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
|
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
|
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.ActiveCfg = Debug|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Build.0 = Debug|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Deploy.0 = Debug|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Deploy.0 = Debug|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Deploy.0 = Debug|x86
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.ActiveCfg = Release|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Build.0 = Release|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Deploy.0 = Release|ARM
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Build.0 = Release|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Deploy.0 = Release|x64
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Build.0 = Release|x86
|
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Deploy.0 = Release|x86
|
|
||||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
@@ -264,13 +249,60 @@ Global
|
|||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
{FF1F72D6-9524-4422-9497-3CC0002216ED} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
|
||||||
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
||||||
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{3D283AAD-AAA8-4339-8394-52F80B6304DB} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
@@ -279,8 +311,12 @@ Global
|
|||||||
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
||||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {A56E3128-1639-4F31-873A-325E14BB6295}
|
||||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
|
||||||
|
{61B165A0-5AA8-4E04-A53D-A22A84AA6EB7} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
||||||
|
{A9662AF3-3520-4BF8-9DFF-C55C0C33D08F} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
|
{D260D63D-7902-4C55-9665-84C5CACBBB24} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
|
{DDB069BA-6E1A-48C7-B374-5D903B553CAD} = {61B165A0-5AA8-4E04-A53D-A22A84AA6EB7}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
||||||
|
|||||||
@@ -11,4 +11,6 @@
|
|||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=PINGREQ/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsub/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/chkr1011/MQTTnet/blob/master/Images/Logo_128x128.png?raw=true" width="128">
|
<img src="https://github.com/chkr1011/MQTTnet/blob/master/Images/icon_det_256.png?raw=true" width="196">
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
</p>
|
</p>
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
[](https://www.nuget.org/packages/MQTTnet)
|
[](https://www.nuget.org/packages/MQTTnet)
|
||||||
[](https://ci.appveyor.com/project/chkr1011/mqttnet)
|
[](https://ci.appveyor.com/project/chkr1011/mqttnet)
|
||||||
[](https://bettercodehub.com/)
|
[](https://bettercodehub.com/)
|
||||||
[](https://opencollective.com/mqttnet)
|
[](https://gitter.im/MQTTnet/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://opencollective.com/mqttnet) [](https://gitter.im/MQTTnet/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://raw.githubusercontent.com/chkr1011/MQTTnet/master/LICENSE)
|
||||||
|
|
||||||
# MQTTnet
|
# MQTTnet
|
||||||
|
|
||||||
@@ -19,14 +19,14 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
|
|||||||
### General
|
### General
|
||||||
|
|
||||||
* Async support
|
* Async support
|
||||||
* TLS 1.2 support for client and server (but not UWP servers)
|
* TLS support for client and server (but not UWP servers)
|
||||||
* Extensible communication channels (e.g. In-Memory, TCP, TCP+TLS, WS)
|
* Extensible communication channels (e.g. In-Memory, TCP, TCP+TLS, WS)
|
||||||
* Lightweight (only the low level implementation of MQTT, no overhead)
|
* Lightweight (only the low level implementation of MQTT, no overhead)
|
||||||
* Performance optimized (processing ~70.000 messages / second)*
|
* Performance optimized (processing ~70.000 messages / second)*
|
||||||
* Uniform API across all supported versions of the MQTT protocol
|
* Uniform API across all supported versions of the MQTT protocol
|
||||||
* Interfaces included for mocking and testing
|
* Interfaces included for mocking and testing
|
||||||
* Access to internal trace messages
|
* Access to internal trace messages
|
||||||
* Unit tested (~210 tests)
|
* Unit tested (~250 tests)
|
||||||
* No external dependencies
|
* No external dependencies
|
||||||
|
|
||||||
\* Tested on local machine (Intel i7 8700K) with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetCore_.
|
\* Tested on local machine (Intel i7 8700K) with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetCore_.
|
||||||
@@ -34,7 +34,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
|
|||||||
### Client
|
### Client
|
||||||
|
|
||||||
* Communication via TCP (+TLS) or WS (WebSocket) supported
|
* Communication via TCP (+TLS) or WS (WebSocket) supported
|
||||||
* Included core _MqttClient_ with low level functionality
|
* Included core _LowLevelMqttClient_ with low level functionality
|
||||||
* Also included _ManagedMqttClient_ which maintains the connection and subscriptions automatically. Also application messages are queued and re-scheduled for higher QoS levels automatically.
|
* Also included _ManagedMqttClient_ which maintains the connection and subscriptions automatically. Also application messages are queued and re-scheduled for higher QoS levels automatically.
|
||||||
* Rx support (via another project)
|
* Rx support (via another project)
|
||||||
* Compatible with Microsoft Azure IoT Hub
|
* Compatible with Microsoft Azure IoT Hub
|
||||||
@@ -64,14 +64,32 @@ _MQTTnet Server_ is a standalone cross platform MQTT server (like mosquitto) bas
|
|||||||
|
|
||||||
## Supported frameworks
|
## Supported frameworks
|
||||||
|
|
||||||
|
* .NET 5.0+
|
||||||
* .NET Standard 1.3+
|
* .NET Standard 1.3+
|
||||||
* .NET Core 1.1+
|
* .NET Core 1.1+
|
||||||
* .NET Core App 1.1+
|
* .NET Core App 1.1+
|
||||||
* .NET Framework 4.5.2+ (x86, x64, AnyCPU)
|
* .NET Framework 4.5.2+
|
||||||
* Mono 5.2+
|
* Mono 5.2+
|
||||||
* Universal Windows Platform (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU, Windows 10 IoT Core)
|
* Universal Windows Platform (UWP) 10.0.10240+ (Windows 10 IoT Core)
|
||||||
* Xamarin.Android 7.5+
|
* Xamarin.Android 7.5+
|
||||||
* Xamarin.iOS 10.14+
|
* Xamarin.iOS 10.14+
|
||||||
|
* Blazor WebAssembly 3.2.0+
|
||||||
|
|
||||||
|
## Supported platforms
|
||||||
|
|
||||||
|
* x86
|
||||||
|
* x64
|
||||||
|
* AnyCPU
|
||||||
|
* ARM
|
||||||
|
|
||||||
|
## Supported OS
|
||||||
|
|
||||||
|
* Windows
|
||||||
|
* Windows 10 IoT Core
|
||||||
|
* Linux (Ubuntu, Raspbian etc.)
|
||||||
|
* macOS
|
||||||
|
* Android
|
||||||
|
* iOS
|
||||||
|
|
||||||
## Supported MQTT versions
|
## Supported MQTT versions
|
||||||
|
|
||||||
@@ -92,17 +110,20 @@ Please find examples and the documentation at the Wiki of this repository (<http
|
|||||||
If you want to contribute to this project just create a pull request. But only pull requests which are matching the code style of this library will be accepted. Before creating a pull request please have a look at the library to get an overview of the required style.
|
If you want to contribute to this project just create a pull request. But only pull requests which are matching the code style of this library will be accepted. Before creating a pull request please have a look at the library to get an overview of the required style.
|
||||||
Also additions and updates in the Wiki are welcome.
|
Also additions and updates in the Wiki are welcome.
|
||||||
|
|
||||||
**This project, like all projects requires time and money. If you feel compelled to support the development team, you can do so through Open Collective (https://opencollective.com/mqttnet)**.
|
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
This library is used in the following projects:
|
This library is used in the following projects:
|
||||||
|
|
||||||
* Azure Functions MQTT Bindings, [CaseOnline.Azure.WebJobs.Extensions.Mqtt](https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt/)
|
* Azure Functions MQTT Bindings, <https://github.com/keesschollaart81/CaseOnline.Azure.WebJobs.Extensions.Mqtt>)
|
||||||
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
|
* HA4IoT (Open Source Home Automation system for .NET, <https://github.com/chkr1011/HA4IoT>)
|
||||||
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
|
* MQTT Client Rx (Wrapper for Reactive Extensions, <https://github.com/1iveowl/MQTTClient.rx>)
|
||||||
|
* MQTT Client Rx (Managed Client Wrapper for Reactive Extensions, <https://github.com/mmuecke/RxMQTTnet>)
|
||||||
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
|
* MQTT Tester (MQTT client test app for [Android](https://play.google.com/store/apps/details?id=com.liveowl.mqtttester) and [iOS](https://itunes.apple.com/us/app/mqtt-tester/id1278621826?mt=8))
|
||||||
|
* MQTTnet App (Cross platform client application for MQTT debugging, inspection etc., <https://github.com/chkr1011/MQTTnet.App>)
|
||||||
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
|
* Wirehome.Core (Open Source Home Automation system for .NET Core, <https://github.com/chkr1011/Wirehome.Core>)
|
||||||
|
* SparkplugNet (Sparkplug library for .Net, <https://github.com/SeppPenner/SparkplugNet>)
|
||||||
|
|
||||||
|
Further projects using this project can be found under https://github.com/chkr1011/MQTTnet/network/dependents.
|
||||||
|
|
||||||
If you use this library and want to see your project here please create a pull request.
|
If you use this library and want to see your project here please create a pull request.
|
||||||
|
|
||||||
@@ -110,7 +131,7 @@ If you use this library and want to see your project here please create a pull r
|
|||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
MQTTnet Copyright (c) 2016-2019 Christian Kratky
|
MQTTnet Copyright (c) 2016-2021 Christian Kratky
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
using System;
|
using MQTTnet.Adapter;
|
||||||
using System.Net;
|
|
||||||
using MQTTnet.Adapter;
|
|
||||||
using MQTTnet.AspNetCore.Client.Tcp;
|
using MQTTnet.AspNetCore.Client.Tcp;
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Diagnostics;
|
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore.Client
|
namespace MQTTnet.AspNetCore.Client
|
||||||
{
|
{
|
||||||
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
|
public class MqttClientConnectionContextFactory : IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger)
|
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using System;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using MQTTnet.Exceptions;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Connections;
|
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
|
||||||
using MQTTnet.Exceptions;
|
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore.Client.Tcp
|
namespace MQTTnet.AspNetCore.Client.Tcp
|
||||||
{
|
{
|
||||||
@@ -40,8 +40,11 @@ namespace MQTTnet.AspNetCore.Client.Tcp
|
|||||||
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
|
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
|
||||||
_receiver = new SocketReceiver(_socket, PipeScheduler.ThreadPool);
|
_receiver = new SocketReceiver(_socket, PipeScheduler.ThreadPool);
|
||||||
}
|
}
|
||||||
|
#if NETCOREAPP3_1 || NET5_0
|
||||||
|
public override ValueTask DisposeAsync()
|
||||||
|
#else
|
||||||
public Task DisposeAsync()
|
public Task DisposeAsync()
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
IsConnected = false;
|
IsConnected = false;
|
||||||
|
|
||||||
@@ -50,8 +53,15 @@ namespace MQTTnet.AspNetCore.Client.Tcp
|
|||||||
|
|
||||||
_socket?.Dispose();
|
_socket?.Dispose();
|
||||||
|
|
||||||
|
#if NETCOREAPP3_1 || NET5_0
|
||||||
|
|
||||||
|
return base.DisposeAsync();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public async Task StartAsync()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Linq;
|
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ApplicationBuilderExtensions
|
public static class ApplicationBuilderExtensions
|
||||||
{
|
{
|
||||||
|
[Obsolete("This class is obsolete and will be removed in a future version. The recommended alternative is to use MapMqtt inside Microsoft.AspNetCore.Builder.UseEndpoints(...).")]
|
||||||
public static IApplicationBuilder UseMqttEndpoint(this IApplicationBuilder app, string path = "/mqtt")
|
public static IApplicationBuilder UseMqttEndpoint(this IApplicationBuilder app, string path = "/mqtt")
|
||||||
{
|
{
|
||||||
app.UseWebSockets();
|
app.UseWebSockets();
|
||||||
@@ -24,7 +23,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
||||||
{
|
{
|
||||||
subProtocol = SelectSubProtocol(requestedSubProtocolValues);
|
subProtocol = MqttSubProtocolSelector.SelectSubProtocol(requestedSubProtocolValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
|
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
|
||||||
@@ -37,14 +36,6 @@ namespace MQTTnet.AspNetCore
|
|||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string SelectSubProtocol(IList<string> requestedSubProtocolValues)
|
|
||||||
{
|
|
||||||
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
|
|
||||||
return requestedSubProtocolValues
|
|
||||||
.OrderByDescending(p => p.Length)
|
|
||||||
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
|
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
|
||||||
{
|
{
|
||||||
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
|
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ConnectionBuilderExtensions
|
public static class ConnectionBuilderExtensions
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Connections;
|
||||||
|
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
using System;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
|
{
|
||||||
|
public static class ConnectionRouteBuilderExtensions
|
||||||
|
{
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
[Obsolete("This class is obsolete and will be removed in a future version. The recommended alternative is to use MapMqtt inside Microsoft.AspNetCore.Builder.UseEndpoints(...).")]
|
||||||
|
#endif
|
||||||
|
#if NETCOREAPP3_1 || NETCOREAPP2_1 || NETSTANDARD
|
||||||
|
public static void MapMqtt(this ConnectionsRouteBuilder connection, PathString path)
|
||||||
|
{
|
||||||
|
connection.MapConnectionHandler<MqttConnectionHandler>(path, options =>
|
||||||
|
{
|
||||||
|
options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
#if NETCOREAPP3_1 || NET5_0
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
|
||||||
|
namespace MQTTnet.AspNetCore
|
||||||
|
{
|
||||||
|
public static class EndpointRouterExtensions
|
||||||
|
{
|
||||||
|
public static void MapMqtt(this IEndpointRouteBuilder endpoints, string pattern)
|
||||||
|
{
|
||||||
|
endpoints.MapConnectionHandler<MqttConnectionHandler>(pattern, options =>
|
||||||
|
{
|
||||||
|
options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,7 +5,7 @@ using MQTTnet.Exceptions;
|
|||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ReaderExtensions
|
public static class ReaderExtensions
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
headerLength = 0;
|
headerLength = 0;
|
||||||
bodyLength = 0;
|
bodyLength = 0;
|
||||||
|
|
||||||
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory();
|
var temp = input.Slice(0, Math.Min(5, input.Length)).GetMemory().Span;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -88,7 +88,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
encodedByte = temp.Span[index];
|
encodedByte = temp[index];
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
value += (byte)(encodedByte & 127) * multiplier;
|
value += (byte)(encodedByte & 127) * multiplier;
|
||||||
@@ -3,17 +3,17 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Server;
|
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
|
using MQTTnet.Server;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore.Extensions
|
||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, IMqttServerOptions options)
|
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, IMqttServerOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
services.AddSingleton(options);
|
services.AddSingleton(options);
|
||||||
|
|
||||||
services.AddHostedMqttServer();
|
services.AddHostedMqttServer();
|
||||||
@@ -23,7 +23,8 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
|
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IMqttServerOptions>(s => {
|
services.AddSingleton<IMqttServerOptions>(s =>
|
||||||
|
{
|
||||||
var builder = new MqttServerOptionsBuilder();
|
var builder = new MqttServerOptionsBuilder();
|
||||||
configure(builder);
|
configure(builder);
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
@@ -36,7 +37,8 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
|
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IMqttServerOptions>(s => {
|
services.AddSingleton<IMqttServerOptions>(s =>
|
||||||
|
{
|
||||||
var builder = new AspNetMqttServerOptionsBuilder(s);
|
var builder = new AspNetMqttServerOptionsBuilder(s);
|
||||||
configure(builder);
|
configure(builder);
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
@@ -60,14 +62,12 @@ namespace MQTTnet.AspNetCore
|
|||||||
private static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
|
private static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
var logger = new MqttNetLogger();
|
var logger = new MqttNetLogger();
|
||||||
var childLogger = logger.CreateChildLogger();
|
|
||||||
|
|
||||||
services.AddSingleton<IMqttNetLogger>(logger);
|
services.AddSingleton<IMqttNetLogger>(logger);
|
||||||
services.AddSingleton(childLogger);
|
|
||||||
services.AddSingleton<MqttHostedServer>();
|
services.AddSingleton<MqttHostedServer>();
|
||||||
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
|
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
|
||||||
services.AddSingleton<IMqttServer>(s => s.GetService<MqttHostedServer>());
|
services.AddSingleton<IMqttServer>(s => s.GetService<MqttHostedServer>());
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,24 +1,32 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
|
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' ">
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="2.1.3" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.0.3" />
|
</ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.1.1" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.1" />
|
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1' and '$(TargetFramework)' != 'net5.0' ">
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -10,11 +10,19 @@ using System.IO.Pipelines;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.AspNetCore.Extensions;
|
||||||
|
using MQTTnet.Internal;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore
|
||||||
{
|
{
|
||||||
public class MqttConnectionContext : IMqttChannelAdapter
|
public sealed class MqttConnectionContext : IMqttChannelAdapter
|
||||||
{
|
{
|
||||||
|
readonly AsyncLock _writerLock = new AsyncLock();
|
||||||
|
readonly SpanBasedMqttPacketBodyReader _reader;
|
||||||
|
|
||||||
|
PipeReader _input;
|
||||||
|
PipeWriter _output;
|
||||||
|
|
||||||
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
|
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection)
|
||||||
{
|
{
|
||||||
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
|
PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter));
|
||||||
@@ -25,18 +33,20 @@ namespace MQTTnet.AspNetCore
|
|||||||
_input = Connection.Transport.Input;
|
_input = Connection.Transport.Input;
|
||||||
_output = Connection.Transport.Output;
|
_output = Connection.Transport.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
_reader = new SpanBasedMqttPacketBodyReader();
|
_reader = new SpanBasedMqttPacketBodyReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PipeReader _input;
|
|
||||||
private PipeWriter _output;
|
|
||||||
private readonly SpanBasedMqttPacketBodyReader _reader;
|
|
||||||
|
|
||||||
public string Endpoint
|
public string Endpoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
#if NETCOREAPP3_1
|
||||||
|
if (Connection?.RemoteEndPoint != null)
|
||||||
|
{
|
||||||
|
return Connection.RemoteEndPoint.ToString();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
var connection = Http?.HttpContext?.Connection;
|
var connection = Http?.HttpContext?.Connection;
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
{
|
{
|
||||||
@@ -51,18 +61,17 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
|
public X509Certificate2 ClientCertificate => Http?.HttpContext?.Connection?.ClientCertificate;
|
||||||
|
|
||||||
private IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
|
|
||||||
|
|
||||||
public ConnectionContext Connection { get; }
|
public ConnectionContext Connection { get; }
|
||||||
|
|
||||||
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
|
public MqttPacketFormatterAdapter PacketFormatterAdapter { get; }
|
||||||
|
|
||||||
public long BytesSent { get; set; }
|
public long BytesSent { get; set; }
|
||||||
|
|
||||||
public long BytesReceived { get; set; }
|
public long BytesReceived { get; set; }
|
||||||
|
|
||||||
public Action ReadingPacketStartedCallback { get; set; }
|
public bool IsReadingPacket { get; private set; }
|
||||||
public Action ReadingPacketCompletedCallback { get; set; }
|
|
||||||
|
|
||||||
private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);
|
IHttpContextFeature Http => Connection.Features.Get<IHttpContextFeature>();
|
||||||
|
|
||||||
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -83,7 +92,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task<MqttBasePacket> ReceivePacketAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var input = Connection.Transport.Input;
|
var input = Connection.Transport.Input;
|
||||||
|
|
||||||
@@ -119,7 +128,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we did receive something but the message is not yet complete
|
// we did receive something but the message is not yet complete
|
||||||
ReadingPacketStartedCallback?.Invoke();
|
IsReadingPacket = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (readResult.IsCompleted)
|
else if (readResult.IsCompleted)
|
||||||
@@ -136,9 +145,16 @@ namespace MQTTnet.AspNetCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// completing the channel makes sure that there is no more data read after a protocol error
|
||||||
|
_input?.Complete(e);
|
||||||
|
_output?.Complete(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ReadingPacketCompletedCallback?.Invoke();
|
IsReadingPacket = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@@ -151,26 +167,21 @@ namespace MQTTnet.AspNetCore
|
|||||||
BytesSent = 0;
|
BytesSent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken)
|
public async Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var formatter = PacketFormatterAdapter;
|
var formatter = PacketFormatterAdapter;
|
||||||
|
using (await _writerLock.WaitAsync(cancellationToken).ConfigureAwait(false))
|
||||||
|
|
||||||
await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var buffer = formatter.Encode(packet);
|
var buffer = formatter.Encode(packet);
|
||||||
var msg = buffer.AsMemory();
|
var msg = buffer.AsMemory();
|
||||||
var output = _output;
|
var output = _output;
|
||||||
msg.CopyTo(output.GetMemory(msg.Length));
|
var result = await output.WriteAsync(msg, cancellationToken).ConfigureAwait(false);
|
||||||
BytesSent += msg.Length;
|
if (result.IsCompleted)
|
||||||
|
{
|
||||||
|
BytesSent += msg.Length;
|
||||||
|
}
|
||||||
|
|
||||||
PacketFormatterAdapter.FreeBuffer();
|
PacketFormatterAdapter.FreeBuffer();
|
||||||
output.Advance(msg.Length);
|
|
||||||
await output.FlushAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_writerSemaphore.Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,15 @@ namespace MQTTnet.AspNetCore
|
|||||||
private readonly IMqttServerOptions _options;
|
private readonly IMqttServerOptions _options;
|
||||||
|
|
||||||
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||||
: base(adapters, logger.CreateChildLogger(nameof(MqttHostedServer)))
|
: base(adapters, logger)
|
||||||
{
|
{
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return StartAsync(_options);
|
_ = StartAsync(_options);
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace MQTTnet.AspNetCore
|
||||||
|
{
|
||||||
|
public static class MqttSubProtocolSelector
|
||||||
|
{
|
||||||
|
public static string SelectSubProtocol(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new ArgumentNullException(nameof(request));
|
||||||
|
|
||||||
|
string subProtocol = null;
|
||||||
|
if (request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
||||||
|
{
|
||||||
|
subProtocol = SelectSubProtocol(requestedSubProtocolValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SelectSubProtocol(IList<string> requestedSubProtocolValues)
|
||||||
|
{
|
||||||
|
if (requestedSubProtocolValues == null) throw new ArgumentNullException(nameof(requestedSubProtocolValues));
|
||||||
|
|
||||||
|
// Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
|
||||||
|
return requestedSubProtocolValues
|
||||||
|
.OrderByDescending(p => p.Length)
|
||||||
|
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,22 @@
|
|||||||
using System;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
using System;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.AspNetCore
|
namespace MQTTnet.AspNetCore
|
||||||
{
|
{
|
||||||
public class MqttWebSocketServerAdapter : IMqttServerAdapter
|
public sealed class MqttWebSocketServerAdapter : IMqttServerAdapter
|
||||||
{
|
{
|
||||||
private readonly IMqttNetChildLogger _logger;
|
readonly IMqttNetLogger _rootLogger;
|
||||||
|
|
||||||
public MqttWebSocketServerAdapter(IMqttNetChildLogger logger)
|
public MqttWebSocketServerAdapter(IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
_rootLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||||
@@ -38,7 +36,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
|
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
|
||||||
|
|
||||||
var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}";
|
var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}";
|
||||||
|
|
||||||
var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false);
|
var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -51,7 +49,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
var formatter = new MqttPacketFormatterAdapter(writer);
|
var formatter = new MqttPacketFormatterAdapter(writer);
|
||||||
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
|
var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate);
|
||||||
|
|
||||||
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter))))
|
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _rootLogger))
|
||||||
{
|
{
|
||||||
await clientHandler(channelAdapter).ConfigureAwait(false);
|
await clientHandler(channelAdapter).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
|
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
|
||||||
{
|
{
|
||||||
private ReadOnlyMemory<byte> _buffer;
|
ReadOnlyMemory<byte> _buffer;
|
||||||
|
|
||||||
private int _offset;
|
int _offset;
|
||||||
|
|
||||||
public void SetBuffer(ReadOnlyMemory<byte> buffer)
|
public void SetBuffer(ReadOnlyMemory<byte> buffer)
|
||||||
{
|
{
|
||||||
@@ -38,16 +38,6 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
return ReadSegmentWithLengthPrefix().ToArray();
|
return ReadSegmentWithLengthPrefix().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
|
|
||||||
{
|
|
||||||
var span = _buffer.Span;
|
|
||||||
var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
|
|
||||||
|
|
||||||
var result = span.Slice(_offset+2, length);
|
|
||||||
_offset += 2 + length;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe string ReadStringWithLengthPrefix()
|
public unsafe string ReadStringWithLengthPrefix()
|
||||||
{
|
{
|
||||||
@@ -121,5 +111,19 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
_offset = position;
|
_offset = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
|
||||||
|
{
|
||||||
|
var span = _buffer.Span;
|
||||||
|
var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
|
||||||
|
|
||||||
|
if (Length < _offset + length)
|
||||||
|
{
|
||||||
|
throw new MqttProtocolViolationException($"Expected at least {_offset + 2 + length} bytes but there are only {Length} bytes");
|
||||||
|
}
|
||||||
|
var result = span.Slice(_offset + 2, length);
|
||||||
|
_offset += 2 + length;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,15 @@ namespace MQTTnet.AspNetCore
|
|||||||
{
|
{
|
||||||
public class SpanBasedMqttPacketWriter : IMqttPacketWriter
|
public class SpanBasedMqttPacketWriter : IMqttPacketWriter
|
||||||
{
|
{
|
||||||
private readonly ArrayPool<byte> _pool;
|
readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create();
|
||||||
|
|
||||||
public SpanBasedMqttPacketWriter()
|
public SpanBasedMqttPacketWriter()
|
||||||
{
|
{
|
||||||
_pool = ArrayPool<byte>.Create();
|
Reset(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] _buffer;
|
byte[] _buffer;
|
||||||
private int _position;
|
int _position;
|
||||||
|
|
||||||
public int Length { get; set; }
|
public int Length { get; set; }
|
||||||
|
|
||||||
@@ -64,7 +63,6 @@ namespace MQTTnet.AspNetCore
|
|||||||
|
|
||||||
GrowIfNeeded(propertyWriter.Length);
|
GrowIfNeeded(propertyWriter.Length);
|
||||||
Write(propertyWriter.GetBuffer(), 0, propertyWriter.Length);
|
Write(propertyWriter.GetBuffer(), 0, propertyWriter.Length);
|
||||||
Commit(propertyWriter.Length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(byte[] payload, int start, int length)
|
public void Write(byte[] payload, int start, int length)
|
||||||
@@ -113,7 +111,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
Commit(payload.Length);
|
Commit(payload.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Commit(int count)
|
void Commit(int count)
|
||||||
{
|
{
|
||||||
if (_position == Length)
|
if (_position == Length)
|
||||||
{
|
{
|
||||||
@@ -123,7 +121,7 @@ namespace MQTTnet.AspNetCore
|
|||||||
_position += count;
|
_position += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GrowIfNeeded(int requiredAdditional)
|
void GrowIfNeeded(int requiredAdditional)
|
||||||
{
|
{
|
||||||
var requiredTotal = _position + requiredAdditional;
|
var requiredTotal = _position + requiredAdditional;
|
||||||
if (_buffer.Length >= requiredTotal)
|
if (_buffer.Length >= requiredTotal)
|
||||||
|
|||||||
@@ -1,31 +1,49 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.Client;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||||
{
|
{
|
||||||
bool IsStarted { get; }
|
/// <summary>
|
||||||
bool IsConnected { get; }
|
/// Gets the internally used MQTT client.
|
||||||
int PendingApplicationMessagesCount { get; }
|
/// This property should be used with caution because manipulating the internal client might break the managed client.
|
||||||
IManagedMqttClientOptions Options { get; }
|
/// </summary>
|
||||||
|
IMqttClient InternalClient { get; }
|
||||||
|
|
||||||
|
bool IsStarted { get; }
|
||||||
|
|
||||||
|
bool IsConnected { get; }
|
||||||
|
|
||||||
|
int PendingApplicationMessagesCount { get; }
|
||||||
|
|
||||||
|
IManagedMqttClientOptions Options { get; }
|
||||||
|
|
||||||
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
IMqttClientConnectedHandler ConnectedHandler { get; set; }
|
||||||
|
|
||||||
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
IMqttClientDisconnectedHandler DisconnectedHandler { get; set; }
|
||||||
|
|
||||||
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
||||||
|
|
||||||
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
|
IApplicationMessageSkippedHandler ApplicationMessageSkippedHandler { get; set; }
|
||||||
|
|
||||||
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
|
IConnectingFailedHandler ConnectingFailedHandler { get; set; }
|
||||||
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
|
|
||||||
|
|
||||||
Task StartAsync(IManagedMqttClientOptions options);
|
ISynchronizingSubscriptionsFailedHandler SynchronizingSubscriptionsFailedHandler { get; set; }
|
||||||
Task StopAsync();
|
|
||||||
|
|
||||||
Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
Task StartAsync(IManagedMqttClientOptions options);
|
||||||
|
|
||||||
|
Task StopAsync();
|
||||||
|
|
||||||
|
Task PingAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters);
|
||||||
|
|
||||||
Task UnsubscribeAsync(IEnumerable<string> topics);
|
Task UnsubscribeAsync(IEnumerable<string> topics);
|
||||||
|
|
||||||
Task PublishAsync(ManagedMqttApplicationMessage applicationMessages);
|
Task PublishAsync(ManagedMqttApplicationMessage applicationMessages);
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<DelaySign>false</DelaySign>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +29,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using MQTTnet.Client;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Connecting;
|
using MQTTnet.Client.Connecting;
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
using MQTTnet.Client.Publishing;
|
using MQTTnet.Client.Publishing;
|
||||||
@@ -13,56 +8,74 @@ using MQTTnet.Exceptions;
|
|||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
public class ManagedMqttClient : IManagedMqttClient
|
public class ManagedMqttClient : Disposable, IManagedMqttClient
|
||||||
{
|
{
|
||||||
private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
|
readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
|
||||||
private readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
|
||||||
private readonly HashSet<string> _unsubscriptions = new HashSet<string>();
|
|
||||||
|
|
||||||
private readonly IMqttClient _mqttClient;
|
/// <summary>
|
||||||
private readonly IMqttNetChildLogger _logger;
|
/// The subscriptions are managed in 2 separate buckets:
|
||||||
|
/// <see cref="_subscriptions"/> and <see cref="_unsubscriptions"/> are processed during normal operation
|
||||||
|
/// and are moved to the <see cref="_reconnectSubscriptions"/> when they get processed. They can be accessed by
|
||||||
|
/// any thread and are therefore mutex'ed. <see cref="_reconnectSubscriptions"/> get sent to the broker
|
||||||
|
/// at reconnect and are solely owned by <see cref="MaintainConnectionAsync"/>.
|
||||||
|
/// </summary>
|
||||||
|
readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
||||||
|
readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>();
|
||||||
|
readonly HashSet<string> _unsubscriptions = new HashSet<string>();
|
||||||
|
readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0);
|
||||||
|
|
||||||
private CancellationTokenSource _connectionCancellationToken;
|
readonly IMqttNetScopedLogger _logger;
|
||||||
private CancellationTokenSource _publishingCancellationToken;
|
|
||||||
private Task _maintainConnectionTask;
|
|
||||||
|
|
||||||
private ManagedMqttClientStorageManager _storageManager;
|
readonly AsyncLock _messageQueueLock = new AsyncLock();
|
||||||
|
|
||||||
private bool _disposed;
|
CancellationTokenSource _connectionCancellationToken;
|
||||||
private bool _subscriptionsNotPushed;
|
CancellationTokenSource _publishingCancellationToken;
|
||||||
|
Task _maintainConnectionTask;
|
||||||
|
|
||||||
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
|
ManagedMqttClientStorageManager _storageManager;
|
||||||
|
|
||||||
|
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
InternalClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
||||||
|
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
_logger = logger.CreateChildLogger(nameof(ManagedMqttClient));
|
_logger = logger.CreateScopedLogger(nameof(ManagedMqttClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsConnected => _mqttClient.IsConnected;
|
public bool IsConnected => InternalClient.IsConnected;
|
||||||
|
|
||||||
public bool IsStarted => _connectionCancellationToken != null;
|
public bool IsStarted => _connectionCancellationToken != null;
|
||||||
|
|
||||||
|
public IMqttClient InternalClient { get; }
|
||||||
|
|
||||||
public int PendingApplicationMessagesCount => _messageQueue.Count;
|
public int PendingApplicationMessagesCount => _messageQueue.Count;
|
||||||
|
|
||||||
public IManagedMqttClientOptions Options { get; private set; }
|
public IManagedMqttClientOptions Options { get; private set; }
|
||||||
|
|
||||||
public IMqttClientConnectedHandler ConnectedHandler
|
public IMqttClientConnectedHandler ConnectedHandler
|
||||||
{
|
{
|
||||||
get => _mqttClient.ConnectedHandler;
|
get => InternalClient.ConnectedHandler;
|
||||||
set => _mqttClient.ConnectedHandler = value;
|
set => InternalClient.ConnectedHandler = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMqttClientDisconnectedHandler DisconnectedHandler
|
public IMqttClientDisconnectedHandler DisconnectedHandler
|
||||||
{
|
{
|
||||||
get => _mqttClient.DisconnectedHandler;
|
get => InternalClient.DisconnectedHandler;
|
||||||
set => _mqttClient.DisconnectedHandler = value;
|
set => InternalClient.DisconnectedHandler = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
|
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
|
||||||
{
|
{
|
||||||
get => _mqttClient.ApplicationMessageReceivedHandler;
|
get => InternalClient.ApplicationMessageReceivedHandler;
|
||||||
set => _mqttClient.ApplicationMessageReceivedHandler = value;
|
set => InternalClient.ApplicationMessageReceivedHandler = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
public IApplicationMessageProcessedHandler ApplicationMessageProcessedHandler { get; set; }
|
||||||
@@ -80,18 +93,13 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
if (options.ClientOptions == null) throw new ArgumentException("The client options are not set.", nameof(options));
|
if (options.ClientOptions == null) throw new ArgumentException("The client options are not set.", nameof(options));
|
||||||
|
|
||||||
if (!options.ClientOptions.CleanSession)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("The managed client does not support existing sessions.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
|
if (!_maintainConnectionTask?.IsCompleted ?? false) throw new InvalidOperationException("The managed client is already started.");
|
||||||
|
|
||||||
Options = options;
|
Options = options;
|
||||||
|
|
||||||
if (Options.Storage != null)
|
if (options.Storage != null)
|
||||||
{
|
{
|
||||||
_storageManager = new ManagedMqttClientStorageManager(Options.Storage);
|
_storageManager = new ManagedMqttClientStorageManager(options.Storage);
|
||||||
var messages = await _storageManager.LoadQueuedMessagesAsync().ConfigureAwait(false);
|
var messages = await _storageManager.LoadQueuedMessagesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
foreach (var message in messages)
|
foreach (var message in messages)
|
||||||
@@ -100,10 +108,12 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_connectionCancellationToken = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
var cancellationToken = cancellationTokenSource.Token;
|
||||||
|
_connectionCancellationToken = cancellationTokenSource;
|
||||||
|
|
||||||
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
|
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(cancellationToken), cancellationToken);
|
||||||
_maintainConnectionTask.Forget(_logger);
|
_maintainConnectionTask.RunInBackground(_logger);
|
||||||
|
|
||||||
_logger.Info("Started");
|
_logger.Info("Started");
|
||||||
}
|
}
|
||||||
@@ -124,6 +134,11 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task PingAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return InternalClient.PingAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
@@ -139,6 +154,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||||
|
if (Options == null) throw new InvalidOperationException("call StartAsync before publishing messages");
|
||||||
|
|
||||||
MqttTopicValidator.ThrowIfInvalid(applicationMessage.ApplicationMessage.Topic);
|
MqttTopicValidator.ThrowIfInvalid(applicationMessage.ApplicationMessage.Topic);
|
||||||
|
|
||||||
@@ -147,7 +163,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (_messageQueue)
|
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
if (_messageQueue.Count >= Options.MaxPendingMessages)
|
if (_messageQueue.Count >= Options.MaxPendingMessages)
|
||||||
{
|
{
|
||||||
@@ -167,6 +183,16 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
_messageQueue.Enqueue(applicationMessage);
|
_messageQueue.Enqueue(applicationMessage);
|
||||||
|
|
||||||
|
if (_storageManager != null)
|
||||||
|
{
|
||||||
|
if (removedMessage != null)
|
||||||
|
{
|
||||||
|
await _storageManager.RemoveAsync(removedMessage).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -181,19 +207,9 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_storageManager != null)
|
|
||||||
{
|
|
||||||
if (removedMessage != null)
|
|
||||||
{
|
|
||||||
await _storageManager.RemoveAsync(removedMessage).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
await _storageManager.AddAsync(applicationMessage).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters)
|
public Task SubscribeAsync(IEnumerable<MqttTopicFilter> topicFilters)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
@@ -204,10 +220,12 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
foreach (var topicFilter in topicFilters)
|
foreach (var topicFilter in topicFilters)
|
||||||
{
|
{
|
||||||
_subscriptions[topicFilter.Topic] = topicFilter.QualityOfServiceLevel;
|
_subscriptions[topicFilter.Topic] = topicFilter.QualityOfServiceLevel;
|
||||||
_subscriptionsNotPushed = true;
|
_unsubscriptions.Remove(topicFilter.Topic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_subscriptionsQueuedSignal.Release();
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,47 +239,38 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
foreach (var topic in topics)
|
foreach (var topic in topics)
|
||||||
{
|
{
|
||||||
if (_subscriptions.Remove(topic))
|
_subscriptions.Remove(topic);
|
||||||
{
|
_unsubscriptions.Add(topic);
|
||||||
_unsubscriptions.Add(topic);
|
|
||||||
_subscriptionsNotPushed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_subscriptionsQueuedSignal.Release();
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (disposing)
|
||||||
{
|
{
|
||||||
return;
|
StopPublishing();
|
||||||
|
StopMaintainingConnection();
|
||||||
|
|
||||||
|
if (_maintainConnectionTask != null)
|
||||||
|
{
|
||||||
|
_maintainConnectionTask.GetAwaiter().GetResult();
|
||||||
|
_maintainConnectionTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_messageQueue.Dispose();
|
||||||
|
_messageQueueLock.Dispose();
|
||||||
|
InternalClient.Dispose();
|
||||||
|
_subscriptionsQueuedSignal.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_disposed = true;
|
base.Dispose(disposing);
|
||||||
|
|
||||||
StopPublishing();
|
|
||||||
StopMaintainingConnection();
|
|
||||||
|
|
||||||
if (_maintainConnectionTask != null)
|
|
||||||
{
|
|
||||||
Task.WaitAny(_maintainConnectionTask);
|
|
||||||
_maintainConnectionTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mqttClient.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowIfDisposed()
|
async Task MaintainConnectionAsync(CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException(nameof(ManagedMqttClient));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -275,15 +284,22 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
_logger.Error(exception, "Unhandled exception while maintaining connection.");
|
_logger.Error(exception, "Error exception while maintaining connection.");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (!_disposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mqttClient.DisconnectAsync().ConfigureAwait(false);
|
using (var disconnectTimeout = new CancellationTokenSource(Options.ClientOptions.CommunicationTimeout))
|
||||||
|
{
|
||||||
|
await InternalClient.DisconnectAsync(disconnectTimeout.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.Warning("Timeout while sending DISCONNECT packet.");
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@@ -292,14 +308,22 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
|
|
||||||
_logger.Info("Stopped");
|
_logger.Info("Stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_reconnectSubscriptions.Clear();
|
||||||
|
|
||||||
|
lock (_subscriptions)
|
||||||
|
{
|
||||||
|
_subscriptions.Clear();
|
||||||
|
_unsubscriptions.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
|
async Task TryMaintainConnectionAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var connectionState = await ReconnectIfRequiredAsync().ConfigureAwait(false);
|
var connectionState = await ReconnectIfRequiredAsync(cancellationToken).ConfigureAwait(false);
|
||||||
if (connectionState == ReconnectionResult.NotConnected)
|
if (connectionState == ReconnectionResult.NotConnected)
|
||||||
{
|
{
|
||||||
StopPublishing();
|
StopPublishing();
|
||||||
@@ -307,16 +331,22 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionState == ReconnectionResult.Reconnected || _subscriptionsNotPushed)
|
if (connectionState == ReconnectionResult.Reconnected)
|
||||||
|
{
|
||||||
|
await PublishReconnectSubscriptionsAsync().ConfigureAwait(false);
|
||||||
|
StartPublishing();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionState == ReconnectionResult.Recovered)
|
||||||
{
|
{
|
||||||
await SynchronizeSubscriptionsAsync().ConfigureAwait(false);
|
|
||||||
StartPublishing();
|
StartPublishing();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionState == ReconnectionResult.StillConnected)
|
if (connectionState == ReconnectionResult.StillConnected)
|
||||||
{
|
{
|
||||||
await Task.Delay(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
|
await PublishSubscriptionsAsync(Options.ConnectionCheckInterval, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
@@ -324,19 +354,19 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
catch (MqttCommunicationException exception)
|
catch (MqttCommunicationException exception)
|
||||||
{
|
{
|
||||||
_logger.Warning(exception, "Communication exception while maintaining connection.");
|
_logger.Warning(exception, "Communication error while maintaining connection.");
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
_logger.Error(exception, "Unhandled exception while maintaining connection.");
|
_logger.Error(exception, "Error exception while maintaining connection.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
|
async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested && _mqttClient.IsConnected)
|
while (!cancellationToken.IsCancellationRequested && InternalClient.IsConnected)
|
||||||
{
|
{
|
||||||
// Peek at the message without dequeueing in order to prevent the
|
// Peek at the message without dequeueing in order to prevent the
|
||||||
// possibility of the queue growing beyond the configured cap.
|
// possibility of the queue growing beyond the configured cap.
|
||||||
@@ -346,7 +376,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
// of the messages, the DropOldestQueuedMessage strategy would
|
// of the messages, the DropOldestQueuedMessage strategy would
|
||||||
// be unable to know which message is actually the oldest and would
|
// be unable to know which message is actually the oldest and would
|
||||||
// instead drop the first item in the queue.
|
// instead drop the first item in the queue.
|
||||||
var message = _messageQueue.PeekAndWait();
|
var message = _messageQueue.PeekAndWait(cancellationToken);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -362,7 +392,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
_logger.Error(exception, "Unhandled exception while publishing queued application messages.");
|
_logger.Error(exception, "Error while publishing queued application messages.");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -370,14 +400,14 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
|
async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
|
||||||
{
|
{
|
||||||
Exception transmitException = null;
|
Exception transmitException = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mqttClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
|
await InternalClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
|
||||||
|
|
||||||
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
|
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false)) //lock to avoid conflict with this.PublishAsync
|
||||||
{
|
{
|
||||||
// While publishing this message, this.PublishAsync could have booted this
|
// While publishing this message, this.PublishAsync could have booted this
|
||||||
// message off the queue to make room for another (when using a cap
|
// message off the queue to make room for another (when using a cap
|
||||||
@@ -386,18 +416,18 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
// it from the queue. If not, that means this.PublishAsync has already
|
// it from the queue. If not, that means this.PublishAsync has already
|
||||||
// removed it, in which case we don't want to do anything.
|
// removed it, in which case we don't want to do anything.
|
||||||
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
||||||
}
|
|
||||||
|
|
||||||
if (_storageManager != null)
|
if (_storageManager != null)
|
||||||
{
|
{
|
||||||
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
|
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (MqttCommunicationException exception)
|
catch (MqttCommunicationException exception)
|
||||||
{
|
{
|
||||||
transmitException = exception;
|
transmitException = exception;
|
||||||
|
|
||||||
_logger.Warning(exception, $"Publishing application ({message.Id}) message failed.");
|
_logger.Warning(exception, "Publishing application message ({0}) failed.", message.Id);
|
||||||
|
|
||||||
if (message.ApplicationMessage.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
if (message.ApplicationMessage.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
{
|
{
|
||||||
@@ -408,21 +438,21 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
//contradict the expected behavior of QoS 1 and 2, that's also true
|
//contradict the expected behavior of QoS 1 and 2, that's also true
|
||||||
//for the usage of a message queue cap, so it's still consistent
|
//for the usage of a message queue cap, so it's still consistent
|
||||||
//with prior behavior in that way.
|
//with prior behavior in that way.
|
||||||
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
|
using (await _messageQueueLock.WaitAsync(CancellationToken.None).ConfigureAwait(false)) //lock to avoid conflict with this.PublishAsync
|
||||||
{
|
{
|
||||||
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
|
||||||
}
|
|
||||||
|
|
||||||
if (_storageManager != null)
|
if (_storageManager != null)
|
||||||
{
|
{
|
||||||
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
|
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
transmitException = exception;
|
transmitException = exception;
|
||||||
_logger.Error(exception, $"Unhandled exception while publishing application message ({message.Id}).");
|
_logger.Error(exception, "Error while publishing application message ({0}).", message.Id);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -435,64 +465,99 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SynchronizeSubscriptionsAsync()
|
async Task PublishSubscriptionsAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.Info("Synchronizing subscriptions");
|
var endTime = DateTime.UtcNow + timeout;
|
||||||
|
|
||||||
List<TopicFilter> subscriptions;
|
while (await _subscriptionsQueuedSignal.WaitAsync(GetRemainingTime(endTime), cancellationToken).ConfigureAwait(false))
|
||||||
HashSet<string> unsubscriptions;
|
|
||||||
|
|
||||||
lock (_subscriptions)
|
|
||||||
{
|
{
|
||||||
subscriptions = _subscriptions.Select(i => new TopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
|
List<MqttTopicFilter> subscriptions;
|
||||||
|
HashSet<string> unsubscriptions;
|
||||||
|
|
||||||
unsubscriptions = new HashSet<string>(_unsubscriptions);
|
lock (_subscriptions)
|
||||||
_unsubscriptions.Clear();
|
|
||||||
|
|
||||||
_subscriptionsNotPushed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!subscriptions.Any() && !unsubscriptions.Any())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (unsubscriptions.Any())
|
|
||||||
{
|
{
|
||||||
await _mqttClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false);
|
subscriptions = _subscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList();
|
||||||
|
_subscriptions.Clear();
|
||||||
|
unsubscriptions = new HashSet<string>(_unsubscriptions);
|
||||||
|
_unsubscriptions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subscriptions.Any())
|
if (!subscriptions.Any() && !unsubscriptions.Any())
|
||||||
{
|
{
|
||||||
await _mqttClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
_logger.Warning(exception, "Synchronizing subscriptions failed.");
|
|
||||||
_subscriptionsNotPushed = true;
|
|
||||||
|
|
||||||
var synchronizingSubscriptionsFailedHandler = SynchronizingSubscriptionsFailedHandler;
|
_logger.Verbose("Publishing {0} subscriptions and {1} unsubscriptions)", subscriptions.Count, unsubscriptions.Count);
|
||||||
if (SynchronizingSubscriptionsFailedHandler != null)
|
|
||||||
|
foreach (var unsubscription in unsubscriptions)
|
||||||
{
|
{
|
||||||
await synchronizingSubscriptionsFailedHandler.HandleSynchronizingSubscriptionsFailedAsync(new ManagedProcessFailedEventArgs(exception)).ConfigureAwait(false);
|
_reconnectSubscriptions.Remove(unsubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var subscription in subscriptions)
|
||||||
|
{
|
||||||
|
_reconnectSubscriptions[subscription.Topic] = subscription.QualityOfServiceLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (unsubscriptions.Any())
|
||||||
|
{
|
||||||
|
await InternalClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subscriptions.Any())
|
||||||
|
{
|
||||||
|
await InternalClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ReconnectionResult> ReconnectIfRequiredAsync()
|
async Task PublishReconnectSubscriptionsAsync()
|
||||||
{
|
{
|
||||||
if (_mqttClient.IsConnected)
|
_logger.Info("Publishing subscriptions at reconnect");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_reconnectSubscriptions.Any())
|
||||||
|
{
|
||||||
|
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value });
|
||||||
|
await InternalClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await HandleSubscriptionExceptionAsync(exception).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task HandleSubscriptionExceptionAsync(Exception exception)
|
||||||
|
{
|
||||||
|
_logger.Warning(exception, "Synchronizing subscriptions failed.");
|
||||||
|
|
||||||
|
var synchronizingSubscriptionsFailedHandler = SynchronizingSubscriptionsFailedHandler;
|
||||||
|
if (SynchronizingSubscriptionsFailedHandler != null)
|
||||||
|
{
|
||||||
|
await synchronizingSubscriptionsFailedHandler.HandleSynchronizingSubscriptionsFailedAsync(new ManagedProcessFailedEventArgs(exception)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<ReconnectionResult> ReconnectIfRequiredAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (InternalClient.IsConnected)
|
||||||
{
|
{
|
||||||
return ReconnectionResult.StillConnected;
|
return ReconnectionResult.StillConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mqttClient.ConnectAsync(Options.ClientOptions).ConfigureAwait(false);
|
var result = await InternalClient.ConnectAsync(Options.ClientOptions, cancellationToken).ConfigureAwait(false);
|
||||||
return ReconnectionResult.Reconnected;
|
return result.IsSessionPresent ? ReconnectionResult.Recovered : ReconnectionResult.Reconnected;
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@@ -505,32 +570,51 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return ReconnectionResult.NotConnected;
|
return ReconnectionResult.NotConnected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartPublishing()
|
void StartPublishing()
|
||||||
{
|
{
|
||||||
if (_publishingCancellationToken != null)
|
if (_publishingCancellationToken != null)
|
||||||
{
|
{
|
||||||
StopPublishing();
|
StopPublishing();
|
||||||
}
|
}
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
_publishingCancellationToken = cts;
|
var cancellationToken = cancellationTokenSource.Token;
|
||||||
|
_publishingCancellationToken = cancellationTokenSource;
|
||||||
|
|
||||||
Task.Run(() => PublishQueuedMessagesAsync(cts.Token), cts.Token).Forget(_logger);
|
Task.Run(() => PublishQueuedMessagesAsync(cancellationToken), cancellationToken).RunInBackground(_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopPublishing()
|
void StopPublishing()
|
||||||
{
|
{
|
||||||
_publishingCancellationToken?.Cancel(false);
|
try
|
||||||
_publishingCancellationToken?.Dispose();
|
{
|
||||||
_publishingCancellationToken = null;
|
_publishingCancellationToken?.Cancel(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_publishingCancellationToken?.Dispose();
|
||||||
|
_publishingCancellationToken = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopMaintainingConnection()
|
void StopMaintainingConnection()
|
||||||
{
|
{
|
||||||
_connectionCancellationToken?.Cancel(false);
|
try
|
||||||
_connectionCancellationToken?.Dispose();
|
{
|
||||||
_connectionCancellationToken = null;
|
_connectionCancellationToken?.Cancel(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connectionCancellationToken?.Dispose();
|
||||||
|
_connectionCancellationToken = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TimeSpan GetRemainingTime(DateTime endTime)
|
||||||
|
{
|
||||||
|
var remainingTime = endTime - DateTime.UtcNow;
|
||||||
|
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using System;
|
using MQTTnet.Client.Connecting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Client.Connecting;
|
|
||||||
using MQTTnet.Client.Disconnecting;
|
using MQTTnet.Client.Disconnecting;
|
||||||
using MQTTnet.Client.Publishing;
|
using MQTTnet.Client.Publishing;
|
||||||
using MQTTnet.Client.Receiving;
|
using MQTTnet.Client.Receiving;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
@@ -76,39 +76,42 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
if (handler == null)
|
if (handler == null)
|
||||||
{
|
{
|
||||||
return client.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
if (handler == null)
|
if (handler == null)
|
||||||
{
|
{
|
||||||
return client.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
return receiver.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
return receiver.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient UseApplicationMessageReceivedHandler(this IManagedMqttClient client, IMqttApplicationMessageReceivedHandler handler)
|
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, IMqttApplicationMessageReceivedHandler handler)
|
||||||
|
where TReceiver : IApplicationMessageReceiver
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||||
|
|
||||||
client.ApplicationMessageReceivedHandler = handler;
|
receiver.ApplicationMessageReceivedHandler = handler;
|
||||||
return client;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task SubscribeAsync(this IManagedMqttClient client, params TopicFilter[] topicFilters)
|
public static Task SubscribeAsync(this IManagedMqttClient client, params MqttTopicFilter[] topicFilters)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
|
|
||||||
@@ -120,7 +123,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task SubscribeAsync(this IManagedMqttClient client, string topic)
|
public static Task SubscribeAsync(this IManagedMqttClient client, string topic)
|
||||||
@@ -128,7 +131,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
|
return client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task UnsubscribeAsync(this IManagedMqttClient client, params string[] topicFilters)
|
public static Task UnsubscribeAsync(this IManagedMqttClient client, params string[] topicFilters)
|
||||||
@@ -138,92 +141,92 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
return client.UnsubscribeAsync(topicFilters);
|
return client.UnsubscribeAsync(topicFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task PublishAsync(this IManagedMqttClient client, IEnumerable<MqttApplicationMessage> applicationMessages)
|
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, IEnumerable<MqttApplicationMessage> applicationMessages)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||||
|
|
||||||
foreach (var applicationMessage in applicationMessages)
|
foreach (var applicationMessage in applicationMessages)
|
||||||
{
|
{
|
||||||
await client.PublishAsync(applicationMessage).ConfigureAwait(false);
|
await publisher.PublishAsync(applicationMessage).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, MqttApplicationMessage applicationMessage)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||||
|
|
||||||
return client.PublishAsync(applicationMessage, CancellationToken.None);
|
return publisher.PublishAsync(applicationMessage, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task PublishAsync(this IManagedMqttClient client, params MqttApplicationMessage[] applicationMessages)
|
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, params MqttApplicationMessage[] applicationMessages)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||||
|
|
||||||
foreach (var applicationMessage in applicationMessages)
|
foreach (var applicationMessage in applicationMessages)
|
||||||
{
|
{
|
||||||
await client.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
await publisher.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic));
|
.WithTopic(topic));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload));
|
.WithPayload(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload)
|
.WithPayload(payload)
|
||||||
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||||
|
|
||||||
return client.PublishAsync(builder => builder
|
return publisher.PublishAsync(builder => builder
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload)
|
.WithPayload(payload)
|
||||||
.WithQualityOfServiceLevel(qualityOfServiceLevel)
|
.WithQualityOfServiceLevel(qualityOfServiceLevel)
|
||||||
.WithRetainFlag(retain));
|
.WithRetainFlag(retain));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
|
|
||||||
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
||||||
return client.PublishAsync(message, cancellationToken);
|
return publisher.PublishAsync(message, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<MqttClientPublishResult> PublishAsync(this IManagedMqttClient client, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||||
|
|
||||||
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
var message = builder(new MqttApplicationMessageBuilder()).Build();
|
||||||
return client.PublishAsync(message, CancellationToken.None);
|
return publisher.PublishAsync(message, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
@@ -7,8 +6,8 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
public class ManagedMqttClientOptionsBuilder
|
public class ManagedMqttClientOptionsBuilder
|
||||||
{
|
{
|
||||||
private readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
|
readonly ManagedMqttClientOptions _options = new ManagedMqttClientOptions();
|
||||||
private MqttClientOptionsBuilder _clientOptionsBuilder;
|
MqttClientOptionsBuilder _clientOptionsBuilder;
|
||||||
|
|
||||||
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
|
public ManagedMqttClientOptionsBuilder WithMaxPendingMessages(int value)
|
||||||
{
|
{
|
||||||
@@ -69,7 +68,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
options(_clientOptionsBuilder);
|
options(_clientOptionsBuilder);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagedMqttClientOptions Build()
|
public ManagedMqttClientOptions Build()
|
||||||
{
|
{
|
||||||
if (_clientOptionsBuilder != null)
|
if (_clientOptionsBuilder != null)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Diagnostics;
|
using System;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.ManagedClient
|
namespace MQTTnet.Extensions.ManagedClient
|
||||||
{
|
{
|
||||||
@@ -9,7 +9,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
{
|
{
|
||||||
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
||||||
|
|
||||||
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger.CreateChildLogger());
|
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory, IMqttNetLogger logger)
|
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory, IMqttNetLogger logger)
|
||||||
@@ -17,7 +17,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
|||||||
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
return new ManagedMqttClient(factory.CreateMqttClient(logger), logger.CreateChildLogger());
|
return new ManagedMqttClient(factory.CreateMqttClient(logger), logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
{
|
{
|
||||||
StillConnected,
|
StillConnected,
|
||||||
Reconnected,
|
Reconnected,
|
||||||
|
Recovered,
|
||||||
NotConnected
|
NotConnected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc
|
||||||
|
{
|
||||||
|
public interface IMqttRpcClient : IDisposable
|
||||||
|
{
|
||||||
|
Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel);
|
||||||
|
|
||||||
|
Task<byte[]> ExecuteAsync(string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<DelaySign>false</DelaySign>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +29,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,23 +1,33 @@
|
|||||||
using System;
|
using MQTTnet.Client;
|
||||||
|
using MQTTnet.Exceptions;
|
||||||
|
using MQTTnet.Extensions.Rpc.Options;
|
||||||
|
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client.Subscribing;
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Implementations;
|
||||||
using MQTTnet.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.Rpc
|
namespace MQTTnet.Extensions.Rpc
|
||||||
{
|
{
|
||||||
public class MqttRpcClient : IDisposable
|
public sealed class MqttRpcClient : IMqttRpcClient
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
|
readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
|
||||||
private readonly IMqttClient _mqttClient;
|
readonly IMqttClient _mqttClient;
|
||||||
private readonly RpcAwareApplicationMessageReceivedHandler _applicationMessageReceivedHandler;
|
readonly IMqttRpcClientOptions _options;
|
||||||
|
readonly RpcAwareApplicationMessageReceivedHandler _applicationMessageReceivedHandler;
|
||||||
|
|
||||||
public MqttRpcClient(IMqttClient mqttClient)
|
[Obsolete("Use MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options).")]
|
||||||
|
public MqttRpcClient(IMqttClient mqttClient) : this(mqttClient, new MqttRpcClientOptions())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options)
|
||||||
{
|
{
|
||||||
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
_applicationMessageReceivedHandler = new RpcAwareApplicationMessageReceivedHandler(
|
_applicationMessageReceivedHandler = new RpcAwareApplicationMessageReceivedHandler(
|
||||||
mqttClient.ApplicationMessageReceivedHandler,
|
mqttClient.ApplicationMessageReceivedHandler,
|
||||||
@@ -26,37 +36,55 @@ namespace MQTTnet.Extensions.Rpc
|
|||||||
_mqttClient.ApplicationMessageReceivedHandler = _applicationMessageReceivedHandler;
|
_mqttClient.ApplicationMessageReceivedHandler = _applicationMessageReceivedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
public async Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||||
{
|
{
|
||||||
return ExecuteAsync(timeout, methodName, Encoding.UTF8.GetBytes(payload), qualityOfServiceLevel, CancellationToken.None);
|
using (var timeoutToken = new CancellationTokenSource(timeout))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await ExecuteAsync(methodName, payload, qualityOfServiceLevel, timeoutToken.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException exception)
|
||||||
|
{
|
||||||
|
if (timeoutToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
throw new MqttCommunicationTimedOutException(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken)
|
public async Task<byte[]> ExecuteAsync(string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
return ExecuteAsync(timeout, methodName, Encoding.UTF8.GetBytes(payload), qualityOfServiceLevel, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
|
||||||
{
|
|
||||||
return ExecuteAsync(timeout, methodName, payload, qualityOfServiceLevel, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
if (methodName == null) throw new ArgumentNullException(nameof(methodName));
|
if (methodName == null) throw new ArgumentNullException(nameof(methodName));
|
||||||
|
|
||||||
if (methodName.Contains("/") || methodName.Contains("+") || methodName.Contains("#"))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The method name cannot contain /, + or #.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(_mqttClient.ApplicationMessageReceivedHandler is RpcAwareApplicationMessageReceivedHandler))
|
if (!(_mqttClient.ApplicationMessageReceivedHandler is RpcAwareApplicationMessageReceivedHandler))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The application message received handler was modified.");
|
throw new InvalidOperationException("The application message received handler was modified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{methodName}";
|
var topicNames = _options.TopicGenerationStrategy.CreateRpcTopics(new TopicGenerationContext
|
||||||
var responseTopic = requestTopic + "/response";
|
{
|
||||||
|
MethodName = methodName,
|
||||||
|
QualityOfServiceLevel = qualityOfServiceLevel,
|
||||||
|
MqttClient = _mqttClient,
|
||||||
|
Options = _options
|
||||||
|
});
|
||||||
|
|
||||||
|
var requestTopic = topicNames.RequestTopic;
|
||||||
|
var responseTopic = topicNames.ResponseTopic;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(requestTopic))
|
||||||
|
{
|
||||||
|
throw new MqttProtocolViolationException("RPC request topic is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(responseTopic))
|
||||||
|
{
|
||||||
|
throw new MqttProtocolViolationException("RPC response topic is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
var requestMessage = new MqttApplicationMessageBuilder()
|
var requestMessage = new MqttApplicationMessageBuilder()
|
||||||
.WithTopic(requestTopic)
|
.WithTopic(requestTopic)
|
||||||
@@ -66,62 +94,54 @@ namespace MQTTnet.Extensions.Rpc
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tcs = new TaskCompletionSource<byte[]>();
|
#if NET452
|
||||||
if (!_waitingCalls.TryAdd(responseTopic, tcs))
|
var promise = new TaskCompletionSource<byte[]>();
|
||||||
|
#else
|
||||||
|
var promise = new TaskCompletionSource<byte[]>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!_waitingCalls.TryAdd(responseTopic, promise))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _mqttClient.SubscribeAsync(responseTopic, qualityOfServiceLevel).ConfigureAwait(false);
|
var subscribeOptions = new MqttClientSubscribeOptionsBuilder()
|
||||||
await _mqttClient.PublishAsync(requestMessage).ConfigureAwait(false);
|
.WithTopicFilter(responseTopic, qualityOfServiceLevel)
|
||||||
|
.Build();
|
||||||
using (var timeoutCts = new CancellationTokenSource(timeout))
|
|
||||||
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token))
|
|
||||||
{
|
|
||||||
linkedCts.Token.Register(() =>
|
|
||||||
{
|
|
||||||
if (!tcs.Task.IsCompleted && !tcs.Task.IsFaulted && !tcs.Task.IsCanceled)
|
|
||||||
{
|
|
||||||
tcs.TrySetCanceled();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
await _mqttClient.SubscribeAsync(subscribeOptions, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
await _mqttClient.PublishAsync(requestMessage, cancellationToken).ConfigureAwait(false);
|
||||||
var result = await tcs.Task.ConfigureAwait(false);
|
|
||||||
timeoutCts.Cancel(false);
|
using (cancellationToken.Register(() => { promise.TrySetCanceled(); }))
|
||||||
return result;
|
{
|
||||||
}
|
return await promise.Task.ConfigureAwait(false);
|
||||||
catch (OperationCanceledException exception)
|
|
||||||
{
|
|
||||||
if (timeoutCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationTimedOutException(exception);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_waitingCalls.TryRemove(responseTopic, out _);
|
_waitingCalls.TryRemove(responseTopic, out _);
|
||||||
|
|
||||||
await _mqttClient.UnsubscribeAsync(responseTopic).ConfigureAwait(false);
|
await _mqttClient.UnsubscribeAsync(responseTopic).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!_waitingCalls.TryRemove(eventArgs.ApplicationMessage.Topic, out var tcs))
|
if (!_waitingCalls.TryRemove(eventArgs.ApplicationMessage.Topic, out var promise))
|
||||||
{
|
{
|
||||||
return Task.FromResult(0);
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcs.TrySetResult(eventArgs.ApplicationMessage.Payload);
|
#if NET452
|
||||||
|
Task.Run(() => promise.TrySetResult(eventArgs.ApplicationMessage.Payload));
|
||||||
|
#else
|
||||||
|
promise.TrySetResult(eventArgs.ApplicationMessage.Payload);
|
||||||
|
#endif
|
||||||
|
|
||||||
return Task.FromResult(0);
|
// Set this message to handled to that other code can avoid execution etc.
|
||||||
|
eventArgs.IsHandled = true;
|
||||||
|
|
||||||
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -136,4 +156,4 @@ namespace MQTTnet.Extensions.Rpc
|
|||||||
_waitingCalls.Clear();
|
_waitingCalls.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc
|
||||||
|
{
|
||||||
|
public static class MqttRpcClientExtensions
|
||||||
|
{
|
||||||
|
public static Task<byte[]> ExecuteAsync(this IMqttRpcClient client, TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||||
|
{
|
||||||
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
|
|
||||||
|
var buffer = Encoding.UTF8.GetBytes(payload ?? string.Empty);
|
||||||
|
|
||||||
|
return client.ExecuteAsync(timeout, methodName, buffer, qualityOfServiceLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc.Options
|
||||||
|
{
|
||||||
|
public interface IMqttRpcClientOptions
|
||||||
|
{
|
||||||
|
IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc.Options
|
||||||
|
{
|
||||||
|
public sealed class MqttRpcClientOptions : IMqttRpcClientOptions
|
||||||
|
{
|
||||||
|
public IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; } = new DefaultMqttRpcClientTopicGenerationStrategy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc.Options
|
||||||
|
{
|
||||||
|
public sealed class MqttRpcClientOptionsBuilder
|
||||||
|
{
|
||||||
|
IMqttRpcClientTopicGenerationStrategy _topicGenerationStrategy = new DefaultMqttRpcClientTopicGenerationStrategy();
|
||||||
|
|
||||||
|
public MqttRpcClientOptionsBuilder WithTopicGenerationStrategy(IMqttRpcClientTopicGenerationStrategy value)
|
||||||
|
{
|
||||||
|
_topicGenerationStrategy = value ?? throw new ArgumentNullException(nameof(value));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttRpcClientOptions Build()
|
||||||
|
{
|
||||||
|
return new MqttRpcClientOptions
|
||||||
|
{
|
||||||
|
TopicGenerationStrategy = _topicGenerationStrategy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace MQTTnet.Extensions.Rpc.Options
|
||||||
|
{
|
||||||
|
public sealed class MqttRpcTopicPair
|
||||||
|
{
|
||||||
|
public string RequestTopic { get; set; }
|
||||||
|
|
||||||
|
public string ResponseTopic { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
|
||||||
|
{
|
||||||
|
public sealed class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
|
||||||
|
{
|
||||||
|
public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context)
|
||||||
|
{
|
||||||
|
if (context.MethodName.Contains("/") || context.MethodName.Contains("+") || context.MethodName.Contains("#"))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The method name cannot contain /, + or #.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{context.MethodName}";
|
||||||
|
var responseTopic = requestTopic + "/response";
|
||||||
|
|
||||||
|
return new MqttRpcTopicPair
|
||||||
|
{
|
||||||
|
RequestTopic = requestTopic,
|
||||||
|
ResponseTopic = responseTopic
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
|
||||||
|
{
|
||||||
|
public interface IMqttRpcClientTopicGenerationStrategy
|
||||||
|
{
|
||||||
|
MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using MQTTnet.Client;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
|
||||||
|
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
|
||||||
|
{
|
||||||
|
public sealed class TopicGenerationContext
|
||||||
|
{
|
||||||
|
public string MethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the quality of service level.
|
||||||
|
/// The Quality of Service (QoS) level is an agreement between the sender of a message and the receiver of a message that defines the guarantee of delivery for a specific message.
|
||||||
|
/// There are 3 QoS levels in MQTT:
|
||||||
|
/// - At most once (0): Message gets delivered no time, once or multiple times.
|
||||||
|
/// - At least once (1): Message gets delivered at least once (one time or more often).
|
||||||
|
/// - Exactly once (2): Message gets delivered exactly once (It's ensured that the message only comes once).
|
||||||
|
/// </summary>
|
||||||
|
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
|
||||||
|
|
||||||
|
public IMqttClient MqttClient { get; set; }
|
||||||
|
|
||||||
|
public IMqttRpcClientOptions Options { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,9 @@ using MQTTnet.Client.Receiving;
|
|||||||
|
|
||||||
namespace MQTTnet.Extensions.Rpc
|
namespace MQTTnet.Extensions.Rpc
|
||||||
{
|
{
|
||||||
public class RpcAwareApplicationMessageReceivedHandler : IMqttApplicationMessageReceivedHandler
|
public sealed class RpcAwareApplicationMessageReceivedHandler : IMqttApplicationMessageReceivedHandler
|
||||||
{
|
{
|
||||||
private readonly Func<MqttApplicationMessageReceivedEventArgs, Task> _handleReceivedApplicationMessageAsync;
|
readonly Func<MqttApplicationMessageReceivedEventArgs, Task> _handleReceivedApplicationMessageAsync;
|
||||||
|
|
||||||
public RpcAwareApplicationMessageReceivedHandler(
|
public RpcAwareApplicationMessageReceivedHandler(
|
||||||
IMqttApplicationMessageReceivedHandler originalHandler,
|
IMqttApplicationMessageReceivedHandler originalHandler,
|
||||||
@@ -20,12 +20,13 @@ namespace MQTTnet.Extensions.Rpc
|
|||||||
|
|
||||||
public async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
public async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
|
// First try to check if there is a pending RPC call!
|
||||||
|
await _handleReceivedApplicationMessageAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
if (OriginalHandler != null)
|
if (OriginalHandler != null)
|
||||||
{
|
{
|
||||||
await OriginalHandler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
|
await OriginalHandler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _handleReceivedApplicationMessageAsync(eventArgs).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks>
|
||||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' AND '$(SolutionName)' != 'MQTTnet.noUWP' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
|
||||||
<Product />
|
<Product />
|
||||||
<Company />
|
<Company />
|
||||||
<Authors />
|
<Authors />
|
||||||
<PackageId />
|
<PackageId />
|
||||||
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<DelaySign>false</DelaySign>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'">
|
||||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier>
|
||||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||||
@@ -23,6 +29,10 @@
|
|||||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
{
|
{
|
||||||
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
|
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
|
||||||
|
|
||||||
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory());
|
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory(mqttFactory.DefaultLogger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ using WebSocket4Net;
|
|||||||
|
|
||||||
namespace MQTTnet.Extensions.WebSocket4Net
|
namespace MQTTnet.Extensions.WebSocket4Net
|
||||||
{
|
{
|
||||||
public class WebSocket4NetMqttChannel : IMqttChannel
|
public sealed class WebSocket4NetMqttChannel : IMqttChannel
|
||||||
{
|
{
|
||||||
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
|
readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
|
||||||
|
|
||||||
private readonly IMqttClientOptions _clientOptions;
|
readonly IMqttClientOptions _clientOptions;
|
||||||
private readonly MqttClientWebSocketOptions _webSocketOptions;
|
readonly MqttClientWebSocketOptions _webSocketOptions;
|
||||||
|
|
||||||
private WebSocket _webSocket;
|
WebSocket _webSocket;
|
||||||
|
|
||||||
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions, MqttClientWebSocketOptions webSocketOptions)
|
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions, MqttClientWebSocketOptions webSocketOptions)
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,12 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
{
|
{
|
||||||
foreach (var certificate in _webSocketOptions.TlsOptions.Certificates)
|
foreach (var certificate in _webSocketOptions.TlsOptions.Certificates)
|
||||||
{
|
{
|
||||||
|
#if WINDOWS_UWP
|
||||||
certificates.Add(new X509Certificate(certificate));
|
certificates.Add(new X509Certificate(certificate));
|
||||||
|
#else
|
||||||
|
certificates.Add(certificate);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,12 +166,12 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
_webSocket = null;
|
_webSocket = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnError(object sender, ErrorEventArgs e)
|
static void OnError(object sender, ErrorEventArgs e)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.Write(e.Exception.ToString());
|
System.Diagnostics.Debug.Write(e.Exception.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDataReceived(object sender, DataReceivedEventArgs e)
|
void OnDataReceived(object sender, DataReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
foreach (var @byte in e.Data)
|
foreach (var @byte in e.Data)
|
||||||
{
|
{
|
||||||
@@ -174,7 +179,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ConnectInternalAsync(CancellationToken cancellationToken)
|
async Task ConnectInternalAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_webSocket.Error += OnError;
|
_webSocket.Error += OnError;
|
||||||
_webSocket.DataReceived += OnDataReceived;
|
_webSocket.DataReceived += OnDataReceived;
|
||||||
@@ -196,7 +201,9 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
|||||||
_webSocket.Opened += SuccessHandler;
|
_webSocket.Opened += SuccessHandler;
|
||||||
_webSocket.Error += ErrorHandler;
|
_webSocket.Error += ErrorHandler;
|
||||||
|
|
||||||
|
#pragma warning disable AsyncFixer02 // Long-running or blocking operations inside an async method
|
||||||
_webSocket.Open();
|
_webSocket.Open();
|
||||||
|
#pragma warning restore AsyncFixer02 // Long-running or blocking operations inside an async method
|
||||||
|
|
||||||
var exception = await MqttTaskTimeout.WaitAsync(c =>
|
var exception = await MqttTaskTimeout.WaitAsync(c =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,35 +1,49 @@
|
|||||||
using System;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Adapter;
|
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MQTTnet.Extensions.WebSocket4Net
|
namespace MQTTnet.Extensions.WebSocket4Net
|
||||||
{
|
{
|
||||||
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
|
public sealed class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
|
||||||
{
|
{
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger)
|
readonly IMqttNetLogger _logger;
|
||||||
|
|
||||||
|
public WebSocket4NetMqttClientAdapterFactory(IMqttNetLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
switch (options.ChannelOptions)
|
switch (options.ChannelOptions)
|
||||||
{
|
{
|
||||||
case MqttClientTcpOptions _:
|
case MqttClientTcpOptions _:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(
|
||||||
|
new MqttTcpChannel(options),
|
||||||
|
new MqttPacketFormatterAdapter(options.ProtocolVersion),
|
||||||
|
options.PacketInspector,
|
||||||
|
_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
case MqttClientWebSocketOptions webSocketOptions:
|
case MqttClientWebSocketOptions webSocketOptions:
|
||||||
{
|
{
|
||||||
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options, webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger);
|
return new MqttChannelAdapter(
|
||||||
|
new WebSocket4NetMqttChannel(options, webSocketOptions),
|
||||||
|
new MqttPacketFormatterAdapter(options.ProtocolVersion),
|
||||||
|
options.PacketInspector,
|
||||||
|
_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
using MQTTnet.Client;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Authentication;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Adapter;
|
|
||||||
using MQTTnet.Channel;
|
|
||||||
using MQTTnet.Diagnostics;
|
|
||||||
using MQTTnet.Serializer;
|
|
||||||
using WebSocket4Net;
|
|
||||||
|
|
||||||
namespace MQTTnet.TestApp.NetCore
|
|
||||||
{
|
|
||||||
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory
|
|
||||||
{
|
|
||||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
|
||||||
|
|
||||||
if (!(options.ChannelOptions is MqttClientWebSocketOptions))
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Only WebSocket connections are supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options), new MqttPacketSerializer(), logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WebSocket4NetMqttChannel : IMqttChannel
|
|
||||||
{
|
|
||||||
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>();
|
|
||||||
|
|
||||||
private readonly IMqttClientOptions _clientOptions;
|
|
||||||
private WebSocket4Net.WebSocket _webSocket;
|
|
||||||
|
|
||||||
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions)
|
|
||||||
{
|
|
||||||
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Endpoint { get; } = "";
|
|
||||||
|
|
||||||
public Task ConnectAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var channelOptions = (MqttClientWebSocketOptions)_clientOptions.ChannelOptions;
|
|
||||||
|
|
||||||
var uri = "ws://" + channelOptions.Uri;
|
|
||||||
var sslProtocols = SslProtocols.None;
|
|
||||||
|
|
||||||
if (channelOptions.TlsOptions.UseTls)
|
|
||||||
{
|
|
||||||
uri = "wss://" + channelOptions.Uri;
|
|
||||||
sslProtocols = SslProtocols.Tls12;
|
|
||||||
}
|
|
||||||
|
|
||||||
var subProtocol = channelOptions.SubProtocols.FirstOrDefault() ?? string.Empty;
|
|
||||||
|
|
||||||
_webSocket = new WebSocket4Net.WebSocket(uri, subProtocol, sslProtocols: sslProtocols);
|
|
||||||
_webSocket.DataReceived += OnDataReceived;
|
|
||||||
_webSocket.Open();
|
|
||||||
SpinWait.SpinUntil(() => _webSocket.State == WebSocketState.Open, _clientOptions.CommunicationTimeout);
|
|
||||||
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
if (_webSocket != null)
|
|
||||||
{
|
|
||||||
_webSocket.DataReceived -= OnDataReceived;
|
|
||||||
_webSocket.Close();
|
|
||||||
SpinWait.SpinUntil(() => _webSocket.State == WebSocketState.Closed, _clientOptions.CommunicationTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSocket = null;
|
|
||||||
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var readBytes = 0;
|
|
||||||
while (count > 0 && !cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
byte @byte;
|
|
||||||
if (readBytes == 0)
|
|
||||||
{
|
|
||||||
// Block until at lease one byte was received.
|
|
||||||
@byte = _receiveBuffer.Take(cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!_receiveBuffer.TryTake(out @byte))
|
|
||||||
{
|
|
||||||
return Task.FromResult(readBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[offset] = @byte;
|
|
||||||
offset++;
|
|
||||||
count--;
|
|
||||||
readBytes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult(readBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_webSocket.Send(buffer, offset, count);
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_webSocket != null)
|
|
||||||
{
|
|
||||||
_webSocket.DataReceived -= OnDataReceived;
|
|
||||||
_webSocket.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDataReceived(object sender, WebSocket4Net.DataReceivedEventArgs e)
|
|
||||||
{
|
|
||||||
foreach (var @byte in e.Data)
|
|
||||||
{
|
|
||||||
_receiveBuffer.Add(@byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server.Configuration
|
||||||
|
{
|
||||||
|
public class CertificateSettingsModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Path to certificate.
|
||||||
|
/// </summary>
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Password of certificate.
|
||||||
|
/// </summary>
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read certificate file.
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ReadCertificate()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Path) || string.IsNullOrWhiteSpace(Path))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("No path set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(Path))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException($"Could not find Certificate in path: {Path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.ReadAllBytes(Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,9 +9,9 @@ namespace MQTTnet.Server.Configuration
|
|||||||
public class TcpEndPointModel
|
public class TcpEndPointModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Path to Certificate
|
/// Certificate settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string CertificatePath { get; set; }
|
public CertificateSettingsModel Certificate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enabled / Disable
|
/// Enabled / Disable
|
||||||
@@ -33,25 +33,6 @@ namespace MQTTnet.Server.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Port { get; set; } = 1883;
|
public int Port { get; set; } = 1883;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Read Certificate file
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public byte[] ReadCertificate()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(CertificatePath) || string.IsNullOrWhiteSpace(CertificatePath))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException("No path set");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(CertificatePath))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"Could not find Certificate in path: {CertificatePath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return File.ReadAllBytes(CertificatePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read IPv4
|
/// Read IPv4
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace MQTTnet.Server.Controllers
|
|||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class ClientsController : ControllerBase
|
public class ClientsController : Controller
|
||||||
{
|
{
|
||||||
private readonly MqttServerService _mqttServerService;
|
private readonly MqttServerService _mqttServerService;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
using MQTTnet.Server.Mqtt;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
public class MessagesController : Controller
|
||||||
|
{
|
||||||
|
private readonly MqttServerService _mqttServerService;
|
||||||
|
|
||||||
|
public MessagesController(MqttServerService mqttServerService)
|
||||||
|
{
|
||||||
|
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("api/v1/messages")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> PostMessage(MqttApplicationMessage message)
|
||||||
|
{
|
||||||
|
await _mqttServerService.PublishAsync(message);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("api/v1/messages/{*topic}")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> PostMessage(string topic, int qosLevel = 0)
|
||||||
|
{
|
||||||
|
byte[] payload;
|
||||||
|
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
await HttpContext.Request.Body.CopyToAsync(memoryStream);
|
||||||
|
payload = memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var message = new MqttApplicationMessageBuilder()
|
||||||
|
.WithTopic(topic)
|
||||||
|
.WithPayload(payload)
|
||||||
|
.WithQualityOfServiceLevel((MqttQualityOfServiceLevel)qosLevel)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return await PostMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ namespace MQTTnet.Server.Controllers
|
|||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class RetainedApplicationMessagesController : ControllerBase
|
public class RetainedApplicationMessagesController : Controller
|
||||||
{
|
{
|
||||||
private readonly MqttServerService _mqttServerService;
|
private readonly MqttServerService _mqttServerService;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
public class ServerController : Controller
|
||||||
|
{
|
||||||
|
[Route("api/v1/server/version")]
|
||||||
|
[HttpGet]
|
||||||
|
public ActionResult<string> GetVersion()
|
||||||
|
{
|
||||||
|
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||||
|
return fileVersion.ProductVersion.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ namespace MQTTnet.Server.Controllers
|
|||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class SessionsController : ControllerBase
|
public class SessionsController : Controller
|
||||||
{
|
{
|
||||||
private readonly MqttServerService _mqttServerService;
|
private readonly MqttServerService _mqttServerService;
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
using System;
|
//using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Diagnostics;
|
//using System;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Logging
|
//namespace MQTTnet.Server.Logging
|
||||||
{
|
//{
|
||||||
public class MqttNetChildLoggerWrapper : IMqttNetChildLogger
|
// public class MqttNetChildLoggerWrapper : IMqttNetChildLogger
|
||||||
{
|
// {
|
||||||
private readonly MqttNetLoggerWrapper _logger;
|
// private readonly MqttNetLoggerWrapper _logger;
|
||||||
private readonly string _source;
|
// private readonly string _source;
|
||||||
|
|
||||||
public MqttNetChildLoggerWrapper(string source, MqttNetLoggerWrapper logger)
|
// public MqttNetChildLoggerWrapper(string source, MqttNetLoggerWrapper logger)
|
||||||
{
|
// {
|
||||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
// _logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_source = source;
|
// _source = source;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public IMqttNetChildLogger CreateChildLogger(string source = null)
|
// public IMqttNetLogger CreateChildLogger(string source = null)
|
||||||
{
|
// {
|
||||||
return _logger.CreateChildLogger(source);
|
// return _logger.CreateChildLogger(source);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void Verbose(string message, params object[] parameters)
|
// public void Verbose(string message, params object[] parameters)
|
||||||
{
|
// {
|
||||||
_logger.Publish(MqttNetLogLevel.Verbose, _source, message, parameters, null);
|
// _logger.Publish(MqttNetLogLevel.Verbose, _source, message, parameters, null);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void Info(string message, params object[] parameters)
|
// public void Info(string message, params object[] parameters)
|
||||||
{
|
// {
|
||||||
_logger.Publish(MqttNetLogLevel.Info, _source, message, parameters, null);
|
// _logger.Publish(MqttNetLogLevel.Info, _source, message, parameters, null);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void Warning(Exception exception, string message, params object[] parameters)
|
// public void Warning(Exception exception, string message, params object[] parameters)
|
||||||
{
|
// {
|
||||||
_logger.Publish(MqttNetLogLevel.Warning, _source, message, parameters, exception);
|
// _logger.Publish(MqttNetLogLevel.Warning, _source, message, parameters, exception);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void Error(Exception exception, string message, params object[] parameters)
|
// public void Error(Exception exception, string message, params object[] parameters)
|
||||||
{
|
// {
|
||||||
_logger.Publish(MqttNetLogLevel.Error, _source, message, parameters, exception);
|
// _logger.Publish(MqttNetLogLevel.Error, _source, message, parameters, exception);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using System;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Logging
|
namespace MQTTnet.Server.Logging
|
||||||
{
|
{
|
||||||
public class MqttNetLoggerWrapper : IMqttNetLogger
|
public sealed class MqttNetLoggerWrapper : IMqttNetLogger
|
||||||
{
|
{
|
||||||
private readonly ILogger<MqttServer> _logger;
|
readonly ILogger<MqttServer> _logger;
|
||||||
|
|
||||||
public MqttNetLoggerWrapper(ILogger<MqttServer> logger)
|
public MqttNetLoggerWrapper(ILogger<MqttServer> logger)
|
||||||
{
|
{
|
||||||
@@ -16,32 +16,46 @@ namespace MQTTnet.Server.Logging
|
|||||||
|
|
||||||
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
public event EventHandler<MqttNetLogMessagePublishedEventArgs> LogMessagePublished;
|
||||||
|
|
||||||
public IMqttNetChildLogger CreateChildLogger(string source = null)
|
public IMqttNetScopedLogger CreateScopedLogger(string source)
|
||||||
{
|
{
|
||||||
return new MqttNetChildLoggerWrapper(source, this);
|
return new MqttNetScopedLogger(this, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception)
|
public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception)
|
||||||
{
|
{
|
||||||
var convertedLogLevel = ConvertLogLevel(logLevel);
|
var convertedLogLevel = ConvertLogLevel(level);
|
||||||
_logger.Log(convertedLogLevel, exception, message, parameters);
|
_logger.Log(convertedLogLevel, exception, message, parameters);
|
||||||
|
|
||||||
var logMessagePublishedEvent = LogMessagePublished;
|
var logMessagePublishedEvent = LogMessagePublished;
|
||||||
if (logMessagePublishedEvent != null)
|
if (logMessagePublishedEvent != null)
|
||||||
{
|
{
|
||||||
var logMessage = new MqttNetLogMessage(null, DateTime.UtcNow, Thread.CurrentThread.ManagedThreadId, source, logLevel, message, exception);
|
var logMessage = new MqttNetLogMessage
|
||||||
|
{
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
ThreadId = Thread.CurrentThread.ManagedThreadId,
|
||||||
|
Source = source,
|
||||||
|
Level = level,
|
||||||
|
Message = message,
|
||||||
|
Exception = exception
|
||||||
|
};
|
||||||
|
|
||||||
logMessagePublishedEvent.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
|
logMessagePublishedEvent.Invoke(this, new MqttNetLogMessagePublishedEventArgs(logMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LogLevel ConvertLogLevel(MqttNetLogLevel logLevel)
|
public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception)
|
||||||
|
{
|
||||||
|
Publish(logLevel, null, message, parameters, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LogLevel ConvertLogLevel(MqttNetLogLevel logLevel)
|
||||||
{
|
{
|
||||||
switch (logLevel)
|
switch (logLevel)
|
||||||
{
|
{
|
||||||
case MqttNetLogLevel.Error: return LogLevel.Error;
|
case MqttNetLogLevel.Error: return LogLevel.Error;
|
||||||
case MqttNetLogLevel.Warning: return LogLevel.Warning;
|
case MqttNetLogLevel.Warning: return LogLevel.Warning;
|
||||||
case MqttNetLogLevel.Info: return LogLevel.Information;
|
case MqttNetLogLevel.Info: return LogLevel.Information;
|
||||||
case MqttNetLogLevel.Verbose: return LogLevel.Debug;
|
case MqttNetLogLevel.Verbose: return LogLevel.Trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LogLevel.Debug;
|
return LogLevel.Debug;
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFrameworks>net5.0</TargetFrameworks>
|
||||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||||
<AssemblyName>MQTTnet.Server</AssemblyName>
|
<AssemblyName>MQTTnet.Server</AssemblyName>
|
||||||
<RootNamespace>MQTTnet.Server</RootNamespace>
|
<RootNamespace>MQTTnet.Server</RootNamespace>
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
<Company />
|
<Company />
|
||||||
<Product>MQTTnet</Product>
|
<Product>MQTTnet</Product>
|
||||||
<Description />
|
<Description>Standalone MQTT server with Python scripting backend.</Description>
|
||||||
<Authors />
|
<Authors>The authors of MQTTnet.Server.</Authors>
|
||||||
<PackageId />
|
<PackageId />
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<DelaySign>false</DelaySign>
|
<DelaySign>false</DelaySign>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Version>1.0.0</Version>
|
<Version>3.0.11</Version>
|
||||||
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
|
<TypeScriptToolsVersion>3.3</TypeScriptToolsVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject></StartupObject>
|
<StartupObject>MQTTnet.Server.Program</StartupObject>
|
||||||
<UserSecretsId>c564f0de-28b4-45bf-b726-4d665d705653</UserSecretsId>
|
<UserSecretsId>c564f0de-28b4-45bf-b726-4d665d705653</UserSecretsId>
|
||||||
|
<Copyright>(c) Christian Kratky 2016-2020</Copyright>
|
||||||
|
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@@ -29,13 +32,6 @@
|
|||||||
<NoWarn>1701;1702</NoWarn>
|
<NoWarn>1701;1702</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="wwwroot\**" />
|
|
||||||
<Content Remove="wwwroot\**" />
|
|
||||||
<EmbeddedResource Remove="wwwroot\**" />
|
|
||||||
<None Remove="wwwroot\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Update="appsettings.json">
|
<Content Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
@@ -43,14 +39,19 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IronPython" Version="2.7.9" />
|
<PackageReference Include="IronPython" Version="2.7.11" />
|
||||||
<PackageReference Include="IronPython.StdLib" Version="2.7.9" />
|
<PackageReference Include="IronPython.StdLib" Version="2.7.11" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.6.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
</ItemGroup>
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0-rc2" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.0.0-rc2" />
|
<ItemGroup Condition="'$(TargetFramework)' != 'net5.0'">
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -74,11 +75,19 @@
|
|||||||
<None Update="Web\authorization_handler.py">
|
<None Update="Web\authorization_handler.py">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Web\wwwroot\Hello.txt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Web\wwwroot\mqtt_Test.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Web\wwwroot\pahoJS_Test.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\PublishProfiles\" />
|
<Folder Include="Properties\PublishProfiles\" />
|
||||||
<Folder Include="Web\wwwroot\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -22,14 +22,18 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// This might be not set when a message was published by the server instead of a client.
|
||||||
|
context.SessionItems.TryGetValue(MqttServerConnectionValidator.WrappedSessionItemsKey, out var sessionItems);
|
||||||
|
|
||||||
var pythonContext = new PythonDictionary
|
var pythonContext = new PythonDictionary
|
||||||
{
|
{
|
||||||
|
{ "client_id", context.ClientId },
|
||||||
|
{ "session_items", sessionItems },
|
||||||
|
{ "retain", context.ApplicationMessage.Retain },
|
||||||
{ "accept_publish", context.AcceptPublish },
|
{ "accept_publish", context.AcceptPublish },
|
||||||
{ "close_connection", context.CloseConnection },
|
{ "close_connection", context.CloseConnection },
|
||||||
{ "client_id", context.ClientId },
|
|
||||||
{ "topic", context.ApplicationMessage.Topic },
|
{ "topic", context.ApplicationMessage.Topic },
|
||||||
{ "qos", (int)context.ApplicationMessage.QualityOfServiceLevel },
|
{ "qos", (int)context.ApplicationMessage.QualityOfServiceLevel }
|
||||||
{ "retain", context.ApplicationMessage.Retain }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_application_message", pythonContext);
|
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_application_message", pythonContext);
|
||||||
@@ -47,4 +51,4 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,8 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
{
|
{
|
||||||
public class MqttServerConnectionValidator : IMqttServerConnectionValidator
|
public class MqttServerConnectionValidator : IMqttServerConnectionValidator
|
||||||
{
|
{
|
||||||
|
public const string WrappedSessionItemsKey = "WRAPPED_ITEMS";
|
||||||
|
|
||||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
@@ -22,6 +24,8 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var sessionItems = new PythonDictionary();
|
||||||
|
|
||||||
var pythonContext = new PythonDictionary
|
var pythonContext = new PythonDictionary
|
||||||
{
|
{
|
||||||
{ "endpoint", context.Endpoint },
|
{ "endpoint", context.Endpoint },
|
||||||
@@ -33,6 +37,7 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
{ "clean_session", context.CleanSession},
|
{ "clean_session", context.CleanSession},
|
||||||
{ "authentication_method", context.AuthenticationMethod},
|
{ "authentication_method", context.AuthenticationMethod},
|
||||||
{ "authentication_data", new Bytes(context.AuthenticationData ?? new byte[0]) },
|
{ "authentication_data", new Bytes(context.AuthenticationData ?? new byte[0]) },
|
||||||
|
{ "session_items", sessionItems },
|
||||||
|
|
||||||
{ "result", PythonConvert.Pythonfy(context.ReasonCode) }
|
{ "result", PythonConvert.Pythonfy(context.ReasonCode) }
|
||||||
};
|
};
|
||||||
@@ -40,6 +45,8 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
_pythonScriptHostService.InvokeOptionalFunction("on_validate_client_connection", pythonContext);
|
_pythonScriptHostService.InvokeOptionalFunction("on_validate_client_connection", pythonContext);
|
||||||
|
|
||||||
context.ReasonCode = PythonConvert.ParseEnum<MqttConnectReasonCode>((string)pythonContext["result"]);
|
context.ReasonCode = PythonConvert.ParseEnum<MqttConnectReasonCode>((string)pythonContext["result"]);
|
||||||
|
|
||||||
|
context.SessionItems[WrappedSessionItemsKey] = sessionItems;
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
using System;
|
using IronPython.Runtime;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Security.Authentication;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using IronPython.Runtime;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
@@ -16,25 +9,33 @@ using MQTTnet.Protocol;
|
|||||||
using MQTTnet.Server.Configuration;
|
using MQTTnet.Server.Configuration;
|
||||||
using MQTTnet.Server.Scripting;
|
using MQTTnet.Server.Scripting;
|
||||||
using MQTTnet.Server.Status;
|
using MQTTnet.Server.Status;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Mqtt
|
namespace MQTTnet.Server.Mqtt
|
||||||
{
|
{
|
||||||
public class MqttServerService
|
public class MqttServerService
|
||||||
{
|
{
|
||||||
private readonly ILogger<MqttServerService> _logger;
|
readonly ILogger<MqttServerService> _logger;
|
||||||
|
|
||||||
private readonly MqttSettingsModel _settings;
|
readonly MqttSettingsModel _settings;
|
||||||
private readonly MqttApplicationMessageInterceptor _mqttApplicationMessageInterceptor;
|
readonly MqttApplicationMessageInterceptor _mqttApplicationMessageInterceptor;
|
||||||
private readonly MqttServerStorage _mqttServerStorage;
|
readonly MqttServerStorage _mqttServerStorage;
|
||||||
private readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
|
readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
|
||||||
private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
|
readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
|
||||||
private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
|
readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
|
||||||
private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
|
readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
|
||||||
private readonly MqttServerConnectionValidator _mqttConnectionValidator;
|
readonly MqttServerConnectionValidator _mqttConnectionValidator;
|
||||||
private readonly IMqttServer _mqttServer;
|
readonly IMqttServer _mqttServer;
|
||||||
private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
|
readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
|
||||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
readonly MqttUnsubscriptionInterceptor _mqttUnsubscriptionInterceptor;
|
||||||
private readonly MqttWebSocketServerAdapter _webSocketServerAdapter;
|
readonly PythonScriptHostService _pythonScriptHostService;
|
||||||
|
readonly MqttWebSocketServerAdapter _webSocketServerAdapter;
|
||||||
|
|
||||||
public MqttServerService(
|
public MqttServerService(
|
||||||
MqttSettingsModel mqttSettings,
|
MqttSettingsModel mqttSettings,
|
||||||
@@ -45,9 +46,10 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
|
MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
|
||||||
MqttServerConnectionValidator mqttConnectionValidator,
|
MqttServerConnectionValidator mqttConnectionValidator,
|
||||||
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
|
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
|
||||||
|
MqttUnsubscriptionInterceptor mqttUnsubscriptionInterceptor,
|
||||||
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
|
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
|
||||||
MqttServerStorage mqttServerStorage,
|
MqttServerStorage mqttServerStorage,
|
||||||
PythonScriptHostService pythonScriptHostService,
|
PythonScriptHostService pythonScriptHostService,
|
||||||
ILogger<MqttServerService> logger)
|
ILogger<MqttServerService> logger)
|
||||||
{
|
{
|
||||||
_settings = mqttSettings ?? throw new ArgumentNullException(nameof(mqttSettings));
|
_settings = mqttSettings ?? throw new ArgumentNullException(nameof(mqttSettings));
|
||||||
@@ -57,16 +59,17 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
_mqttClientUnsubscribedTopicHandler = mqttClientUnsubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientUnsubscribedTopicHandler));
|
_mqttClientUnsubscribedTopicHandler = mqttClientUnsubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientUnsubscribedTopicHandler));
|
||||||
_mqttConnectionValidator = mqttConnectionValidator ?? throw new ArgumentNullException(nameof(mqttConnectionValidator));
|
_mqttConnectionValidator = mqttConnectionValidator ?? throw new ArgumentNullException(nameof(mqttConnectionValidator));
|
||||||
_mqttSubscriptionInterceptor = mqttSubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttSubscriptionInterceptor));
|
_mqttSubscriptionInterceptor = mqttSubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttSubscriptionInterceptor));
|
||||||
|
_mqttUnsubscriptionInterceptor = mqttUnsubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttUnsubscriptionInterceptor));
|
||||||
_mqttApplicationMessageInterceptor = mqttApplicationMessageInterceptor ?? throw new ArgumentNullException(nameof(mqttApplicationMessageInterceptor));
|
_mqttApplicationMessageInterceptor = mqttApplicationMessageInterceptor ?? throw new ArgumentNullException(nameof(mqttApplicationMessageInterceptor));
|
||||||
_mqttServerStorage = mqttServerStorage ?? throw new ArgumentNullException(nameof(mqttServerStorage));
|
_mqttServerStorage = mqttServerStorage ?? throw new ArgumentNullException(nameof(mqttServerStorage));
|
||||||
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
_webSocketServerAdapter = new MqttWebSocketServerAdapter(mqttFactory.Logger.CreateChildLogger());
|
_webSocketServerAdapter = new MqttWebSocketServerAdapter(mqttFactory.Logger);
|
||||||
|
|
||||||
var adapters = new List<IMqttServerAdapter>
|
var adapters = new List<IMqttServerAdapter>
|
||||||
{
|
{
|
||||||
new MqttTcpServerAdapter(mqttFactory.Logger.CreateChildLogger())
|
new MqttTcpServerAdapter(mqttFactory.Logger)
|
||||||
{
|
{
|
||||||
TreatSocketOpeningErrorAsWarning = true // Opening other ports than for HTTP is not allows in Azure App Services.
|
TreatSocketOpeningErrorAsWarning = true // Opening other ports than for HTTP is not allows in Azure App Services.
|
||||||
},
|
},
|
||||||
@@ -124,7 +127,7 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
return _mqttServer.PublishAsync(applicationMessage);
|
return _mqttServer.PublishAsync(applicationMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Publish(PythonDictionary parameters)
|
void Publish(PythonDictionary parameters)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -170,7 +173,7 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMqttServerOptions CreateMqttServerOptions()
|
IMqttServerOptions CreateMqttServerOptions()
|
||||||
{
|
{
|
||||||
var options = new MqttServerOptionsBuilder()
|
var options = new MqttServerOptionsBuilder()
|
||||||
.WithMaxPendingMessagesPerClient(_settings.MaxPendingMessagesPerClient)
|
.WithMaxPendingMessagesPerClient(_settings.MaxPendingMessagesPerClient)
|
||||||
@@ -178,8 +181,9 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
.WithConnectionValidator(_mqttConnectionValidator)
|
.WithConnectionValidator(_mqttConnectionValidator)
|
||||||
.WithApplicationMessageInterceptor(_mqttApplicationMessageInterceptor)
|
.WithApplicationMessageInterceptor(_mqttApplicationMessageInterceptor)
|
||||||
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
|
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
|
||||||
|
.WithUnsubscriptionInterceptor(_mqttUnsubscriptionInterceptor)
|
||||||
.WithStorage(_mqttServerStorage);
|
.WithStorage(_mqttServerStorage);
|
||||||
|
|
||||||
// Configure unencrypted connections
|
// Configure unencrypted connections
|
||||||
if (_settings.TcpEndPoint.Enabled)
|
if (_settings.TcpEndPoint.Enabled)
|
||||||
{
|
{
|
||||||
@@ -208,10 +212,30 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
// Configure encrypted connections
|
// Configure encrypted connections
|
||||||
if (_settings.EncryptedTcpEndPoint.Enabled)
|
if (_settings.EncryptedTcpEndPoint.Enabled)
|
||||||
{
|
{
|
||||||
|
#if NETCOREAPP3_1 || NET5_0
|
||||||
options
|
options
|
||||||
.WithEncryptedEndpoint()
|
.WithEncryptedEndpoint()
|
||||||
.WithEncryptionSslProtocol(SslProtocols.Tls12)
|
.WithEncryptionSslProtocol(SslProtocols.Tls13);
|
||||||
.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.ReadCertificate());
|
#else
|
||||||
|
options
|
||||||
|
.WithEncryptedEndpoint()
|
||||||
|
.WithEncryptionSslProtocol(SslProtocols.Tls12);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Path))
|
||||||
|
{
|
||||||
|
IMqttServerCertificateCredentials certificateCredentials = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Password))
|
||||||
|
{
|
||||||
|
certificateCredentials = new MqttServerCertificateCredentials
|
||||||
|
{
|
||||||
|
Password = _settings.EncryptedTcpEndPoint.Certificate.Password
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
options.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.Certificate.ReadCertificate(), certificateCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
if (_settings.EncryptedTcpEndPoint.TryReadIPv4(out var address4))
|
if (_settings.EncryptedTcpEndPoint.TryReadIPv4(out var address4))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,14 +21,16 @@ namespace MQTTnet.Server.Mqtt
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var sessionItems = (PythonDictionary)context.SessionItems[MqttServerConnectionValidator.WrappedSessionItemsKey];
|
||||||
|
|
||||||
var pythonContext = new PythonDictionary
|
var pythonContext = new PythonDictionary
|
||||||
{
|
{
|
||||||
{ "accept_subscription", context.AcceptSubscription },
|
|
||||||
{ "close_connection", context.CloseConnection },
|
|
||||||
|
|
||||||
{ "client_id", context.ClientId },
|
{ "client_id", context.ClientId },
|
||||||
|
{ "session_items", sessionItems },
|
||||||
{ "topic", context.TopicFilter.Topic },
|
{ "topic", context.TopicFilter.Topic },
|
||||||
{ "qos", (int)context.TopicFilter.QualityOfServiceLevel }
|
{ "qos", (int)context.TopicFilter.QualityOfServiceLevel },
|
||||||
|
{ "accept_subscription", context.AcceptSubscription },
|
||||||
|
{ "close_connection", context.CloseConnection }
|
||||||
};
|
};
|
||||||
|
|
||||||
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_subscription", pythonContext);
|
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_subscription", pythonContext);
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using IronPython.Runtime;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MQTTnet.Server.Scripting;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server.Mqtt
|
||||||
|
{
|
||||||
|
public class MqttUnsubscriptionInterceptor : IMqttServerUnsubscriptionInterceptor
|
||||||
|
{
|
||||||
|
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public MqttUnsubscriptionInterceptor(PythonScriptHostService pythonScriptHostService, ILogger<MqttUnsubscriptionInterceptor> logger)
|
||||||
|
{
|
||||||
|
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sessionItems = (PythonDictionary)context.SessionItems[MqttServerConnectionValidator.WrappedSessionItemsKey];
|
||||||
|
|
||||||
|
var pythonContext = new PythonDictionary
|
||||||
|
{
|
||||||
|
{ "client_id", context.ClientId },
|
||||||
|
{ "session_items", sessionItems },
|
||||||
|
{ "topic", context.Topic },
|
||||||
|
{ "accept_unsubscription", context.AcceptUnsubscription },
|
||||||
|
{ "close_connection", context.CloseConnection }
|
||||||
|
};
|
||||||
|
|
||||||
|
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_unsubscription", pythonContext);
|
||||||
|
|
||||||
|
context.AcceptUnsubscription = (bool)pythonContext["accept_unsubscription"];
|
||||||
|
context.CloseConnection = (bool)pythonContext["close_connection"];
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.LogError(exception, "Error while intercepting unsubscription.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using System.Reflection;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.AspNetCore;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using MQTTnet.Server.Web;
|
using MQTTnet.Server.Web;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
@@ -14,7 +16,15 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
PrintLogo();
|
PrintLogo();
|
||||||
|
|
||||||
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build().Run();
|
Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.ConfigureKestrel(serverOptions =>
|
||||||
|
{
|
||||||
|
})
|
||||||
|
.UseWebRoot(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot"))
|
||||||
|
.UseStartup<Startup>();
|
||||||
|
}).Build().Run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -25,7 +35,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PrintLogo()
|
static void PrintLogo()
|
||||||
{
|
{
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
@@ -46,14 +56,15 @@ namespace MQTTnet.Server
|
|||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
Console.WriteLine("The official MQTT server implementation of MQTTnet");
|
Console.WriteLine("The official MQTT server implementation of MQTTnet");
|
||||||
Console.WriteLine("Copyright (c) 2017-2019 The MQTTnet Team");
|
Console.WriteLine("Copyright (c) 2017-2020 The MQTTnet Team");
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Blue;
|
|
||||||
Console.WriteLine(@"https://github.com/chkr1011/MQTTnet");
|
Console.WriteLine(@"https://github.com/chkr1011/MQTTnet");
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||||
|
|
||||||
Console.WriteLine($@"
|
Console.WriteLine($@"
|
||||||
Version: {Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}
|
Version: {fileVersion.ProductVersion}
|
||||||
License: MIT (read LICENSE file)
|
License: MIT (read LICENSE file)
|
||||||
Sponsoring: https://opencollective.com/mqttnet
|
Sponsoring: https://opencollective.com/mqttnet
|
||||||
Support: https://github.com/chkr1011/MQTTnet/issues
|
Support: https://github.com/chkr1011/MQTTnet/issues
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server.Scripting.DataSharing
|
namespace MQTTnet.Server.Scripting.DataSharing
|
||||||
{
|
{
|
||||||
public class DataSharingService
|
public class DataSharingService
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, object> _storage = new Dictionary<string, object>();
|
readonly Dictionary<string, object> _storage = new Dictionary<string, object>();
|
||||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
readonly PythonScriptHostService _pythonScriptHostService;
|
||||||
private readonly ILogger<DataSharingService> _logger;
|
readonly ILogger<DataSharingService> _logger;
|
||||||
|
|
||||||
public DataSharingService(PythonScriptHostService pythonScriptHostService, ILogger<DataSharingService> logger)
|
public DataSharingService(PythonScriptHostService pythonScriptHostService, ILogger<DataSharingService> logger)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server.Scripting
|
namespace MQTTnet.Server.Scripting
|
||||||
{
|
{
|
||||||
public class PythonIOStream : Stream
|
public class PythonIOStream : Stream
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
readonly ILogger _logger;
|
||||||
private readonly Encoding _encoder = Encoding.UTF8;
|
readonly Encoding _encoder = Encoding.UTF8;
|
||||||
|
|
||||||
public PythonIOStream(ILogger<PythonIOStream> logger)
|
public PythonIOStream(ILogger<PythonIOStream> logger)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
using System;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Scripting;
|
||||||
|
using Microsoft.Scripting.Hosting;
|
||||||
|
using MQTTnet.Server.Configuration;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -6,22 +10,18 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Scripting;
|
|
||||||
using Microsoft.Scripting.Hosting;
|
|
||||||
using MQTTnet.Server.Configuration;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server.Scripting
|
namespace MQTTnet.Server.Scripting
|
||||||
{
|
{
|
||||||
public class PythonScriptHostService
|
public class PythonScriptHostService
|
||||||
{
|
{
|
||||||
private readonly IDictionary<string, object> _proxyObjects = new ExpandoObject();
|
readonly IDictionary<string, object> _proxyObjects = new ExpandoObject();
|
||||||
private readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>();
|
readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>();
|
||||||
private readonly string _scriptsPath;
|
readonly string _scriptsPath;
|
||||||
private readonly ScriptingSettingsModel _scriptingSettings;
|
readonly ScriptingSettingsModel _scriptingSettings;
|
||||||
private readonly ILogger<PythonScriptHostService> _logger;
|
readonly ILogger<PythonScriptHostService> _logger;
|
||||||
private readonly ScriptEngine _scriptEngine;
|
readonly ScriptEngine _scriptEngine;
|
||||||
|
|
||||||
public PythonScriptHostService(ScriptingSettingsModel scriptingSettings, PythonIOStream pythonIOStream, ILogger<PythonScriptHostService> logger)
|
public PythonScriptHostService(ScriptingSettingsModel scriptingSettings, PythonIOStream pythonIOStream, ILogger<PythonScriptHostService> logger)
|
||||||
{
|
{
|
||||||
_scriptingSettings = scriptingSettings ?? throw new ArgumentNullException(nameof(scriptingSettings));
|
_scriptingSettings = scriptingSettings ?? throw new ArgumentNullException(nameof(scriptingSettings));
|
||||||
@@ -139,7 +139,7 @@ namespace MQTTnet.Server.Scripting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryInitializeScriptAsync(string path)
|
async Task TryInitializeScriptAsync(string path)
|
||||||
{
|
{
|
||||||
var uid = new FileInfo(path).Name.Replace(".py", string.Empty, StringComparison.OrdinalIgnoreCase);
|
var uid = new FileInfo(path).Name.Replace(".py", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ namespace MQTTnet.Server.Scripting
|
|||||||
{
|
{
|
||||||
_scriptInstances.Add(scriptInstance);
|
_scriptInstances.Add(scriptInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation($"Initialized script '{uid}'.");
|
_logger.LogInformation($"Initialized script '{uid}'.");
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
@@ -164,7 +164,7 @@ namespace MQTTnet.Server.Scripting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PythonScriptInstance CreateScriptInstance(string uid, string path, string code)
|
PythonScriptInstance CreateScriptInstance(string uid, string path, string code)
|
||||||
{
|
{
|
||||||
var scriptScope = _scriptEngine.CreateScope();
|
var scriptScope = _scriptEngine.CreateScope();
|
||||||
|
|
||||||
@@ -173,11 +173,11 @@ namespace MQTTnet.Server.Scripting
|
|||||||
|
|
||||||
scriptScope.SetVariable("mqtt_net_server", _proxyObjects);
|
scriptScope.SetVariable("mqtt_net_server", _proxyObjects);
|
||||||
compiledCode.Execute(scriptScope);
|
compiledCode.Execute(scriptScope);
|
||||||
|
|
||||||
return new PythonScriptInstance(uid, path, scriptScope);
|
return new PythonScriptInstance(uid, path, scriptScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSearchPaths(ScriptEngine scriptEngine)
|
void AddSearchPaths(ScriptEngine scriptEngine)
|
||||||
{
|
{
|
||||||
if (_scriptingSettings.IncludePaths?.Any() != true)
|
if (_scriptingSettings.IncludePaths?.Any() != true)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using System;
|
using IronPython.Runtime;
|
||||||
using IronPython.Runtime;
|
|
||||||
using Microsoft.Scripting.Hosting;
|
using Microsoft.Scripting.Hosting;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Scripting
|
namespace MQTTnet.Server.Scripting
|
||||||
{
|
{
|
||||||
public class PythonScriptInstance
|
public class PythonScriptInstance
|
||||||
{
|
{
|
||||||
private readonly ScriptScope _scriptScope;
|
readonly ScriptScope _scriptScope;
|
||||||
|
|
||||||
public PythonScriptInstance(string uid, string path, ScriptScope scriptScope)
|
public PythonScriptInstance(string uid, string path, ScriptScope scriptScope)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
using System;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.Scripting.Utils;
|
using Microsoft.Scripting.Utils;
|
||||||
|
using MQTTnet.AspNetCore;
|
||||||
using MQTTnet.Server.Configuration;
|
using MQTTnet.Server.Configuration;
|
||||||
using MQTTnet.Server.Logging;
|
using MQTTnet.Server.Logging;
|
||||||
using MQTTnet.Server.Mqtt;
|
using MQTTnet.Server.Mqtt;
|
||||||
using MQTTnet.Server.Scripting;
|
using MQTTnet.Server.Scripting;
|
||||||
using MQTTnet.Server.Scripting.DataSharing;
|
using MQTTnet.Server.Scripting.DataSharing;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Swashbuckle.AspNetCore.SwaggerUI;
|
using Swashbuckle.AspNetCore.SwaggerUI;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace MQTTnet.Server.Web
|
namespace MQTTnet.Server.Web
|
||||||
{
|
{
|
||||||
@@ -35,33 +36,28 @@ namespace MQTTnet.Server.Web
|
|||||||
|
|
||||||
public void Configure(
|
public void Configure(
|
||||||
IApplicationBuilder application,
|
IApplicationBuilder application,
|
||||||
IHostingEnvironment environment,
|
|
||||||
MqttServerService mqttServerService,
|
MqttServerService mqttServerService,
|
||||||
PythonScriptHostService pythonScriptHostService,
|
PythonScriptHostService pythonScriptHostService,
|
||||||
DataSharingService dataSharingService,
|
DataSharingService dataSharingService,
|
||||||
MqttSettingsModel mqttSettings)
|
MqttSettingsModel mqttSettings)
|
||||||
{
|
{
|
||||||
if (environment.IsDevelopment())
|
application.UseDefaultFiles();
|
||||||
{
|
application.UseStaticFiles();
|
||||||
application.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
application.UseHsts();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
application.UseHsts();
|
||||||
|
application.UseRouting();
|
||||||
application.UseCors(x => x
|
application.UseCors(x => x
|
||||||
.AllowAnyOrigin()
|
.AllowAnyOrigin()
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader());
|
||||||
.AllowCredentials());
|
|
||||||
|
|
||||||
application.UseAuthentication();
|
application.UseAuthentication();
|
||||||
|
application.UseAuthorization();
|
||||||
application.UseStaticFiles();
|
|
||||||
|
application.UseEndpoints(endpoints =>
|
||||||
application.UseHttpsRedirection();
|
{
|
||||||
application.UseMvc();
|
endpoints.MapControllers();
|
||||||
|
});
|
||||||
|
|
||||||
ConfigureWebSocketEndpoint(application, mqttServerService, mqttSettings);
|
ConfigureWebSocketEndpoint(application, mqttServerService, mqttSettings);
|
||||||
|
|
||||||
@@ -87,11 +83,13 @@ namespace MQTTnet.Server.Web
|
|||||||
{
|
{
|
||||||
services.AddCors();
|
services.AddCors();
|
||||||
|
|
||||||
|
services.AddControllers();
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddMvc()
|
||||||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
|
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
|
||||||
.AddJsonOptions(options =>
|
.AddNewtonsoftJson(o =>
|
||||||
{
|
{
|
||||||
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
|
o.SerializerSettings.Converters.Add(new StringEnumConverter());
|
||||||
});
|
});
|
||||||
|
|
||||||
ReadMqttSettings(services);
|
ReadMqttSettings(services);
|
||||||
@@ -111,18 +109,22 @@ namespace MQTTnet.Server.Web
|
|||||||
services.AddSingleton<MqttClientUnsubscribedTopicHandler>();
|
services.AddSingleton<MqttClientUnsubscribedTopicHandler>();
|
||||||
services.AddSingleton<MqttServerConnectionValidator>();
|
services.AddSingleton<MqttServerConnectionValidator>();
|
||||||
services.AddSingleton<MqttSubscriptionInterceptor>();
|
services.AddSingleton<MqttSubscriptionInterceptor>();
|
||||||
|
services.AddSingleton<MqttUnsubscriptionInterceptor>();
|
||||||
services.AddSingleton<MqttApplicationMessageInterceptor>();
|
services.AddSingleton<MqttApplicationMessageInterceptor>();
|
||||||
|
|
||||||
services.AddSwaggerGen(c =>
|
services.AddSwaggerGen(c =>
|
||||||
{
|
{
|
||||||
c.DescribeAllEnumsAsStrings();
|
|
||||||
|
|
||||||
var securityScheme = new OpenApiSecurityScheme
|
var securityScheme = new OpenApiSecurityScheme
|
||||||
{
|
{
|
||||||
Scheme = "Basic",
|
Scheme = "basic",
|
||||||
Name = HeaderNames.Authorization,
|
Name = HeaderNames.Authorization,
|
||||||
Type = SecuritySchemeType.Http,
|
Type = SecuritySchemeType.Http,
|
||||||
In = ParameterLocation.Header
|
In = ParameterLocation.Header,
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Swagger"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
c.AddSecurityDefinition("Swagger", securityScheme);
|
c.AddSecurityDefinition("Swagger", securityScheme);
|
||||||
@@ -156,7 +158,7 @@ namespace MQTTnet.Server.Web
|
|||||||
.AddCookie();
|
.AddCookie();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadMqttSettings(IServiceCollection services)
|
void ReadMqttSettings(IServiceCollection services)
|
||||||
{
|
{
|
||||||
var mqttSettings = new MqttSettingsModel();
|
var mqttSettings = new MqttSettingsModel();
|
||||||
Configuration.Bind("MQTT", mqttSettings);
|
Configuration.Bind("MQTT", mqttSettings);
|
||||||
@@ -167,7 +169,7 @@ namespace MQTTnet.Server.Web
|
|||||||
services.AddSingleton(scriptingSettings);
|
services.AddSingleton(scriptingSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ConfigureWebSocketEndpoint(
|
static void ConfigureWebSocketEndpoint(
|
||||||
IApplicationBuilder application,
|
IApplicationBuilder application,
|
||||||
MqttServerService mqttServerService,
|
MqttServerService mqttServerService,
|
||||||
MqttSettingsModel mqttSettings)
|
MqttSettingsModel mqttSettings)
|
||||||
@@ -184,8 +186,7 @@ namespace MQTTnet.Server.Web
|
|||||||
|
|
||||||
var webSocketOptions = new WebSocketOptions
|
var webSocketOptions = new WebSocketOptions
|
||||||
{
|
{
|
||||||
KeepAliveInterval = TimeSpan.FromSeconds(mqttSettings.WebSocketEndPoint.KeepAliveInterval),
|
KeepAliveInterval = TimeSpan.FromSeconds(mqttSettings.WebSocketEndPoint.KeepAliveInterval)
|
||||||
ReceiveBufferSize = mqttSettings.WebSocketEndPoint.ReceiveBufferSize
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mqttSettings.WebSocketEndPoint.AllowedOrigins?.Any() == true)
|
if (mqttSettings.WebSocketEndPoint.AllowedOrigins?.Any() == true)
|
||||||
@@ -201,7 +202,13 @@ namespace MQTTnet.Server.Web
|
|||||||
{
|
{
|
||||||
if (context.WebSockets.IsWebSocketRequest)
|
if (context.WebSockets.IsWebSocketRequest)
|
||||||
{
|
{
|
||||||
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false))
|
string subProtocol = null;
|
||||||
|
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
|
||||||
|
{
|
||||||
|
subProtocol = MqttSubProtocolSelector.SelectSubProtocol(requestedSubProtocolValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await mqttServerService.RunWebSocketConnectionAsync(webSocket, context).ConfigureAwait(false);
|
await mqttServerService.RunWebSocketConnectionAsync(webSocket, context).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
World
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>MQTT JS Example</title>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mqtt@4.0.1/dist/mqtt.min.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var client = mqtt.connect('ws://localhost:80/mqtt')
|
||||||
|
|
||||||
|
client.on('connect', function () {
|
||||||
|
client.subscribe('mqtt_subscription', function (err) {
|
||||||
|
console.log("Subscribed");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('message', function (topic, message) {
|
||||||
|
console.log(topic);
|
||||||
|
console.log(message.toString())
|
||||||
|
})
|
||||||
|
|
||||||
|
function buttonClick() {
|
||||||
|
client.publish("MQTT_JS_TOPIC", "payload");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<button onclick="buttonClick()">Publish</button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>paho JS Example</title>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var mqttClient = new Paho.MQTT.Client("localhost", 80, "/mqtt", "pahoJS_client");
|
||||||
|
mqttClient.onConnectionLost = onConnectionLost;
|
||||||
|
mqttClient.onMessageArrived = onMessageArrived;
|
||||||
|
mqttClient.connect({ onSuccess: onConnect });
|
||||||
|
|
||||||
|
function onConnect() {
|
||||||
|
console.log("MQTT client connected");
|
||||||
|
mqttClient.subscribe("pahoJS_subscription");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConnectionLost(responseObject) {
|
||||||
|
if (responseObject.errorCode !== 0) {
|
||||||
|
console.log("onConnectionLost:" + responseObject.errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessageArrived(message) {
|
||||||
|
console.log("onMessageArrived:" + message.payloadString);
|
||||||
|
}
|
||||||
|
function buttonClick() {
|
||||||
|
message = new Paho.MQTT.Message("Hello");
|
||||||
|
message.destinationName = "pahoJS_topic";
|
||||||
|
mqttClient.send(message);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<button onclick="buttonClick()">Publish</button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -27,7 +27,10 @@
|
|||||||
"IPv4": "*",
|
"IPv4": "*",
|
||||||
"IPv6": "*",
|
"IPv6": "*",
|
||||||
"Port": 8883,
|
"Port": 8883,
|
||||||
"CertificatePath": "/absolute/path/to/pfx"
|
"Certificate": {
|
||||||
|
"Path": "/absolute/path/to/pfx",
|
||||||
|
"Password": ""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"WebSocketEndPoint": {
|
"WebSocketEndPoint": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
@@ -49,11 +52,7 @@
|
|||||||
},
|
},
|
||||||
"Scripting": {
|
"Scripting": {
|
||||||
"ScriptsPath": "Scripts",
|
"ScriptsPath": "Scripts",
|
||||||
"IncludePaths": [
|
"IncludePaths": []
|
||||||
"Lib",
|
|
||||||
"/usr/lib/python2.7",
|
|
||||||
"C:\\Python27\\Lib"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
@@ -63,4 +62,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||