Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cea751ff9d | ||
|
|
e88b280eb0 | ||
|
|
e4b07f2b8c | ||
|
|
4eb6e77eb5 | ||
|
|
db1fc7625d | ||
|
|
bfec9dc5ad | ||
|
|
56f0a2c31c | ||
|
|
5ee0bb4b65 | ||
|
|
5c74728387 | ||
|
|
97c46bea0f | ||
|
|
e6c1ab4e4c | ||
|
|
6e1ec266a7 | ||
|
|
3fc6982e9a | ||
|
|
5b1cc7d713 | ||
|
|
2842f27522 | ||
|
|
7ef137e26e | ||
|
|
b1a336eb62 | ||
|
|
d481e93832 | ||
|
|
8cf5537043 | ||
|
|
d2ce9d607a | ||
|
|
36736914bc | ||
|
|
7823d8342e | ||
|
|
431142471f | ||
|
|
a3227a444a | ||
|
|
f74af45fba | ||
|
|
e050e2d61e | ||
|
|
ef85ef676a | ||
|
|
e977546297 | ||
|
|
ae92b0ed33 | ||
|
|
7e686d9aa5 | ||
|
|
d23bbf7bf3 | ||
|
|
d4dad4860a | ||
|
|
c009cbef76 | ||
|
|
37e60c73ae | ||
|
|
3ab095a568 | ||
|
|
f5d9b65139 | ||
|
|
31e5b40459 | ||
|
|
8fb55d75fe | ||
|
|
420222511b | ||
|
|
c5cec60809 | ||
|
|
12dd815421 | ||
|
|
f36f49cb3e | ||
|
|
9152fe637e | ||
|
|
b976e9c177 | ||
|
|
262a4681ad | ||
|
|
ad546adafe | ||
|
|
29a9941d86 | ||
|
|
5a21939e29 | ||
|
|
469caf656e | ||
|
|
42402fba04 | ||
|
|
a0dc8ab0d7 | ||
|
|
02ede5a2d8 | ||
|
|
cef61900df | ||
|
|
09385b1b36 | ||
|
|
cbf413f04e | ||
|
|
11249d006f | ||
|
|
0d7b020994 | ||
|
|
d71ff3d615 | ||
|
|
57745e8324 | ||
|
|
a94776eeea | ||
|
|
d3848d8cb0 | ||
|
|
6c29ea56fc | ||
|
|
ed7c150cc5 | ||
|
|
13762eedd4 | ||
|
|
e33495010e | ||
|
|
b0d1fcd161 | ||
|
|
f7a739e162 | ||
|
|
422945929e | ||
|
|
76e54dc49b | ||
|
|
b10a69a0ae | ||
|
|
4b1c7cf772 | ||
|
|
3f67df007b | ||
|
|
36b1ed06f0 | ||
|
|
4a982ea228 | ||
|
|
9fe5073186 | ||
|
|
305c552474 | ||
|
|
f632fbb447 | ||
|
|
8231d62f9f | ||
|
|
a52a717965 | ||
|
|
2b653f2379 | ||
|
|
725cfb643f | ||
|
|
29ec6edbf4 | ||
|
|
f3ef2dbf7c | ||
|
|
14eb202873 | ||
|
|
a3c7f9a22c | ||
|
|
41e0a25fc8 | ||
|
|
772cd3cd12 | ||
|
|
42cf9f73c2 | ||
|
|
ec2e08668f | ||
|
|
e9e8583d1a | ||
|
|
f68b109471 | ||
|
|
dd1e155ff4 | ||
|
|
cf6369d63f | ||
|
|
3049fc6608 | ||
|
|
b75076a1c5 | ||
|
|
ae8e2ec7c9 | ||
|
|
e7e6a080e0 | ||
|
|
dc9afa6c3a | ||
|
|
02b17f277d | ||
|
|
b9d9ea2d4d | ||
|
|
c9cc6c9c0f | ||
|
|
967c964111 | ||
|
|
80aaca63f9 | ||
|
|
eeeb479db2 | ||
|
|
9e47a0985b | ||
|
|
2d9ae0576b | ||
|
|
fcf276dd1a | ||
|
|
920728e77a | ||
|
|
1d4794b071 | ||
|
|
626baa7bb5 | ||
|
|
810746b56b | ||
|
|
7cf454952f | ||
|
|
cf2974cd34 | ||
|
|
7d95c238c3 | ||
|
|
9a94b0465d | ||
|
|
1d8b6e387d | ||
|
|
73d681bc1f | ||
|
|
2ce9b94ec9 | ||
|
|
47e674e4d3 | ||
|
|
d5691346a9 | ||
|
|
0730f21d29 | ||
|
|
6dfa7f0769 | ||
|
|
27592f1643 | ||
|
|
c6f4b59438 | ||
|
|
b362b2afc2 | ||
|
|
7a72a8d562 | ||
|
|
bd40e10a66 | ||
|
|
4b44a2b2b1 | ||
|
|
215f24a95b | ||
|
|
72f9acdc20 | ||
|
|
1e5390679f | ||
|
|
5cafce4345 | ||
|
|
dfaf3dc31f | ||
|
|
3a9397c793 | ||
|
|
1cf4a7d6be | ||
|
|
180588c3a4 | ||
|
|
bc4c86bebd | ||
|
|
ea88a8c0de | ||
|
|
d98129481a | ||
|
|
5e5818d7df | ||
|
|
72c7a8959c | ||
|
|
39e637795e | ||
|
|
731c89d2e9 | ||
|
|
25ddfc83a8 | ||
|
|
2d94abdde3 | ||
|
|
f0ea13c07f | ||
|
|
47cd5aa3cd | ||
|
|
258df6bb14 | ||
|
|
85c3c0b352 | ||
|
|
8020e66f41 | ||
|
|
bd004ec327 | ||
|
|
1e68c2e815 | ||
|
|
d7e1c89d62 | ||
|
|
b779d04636 | ||
|
|
623d8cafaa | ||
|
|
0920c86d37 | ||
|
|
c756a4092f | ||
|
|
feb53e78c6 | ||
|
|
dd0aba0640 | ||
|
|
68f1043ef5 | ||
|
|
d01d859227 | ||
|
|
fcab0d5cf0 | ||
|
|
b66a18f8dd | ||
|
|
8e1e93c00f | ||
|
|
cd8940f9b7 | ||
|
|
9d9077f17c | ||
|
|
fa6859d68a | ||
|
|
4f14373117 | ||
|
|
90ec39f2a4 | ||
|
|
2aa4d1b77a | ||
|
|
aa9f8d8ef3 | ||
|
|
50381637af | ||
|
|
8905b612c9 | ||
|
|
3cdf6d1261 | ||
|
|
d1c883ebae | ||
|
|
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 | ||
|
|
2ed8e55394 | ||
|
|
c5b6ca204d | ||
|
|
7a767c7d2f | ||
|
|
dd96cf98a8 | ||
|
|
6ee3d1640f | ||
|
|
6f8272210c | ||
|
|
ce05cc9936 | ||
|
|
985c3084a8 | ||
|
|
7b3be3a64f | ||
|
|
c50fb740fc | ||
|
|
5895a73f85 | ||
|
|
961a497798 | ||
|
|
6a90864c44 | ||
|
|
a9017b8795 | ||
|
|
f76e130283 | ||
|
|
5a48b146b4 | ||
|
|
1d1def3275 | ||
|
|
bd75a2440e | ||
|
|
7a642802ed | ||
|
|
a8f8601bc5 | ||
|
|
0c7a5a992b | ||
|
|
bd665c3d56 | ||
|
|
7e7b36aadf | ||
|
|
a79c2484b3 | ||
|
|
e4e46f0094 | ||
|
|
5a4c735b85 | ||
|
|
42516942ac | ||
|
|
591ccfec29 | ||
|
|
ffc1d950da | ||
|
|
1c004ead6d | ||
|
|
b0ad6bda70 | ||
|
|
6262a16504 | ||
|
|
0de683979d | ||
|
|
0a6f564446 | ||
|
|
f0be3ef0cf | ||
|
|
f79eebdf64 | ||
|
|
c3c0dcf313 | ||
|
|
60c6074953 | ||
|
|
2b9b22def6 | ||
|
|
5cfb092449 | ||
|
|
a450fc4e01 | ||
|
|
ffe9c57ae8 | ||
|
|
0257e31910 | ||
|
|
7fe5f521dc | ||
|
|
2d03c267e4 | ||
|
|
ccfe67e6a6 | ||
|
|
98e17903ea | ||
|
|
c7d56a78f3 | ||
|
|
b491c74228 | ||
|
|
a2414f48ca | ||
|
|
396e0e1697 | ||
|
|
01f6c959e1 | ||
|
|
f425d87562 | ||
|
|
6614b23ab8 | ||
|
|
02c9133a1c | ||
|
|
913afa3977 | ||
|
|
e068286f15 | ||
|
|
373fe8c72c | ||
|
|
396f040aae | ||
|
|
c90b5f6fb2 | ||
|
|
744b1b302b | ||
|
|
78e504dc2c | ||
|
|
79518d4a35 | ||
|
|
a50fb2a320 | ||
|
|
9fa9d22097 | ||
|
|
e4351b73bd | ||
|
|
2d3fdd4faf | ||
|
|
0a509fd685 | ||
|
|
d1a17314ef | ||
|
|
e96b66e9f8 | ||
|
|
80b05a8944 | ||
|
|
ab3df2ba65 | ||
|
|
f169aaa79b | ||
|
|
231001850a | ||
|
|
6839970d41 | ||
|
|
4df29be155 | ||
|
|
c5cfede231 | ||
|
|
c22b6033e3 | ||
|
|
27476a9194 | ||
|
|
12973a4179 | ||
|
|
01b437dc08 | ||
|
|
ac88f0a05a | ||
|
|
b02f30844c | ||
|
|
1a8bcae47c | ||
|
|
664549ab93 | ||
|
|
914d2b641f | ||
|
|
0cc0fcf5d9 | ||
|
|
5980cbd944 | ||
|
|
3ef7f60a18 | ||
|
|
efef23e3f5 | ||
|
|
53ab2ac140 | ||
|
|
2ecbd83d06 | ||
|
|
a278b6189b | ||
|
|
cdbdfdec6d | ||
|
|
808c2da5f6 | ||
|
|
6ed3b0cedd | ||
|
|
9da3377aa7 | ||
|
|
0cac2aa1bc | ||
|
|
2d59b5c1ac | ||
|
|
9dfa0b32e4 | ||
|
|
20a7579156 | ||
|
|
c7409c2ff4 | ||
|
|
d4c6fb44c9 | ||
|
|
e6cf23aebd | ||
|
|
0fec860b25 | ||
|
|
2c927c5995 | ||
|
|
6399172582 | ||
|
|
5c903e6fbf | ||
|
|
f60bbf7dd7 | ||
|
|
519bb05aac | ||
|
|
a8434d1b58 | ||
|
|
420b35e37d | ||
|
|
a25c8cd4c7 | ||
|
|
8ac77558af | ||
|
|
953578eba2 | ||
|
|
527713ccf8 | ||
|
|
477e2d23ab | ||
|
|
03c61ad82c | ||
|
|
9475ccd0d8 | ||
|
|
73b051d159 | ||
|
|
a9944def68 | ||
|
|
aee10ba6fa | ||
|
|
cfc1b27950 | ||
|
|
149d01e173 | ||
|
|
888e1797d7 | ||
|
|
f8ade2daf4 | ||
|
|
a85792c392 | ||
|
|
fbca8a6dc1 | ||
|
|
732ea84caa | ||
|
|
65896269da | ||
|
|
631f660d5c | ||
|
|
7f08371532 | ||
|
|
1afd59325f | ||
|
|
45c033f401 | ||
|
|
7855eccb78 | ||
|
|
d51300d32d | ||
|
|
61b10a8b56 | ||
|
|
dbee941dcc | ||
|
|
fd7c98d0d1 | ||
|
|
c911797f1b | ||
|
|
b5a1d3a69f | ||
|
|
cdeb073bb0 | ||
|
|
a8db0dd3d6 | ||
|
|
2267770a72 | ||
|
|
35ee732045 | ||
|
|
ad5834dd1f | ||
|
|
a7204234f6 | ||
|
|
e8c33077b7 | ||
|
|
bd86dae8a9 | ||
|
|
7188aaf79d | ||
|
|
bafcc81672 | ||
|
|
d0f1659eec | ||
|
|
11a5b5a080 | ||
|
|
7ed5580352 | ||
|
|
efc6f124b4 | ||
|
|
7c3d88f62d | ||
|
|
b383a54416 | ||
|
|
673fc5e20c | ||
|
|
f2b9642712 | ||
|
|
4f03f22afb | ||
|
|
27a4af6070 | ||
|
|
0184ce400c | ||
|
|
653ea8a102 | ||
|
|
3450889e84 | ||
|
|
1311535eed | ||
|
|
e1799ea6a3 | ||
|
|
cd76f434e3 | ||
|
|
fd91170aee | ||
|
|
cd1bfc3a10 | ||
|
|
f074e9ed04 | ||
|
|
562a5304f6 | ||
|
|
1e697a94a1 | ||
|
|
0e2c3abd05 | ||
|
|
7321774c45 | ||
|
|
4a65cab769 | ||
|
|
510c3bd0bf | ||
|
|
0c056b511e | ||
|
|
2ca6866c5e | ||
|
|
ebcce9b8be | ||
|
|
9e7c70e649 | ||
|
|
bef0860e53 | ||
|
|
67c9177731 | ||
|
|
007991f073 | ||
|
|
532dddeb6c | ||
|
|
9070087fad | ||
|
|
de8bcb7f37 | ||
|
|
5090cfb411 | ||
|
|
6e64d653c5 | ||
|
|
461bc6e594 | ||
|
|
0d95dc563c | ||
|
|
03bfc5f00b | ||
|
|
8708609498 | ||
|
|
dffc27c1f4 | ||
|
|
6f5f507323 | ||
|
|
26d6d817cd | ||
|
|
b68247f56d | ||
|
|
3b02a5f6aa | ||
|
|
09718a00e7 | ||
|
|
ecc2cd5f0c | ||
|
|
618580dc15 | ||
|
|
4860cec6c7 | ||
|
|
b9e0dbf150 | ||
|
|
2a4eb460da | ||
|
|
087c622122 | ||
|
|
2000de15e7 | ||
|
|
5e6b902430 | ||
|
|
a1f414a06d | ||
|
|
de3a39bdc2 | ||
|
|
6c5c9e5bf2 | ||
|
|
506873ed5b | ||
|
|
6a2bded181 | ||
|
|
ebf0e91ab8 | ||
|
|
107e96ff7d | ||
|
|
0d6e244f84 | ||
|
|
96a67579e2 | ||
|
|
4cba814716 | ||
|
|
b527059b72 | ||
|
|
c0507fcc55 | ||
|
|
38f2453c92 | ||
|
|
058bb65d31 | ||
|
|
38b215e9b5 | ||
|
|
45df33c9a5 | ||
|
|
89becaa191 | ||
|
|
6c87e4e039 | ||
|
|
cbe06d6b87 | ||
|
|
4fed80c2d0 | ||
|
|
74e4fd8b3f | ||
|
|
cc113a6c34 | ||
|
|
fca9876111 | ||
|
|
ac9f6a36f8 | ||
|
|
929b60e044 | ||
|
|
acb433dd4c | ||
|
|
c4e8bf7f39 | ||
|
|
ba4fdfb51c | ||
|
|
dfda916283 | ||
|
|
40326df9a9 | ||
|
|
a94444098a | ||
|
|
0c13e7a504 | ||
|
|
0dba57fe75 | ||
|
|
6483f896c1 | ||
|
|
8fa9943c3d | ||
|
|
195357835b | ||
|
|
28b2562112 | ||
|
|
ab24368de1 | ||
|
|
9b51404b4d | ||
|
|
619eaf284d | ||
|
|
86c348df58 | ||
|
|
fdb2ec897c | ||
|
|
b091fee554 | ||
|
|
14ec6ee793 | ||
|
|
0cfef0649a | ||
|
|
7292af7db4 | ||
|
|
bc1a197c4f | ||
|
|
ccc275902f | ||
|
|
0f5fb8aa3a | ||
|
|
83eca982e9 | ||
|
|
017f17a6b1 | ||
|
|
b3564e01a4 | ||
|
|
43105f71d8 | ||
|
|
40c408a9c0 | ||
|
|
7baff7c080 | ||
|
|
91a918d30b | ||
|
|
2a93fc18e4 | ||
|
|
31de6ee186 | ||
|
|
74d59673a8 | ||
|
|
d1c3d9b453 | ||
|
|
baa9241216 | ||
|
|
2c6c3ac6a4 | ||
|
|
b2c31331b6 | ||
|
|
9ff39c1fd9 | ||
|
|
210d57b254 | ||
|
|
7292cedd2f | ||
|
|
48d5afa799 | ||
|
|
3db22eea51 | ||
|
|
2fbb44ec66 | ||
|
|
d7b98080f5 | ||
|
|
3e7b41e712 | ||
|
|
5f18f35e02 | ||
|
|
af39e87703 | ||
|
|
ace25af0e8 | ||
|
|
8d78455414 | ||
|
|
fed16d7710 | ||
|
|
fcff3a2c8d | ||
|
|
803dd6f64e | ||
|
|
a1e258eb24 | ||
|
|
e9df698a1f | ||
|
|
bddcbf6999 | ||
|
|
be22e2551d | ||
|
|
4e01c7f13d | ||
|
|
7181813f12 | ||
|
|
6fc9f12c34 | ||
|
|
cc4e37fa40 | ||
|
|
ccadd4e41a | ||
|
|
a5caab62f8 | ||
|
|
2bff218806 | ||
|
|
95c30a2843 | ||
|
|
28efbcdb3d | ||
|
|
ca7952ab33 | ||
|
|
62693af196 | ||
|
|
5abee2512f | ||
|
|
c9a6155834 | ||
|
|
aad3ab903f | ||
|
|
4c76a898b6 | ||
|
|
d273148bc5 | ||
|
|
5314f5c67a | ||
|
|
22aab44d49 | ||
|
|
b819746165 | ||
|
|
73d33e2200 | ||
|
|
740bc3aa30 | ||
|
|
583b32f17a | ||
|
|
b7ab29473b | ||
|
|
ffc4f1408a | ||
|
|
c8b3066883 | ||
|
|
fb4f89b412 | ||
|
|
6bee6a0469 | ||
|
|
0c2ab9b231 | ||
|
|
03bef4c15d | ||
|
|
ba62ca7306 | ||
|
|
56a1530cee | ||
|
|
699cd5fc23 | ||
|
|
381c59d1e5 | ||
|
|
70f4dc9e10 | ||
|
|
0367ad31f1 | ||
|
|
5c6bcdbca6 | ||
|
|
400c0f05ad | ||
|
|
00df7c9b7b | ||
|
|
a272ed7daa | ||
|
|
b2e7a2e370 | ||
|
|
39bc70cbf0 | ||
|
|
682298b69f | ||
|
|
028a39ec25 | ||
|
|
3b104049b4 | ||
|
|
dd83a360b4 | ||
|
|
976c62d9c2 | ||
|
|
4cc9f12a03 | ||
|
|
0b5a751c56 | ||
|
|
5a59cd278c | ||
|
|
cdb05e5894 | ||
|
|
6c08b5caf3 | ||
|
|
d5b53f3712 | ||
|
|
80fbb2f0b2 | ||
|
|
b4f90decc7 | ||
|
|
61b324043a | ||
|
|
2ced921008 | ||
|
|
1e2fee0f33 | ||
|
|
ac36c9c406 | ||
|
|
f70c79aaf9 | ||
|
|
0839fa5757 | ||
|
|
60bc4ebcee | ||
|
|
65e239652d | ||
|
|
6b9015a928 | ||
|
|
a740c38ee6 | ||
|
|
603639126e | ||
|
|
043cfdb3f9 | ||
|
|
b0da4b2b2d | ||
|
|
5402859a30 | ||
|
|
2b10200101 | ||
|
|
55e8927ab7 | ||
|
|
d30fe61264 | ||
|
|
f7ea2d29e1 | ||
|
|
e6cfef5295 | ||
|
|
0dea9e6a2b | ||
|
|
ae80de26ec | ||
|
|
53bd2a0960 | ||
|
|
b55f5ff298 | ||
|
|
21048b51ae | ||
|
|
773fd09166 | ||
|
|
57532a290a | ||
|
|
740a35b018 | ||
|
|
6e995230a7 | ||
|
|
65a8b091b9 | ||
|
|
fa34908d82 | ||
|
|
b09eb1213c | ||
|
|
23ae8ab3b5 | ||
|
|
0bdb7e9e44 | ||
|
|
54e3cd7cb7 | ||
|
|
16ad07cfc9 | ||
|
|
dee0adcd8c | ||
|
|
acbf1226ab | ||
|
|
f002744d87 | ||
|
|
9efee7af21 | ||
|
|
9814b10496 | ||
|
|
978694b3c0 | ||
|
|
bc6f155f12 | ||
|
|
d494c2104b | ||
|
|
8035c6859f | ||
|
|
2f10295022 | ||
|
|
e5f32730a7 | ||
|
|
cd257b4d25 | ||
|
|
ce534baa75 | ||
|
|
2b420b8e66 | ||
|
|
35300abfb5 | ||
|
|
3d0ecc05ff | ||
|
|
bfb6ec8856 | ||
|
|
bf1d682a85 | ||
|
|
7d9326a147 | ||
|
|
7fd09009e7 | ||
|
|
9fa5e2dc1f | ||
|
|
15d4ee4d68 | ||
|
|
6ca6a52ae8 | ||
|
|
3d643aa4cb | ||
|
|
9739d23b6f | ||
|
|
c43acf7dac | ||
|
|
995c226893 | ||
|
|
8574bbb64f | ||
|
|
b2bb545947 | ||
|
|
bf8dae67de | ||
|
|
c6309da015 | ||
|
|
2e83a1010e | ||
|
|
d5efb31e3a | ||
|
|
b77798f885 | ||
|
|
5923c7c408 | ||
|
|
7dfb6fdc52 | ||
|
|
4e40b2ddf3 | ||
|
|
4e9abd41c0 | ||
|
|
7240b86d98 | ||
|
|
211853d519 | ||
|
|
f39589a8c1 | ||
|
|
e387971292 | ||
|
|
4fc1912ee8 | ||
|
|
31a704b675 | ||
|
|
c5c088300f | ||
|
|
ccea8e6eb5 | ||
|
|
ac60ed4559 | ||
|
|
8026263a27 | ||
|
|
6fa6abe6f0 | ||
|
|
e8d5bd7bfb | ||
|
|
2a03c1f1f4 | ||
|
|
0c6b92536e | ||
|
|
dddc1ec112 | ||
|
|
8b376874c0 | ||
|
|
0322660561 | ||
|
|
a7205ddf02 | ||
|
|
64b38487bc | ||
|
|
bc20850fba | ||
|
|
66048931a2 | ||
|
|
8444b6b3be | ||
|
|
baac26c5f6 | ||
|
|
56e9e15ac0 | ||
|
|
beb54acc2f | ||
|
|
d573423372 | ||
|
|
410bc211a5 | ||
|
|
e65c3f2f2b | ||
|
|
cf947415e8 | ||
|
|
c32a606a70 | ||
|
|
78c6059668 | ||
|
|
7c2adf636f | ||
|
|
d5ac8c7183 | ||
|
|
7a7fab0907 | ||
|
|
c758ae89f4 | ||
|
|
caea7910b4 | ||
|
|
6192685671 | ||
|
|
26eed30dbf | ||
|
|
20779dfece | ||
|
|
6bcfa436ea | ||
|
|
e62316105f | ||
|
|
9e318fc40d | ||
|
|
4b407d5213 | ||
|
|
841a22b2b2 | ||
|
|
840d8ab4fd | ||
|
|
2e3e58ed73 | ||
|
|
eb48f87667 | ||
|
|
a164c120d5 | ||
|
|
9dddd40dbe | ||
|
|
ad778636cf | ||
|
|
78360bc24a | ||
|
|
3480d9ac35 | ||
|
|
ae72bc3f99 | ||
|
|
c8bf36044b | ||
|
|
b05cb0d2ea | ||
|
|
fd1880f1ff | ||
|
|
70c5bd1875 | ||
|
|
00ac9ce961 | ||
|
|
1d455221e4 | ||
|
|
31b4eb7937 | ||
|
|
c88b46783b | ||
|
|
39edd22a9d | ||
|
|
afe25db0d3 | ||
|
|
f86a5af794 | ||
|
|
e6de4d014e | ||
|
|
b38df9eecd | ||
|
|
54abf84e96 | ||
|
|
66ebdfd61a | ||
|
|
4fe7c13d8e | ||
|
|
2578b380f9 | ||
|
|
cadf9f797f | ||
|
|
fd50e4e260 | ||
|
|
1cbec27b7f | ||
|
|
8d110c44f7 | ||
|
|
66a77db851 | ||
|
|
0505efbac1 | ||
|
|
99614f2e15 | ||
|
|
08e41244fc | ||
|
|
4e74b59796 | ||
|
|
2b6b268b4e | ||
|
|
09aacf011e | ||
|
|
9bea46adcb | ||
|
|
a10183628b | ||
|
|
7e0017d14a | ||
|
|
62e9a333c7 | ||
|
|
4838da48ef | ||
|
|
b5a43c416a | ||
|
|
c1297eadd4 | ||
|
|
06886fe6c2 | ||
|
|
137d1d181b | ||
|
|
97d0286a31 | ||
|
|
782dcffc62 | ||
|
|
40f7a7c593 | ||
|
|
44e5b2c2fd | ||
|
|
f844a8be5e | ||
|
|
449d8aca65 | ||
|
|
9b29f8c23a | ||
|
|
5e79581662 | ||
|
|
79a2952f94 | ||
|
|
8077d8dfeb | ||
|
|
d72ac9694e | ||
|
|
5e0bc17341 | ||
|
|
932aa1fd39 | ||
|
|
2c45e9fedd | ||
|
|
c1352d50c1 | ||
|
|
2499d29196 | ||
|
|
fbf1cbc76e | ||
|
|
719838de3b | ||
|
|
ba66c108fa | ||
|
|
5287bf5cac | ||
|
|
10740f12c4 | ||
|
|
3e6edb92c5 | ||
|
|
dc7b9414d9 | ||
|
|
8df8cb1eb6 | ||
|
|
e14ea9a240 | ||
|
|
57287a5303 | ||
|
|
febc8f774d | ||
|
|
e51042ed04 | ||
|
|
910c123887 | ||
|
|
e0899abaac | ||
|
|
9df1bb2ff2 | ||
|
|
7b987635f7 | ||
|
|
8c37cf16c0 | ||
|
|
c569c10740 | ||
|
|
325541642e | ||
|
|
97d91ec0f8 | ||
|
|
17db90d5ab | ||
|
|
e7a7bb1a7b | ||
|
|
b621806a7c | ||
|
|
7720a3f091 | ||
|
|
b22b02a0b6 | ||
|
|
d14088512b | ||
|
|
62527a91ac | ||
|
|
f9e4a97eb8 | ||
|
|
ff45be1f71 | ||
|
|
aaed2ed790 | ||
|
|
d9501de252 | ||
|
|
9fdcb08364 | ||
|
|
9f4f37bb51 | ||
|
|
49cf364352 | ||
|
|
b9a73cc23d | ||
|
|
357fd844d7 | ||
|
|
74a5522965 | ||
|
|
84dab18c2a | ||
|
|
9e90111b37 | ||
|
|
ffb1645f14 | ||
|
|
6448b217d5 | ||
|
|
1b84ab40ce | ||
|
|
af8d1ec6be | ||
|
|
04a4080768 | ||
|
|
942bf70582 | ||
|
|
b9f0ee2317 | ||
|
|
cb09bac246 | ||
|
|
109e4b2cf1 | ||
|
|
e4cf2978e6 | ||
|
|
17b74f20c9 | ||
|
|
ae11e31048 | ||
|
|
e455ce9c78 | ||
|
|
41df5cdd8b | ||
|
|
383225d7f4 | ||
|
|
a62c15ad1a | ||
|
|
5300742543 | ||
|
|
cd09a2f176 | ||
|
|
11ba46d140 | ||
|
|
e006377e64 | ||
|
|
786fa53334 | ||
|
|
9bc34e4406 | ||
|
|
c915af8dad | ||
|
|
98fbbc2864 | ||
|
|
d2049d63d6 | ||
|
|
63a12d4d40 | ||
|
|
9051f8275b | ||
|
|
a5f33bc244 | ||
|
|
b23d25217b | ||
|
|
1df6798934 | ||
|
|
9afff6d8a0 | ||
|
|
ec41efd860 | ||
|
|
580a431fbf | ||
|
|
c06d84e834 | ||
|
|
06a299d212 | ||
|
|
f90985a1f9 | ||
|
|
677beddf07 | ||
|
|
7154a7b3dc | ||
|
|
7de3d79d09 | ||
|
|
54a0265ef9 | ||
|
|
8f96acaec4 | ||
|
|
cea984cc2f | ||
|
|
fcf748e980 | ||
|
|
e58cb3c9cd | ||
|
|
3587a8ebd1 | ||
|
|
3193381b69 | ||
|
|
7a9ddfc2b5 | ||
|
|
447b2aa2c6 | ||
|
|
b3eaeea8a4 | ||
|
|
45b4c05867 | ||
|
|
49da66dcff | ||
|
|
bb9d5586f0 | ||
|
|
c5d22f4b27 | ||
|
|
e57ec11ed8 | ||
|
|
56acc82445 | ||
|
|
6e828d091f | ||
|
|
e1d8697331 | ||
|
|
90098c2006 | ||
|
|
b3a25fb9e8 | ||
|
|
f85ad4965b | ||
|
|
f5696b6fc0 | ||
|
|
c26555aca5 | ||
|
|
0accb467b5 | ||
|
|
3b34fd4750 | ||
|
|
abb216c055 | ||
|
|
1760dc7d35 | ||
|
|
034e7fd750 | ||
|
|
76c7b319b8 | ||
|
|
09010e95a2 | ||
|
|
2341d66192 | ||
|
|
21586b7710 | ||
|
|
b426ae1198 | ||
|
|
e9db9d65ac | ||
|
|
59dcbf4c0c | ||
|
|
a204d233f6 | ||
|
|
26cd84c88c | ||
|
|
5f77255893 | ||
|
|
8856a7aa34 | ||
|
|
30754433eb | ||
|
|
751ac19c4b | ||
|
|
1415e4b878 | ||
|
|
e56203faac | ||
|
|
64c997a4a2 | ||
|
|
391ee34a0f | ||
|
|
88de5047bc | ||
|
|
d020e809a1 | ||
|
|
8b2b8d41df | ||
|
|
40c33ac639 | ||
|
|
002e4b8d69 | ||
|
|
c060c379d3 | ||
|
|
4d13407a83 | ||
|
|
d737f550c7 | ||
|
|
5e8d5b9219 | ||
|
|
f98f21ffdf | ||
|
|
ec9e64ebfb | ||
|
|
39672970e2 | ||
|
|
5becf7980a | ||
|
|
c7c84ad39b | ||
|
|
8773117493 | ||
|
|
bb697e1bd9 | ||
|
|
e1a9aa7d03 | ||
|
|
312773d054 | ||
|
|
1ee48a978f | ||
|
|
5ddb6b77e2 | ||
|
|
e0284886b5 | ||
|
|
44c07c2034 | ||
|
|
f6b38081fc | ||
|
|
c570509628 | ||
|
|
e98ff1d6d6 | ||
|
|
0f54663789 | ||
|
|
f91d935708 | ||
|
|
fb8b60fccc | ||
|
|
ad8506cc30 | ||
|
|
d6f88acb8d | ||
|
|
333fc4c387 | ||
|
|
5f9214e9a2 | ||
|
|
f974dcb647 | ||
|
|
2cb1c544f5 | ||
|
|
644e948489 | ||
|
|
d12d2648b7 | ||
|
|
0ee3c8e135 | ||
|
|
bc959a8c3d | ||
|
|
69781d822a | ||
|
|
611fabcd01 | ||
|
|
24ab285066 | ||
|
|
ee6ec14bf8 | ||
|
|
f9d67e2cd2 | ||
|
|
a72516fdcc | ||
|
|
ebfc6aab6b | ||
|
|
9c20edd3d0 | ||
|
|
b02b0ccd7c | ||
|
|
1bcf7ec29c | ||
|
|
e54b4f58df | ||
|
|
30540729df | ||
|
|
77b80dc53e | ||
|
|
861d3dfa0f | ||
|
|
e0235aedff | ||
|
|
8411382c42 | ||
|
|
f8078a6894 | ||
|
|
f66e8c8b3a | ||
|
|
acc269e702 | ||
|
|
5bcda12ca9 | ||
|
|
8de87c8772 | ||
|
|
b956623234 | ||
|
|
6e615f85eb | ||
|
|
b70b469201 | ||
|
|
c4b706f8ad | ||
|
|
9d971003d5 | ||
|
|
c322817cb1 | ||
|
|
0c4c93784d | ||
|
|
4cae09a4e9 | ||
|
|
c775867db4 | ||
|
|
8672fb2792 | ||
|
|
48c47c6fcf | ||
|
|
38904a6213 | ||
|
|
bdadfa1c26 | ||
|
|
e38142399e | ||
|
|
5cbbfedcce | ||
|
|
bc97575760 | ||
|
|
afd56a7f6f | ||
|
|
0844abd7e5 | ||
|
|
3625363fcf | ||
|
|
9692ae5617 | ||
|
|
c01edb192f | ||
|
|
acbf9153f4 | ||
|
|
b6cd4638b9 | ||
|
|
683d97dc14 | ||
|
|
ad77dc0bea | ||
|
|
587622af81 | ||
|
|
eaf27c1e12 | ||
|
|
1c78cd4c31 | ||
|
|
d1ab867afc | ||
|
|
522a385523 | ||
|
|
40dd620f90 | ||
|
|
7dfc19e588 | ||
|
|
0b002e8d11 | ||
|
|
d2e481719c | ||
|
|
7e48746944 | ||
|
|
f481c704c9 | ||
|
|
6e5b991406 | ||
|
|
e07ead53a9 | ||
|
|
e6e88e132b | ||
|
|
8778848301 | ||
|
|
5fbef7beb5 | ||
|
|
387a3bc281 | ||
|
|
11ccb951aa | ||
|
|
3a6df2eab0 | ||
|
|
c5e3bc70b1 | ||
|
|
9c46b8fd75 | ||
|
|
d5dc3a1361 | ||
|
|
f0e8d8e98c | ||
|
|
589fd22a63 | ||
|
|
83821453a0 | ||
|
|
d335b6393e | ||
|
|
6240d60003 | ||
|
|
4519c4fe3d | ||
|
|
e969b2f31f | ||
|
|
44ae9093f9 | ||
|
|
fcd3bdf297 | ||
|
|
cbb2f43047 | ||
|
|
5e74869dbc | ||
|
|
98cac153e6 | ||
|
|
d076aac421 | ||
|
|
b51a603aa9 | ||
|
|
2fe520ad46 | ||
|
|
c8846329f3 | ||
|
|
08f2db05a9 | ||
|
|
5427b488c3 | ||
|
|
ec24f03324 | ||
|
|
4ef16cfd8d | ||
|
|
177c7cbf03 | ||
|
|
8025717658 | ||
|
|
275d8d9f0b | ||
|
|
30df7d4c9e | ||
|
|
019ef1398e | ||
|
|
4a6f517e91 | ||
|
|
d560cb4c9e | ||
|
|
ba16ae6568 | ||
|
|
3b2c40d49e | ||
|
|
9894dbef87 | ||
|
|
dd447f24d2 | ||
|
|
3a250723d7 | ||
|
|
e0797e5d14 | ||
|
|
d0f1c18a2f | ||
|
|
e6d811ea7c | ||
|
|
bb6eb246e8 | ||
|
|
0e666f0316 | ||
|
|
0811938466 | ||
|
|
466b6a25cd | ||
|
|
15a564dcfe | ||
|
|
f85721fbf5 | ||
|
|
3b366f91fc | ||
|
|
418f2b2c3f | ||
|
|
8fa91736b6 | ||
|
|
a18c533603 | ||
|
|
a9b394401b | ||
|
|
c257e5cb77 | ||
|
|
93863ece0d | ||
|
|
29918fb454 | ||
|
|
412cf115a5 | ||
|
|
8dab5d3800 | ||
|
|
2cd3bd7588 | ||
|
|
0e0fcabc04 | ||
|
|
e80d21e852 | ||
|
|
a68343a306 | ||
|
|
d594b1447f | ||
|
|
1ca9b0bd62 | ||
|
|
1c0b2b55b6 | ||
|
|
41ca15120d | ||
|
|
49b1706495 | ||
|
|
daf22c762f | ||
|
|
3529724bdc | ||
|
|
56a86b6127 | ||
|
|
7e6f4453ad | ||
|
|
84a647e712 | ||
|
|
d10f29bbc6 | ||
|
|
41edc3a1ec | ||
|
|
3f080e04b9 | ||
|
|
4386ef1e56 | ||
|
|
df1dd0eec7 | ||
|
|
3954777d20 | ||
|
|
b52645f77a | ||
|
|
65e6f96e59 | ||
|
|
24c35de330 | ||
|
|
d052f409b6 | ||
|
|
f9eb6ed85e | ||
|
|
11ade8c3df | ||
|
|
fe88b7551c | ||
|
|
bddfadaefa | ||
|
|
40b1be075c | ||
|
|
680bc4658f | ||
|
|
870ed00e3c | ||
|
|
1f3b24d20f | ||
|
|
bc19f66812 | ||
|
|
9915cc4492 | ||
|
|
ad4585989a | ||
|
|
ea5616002a | ||
|
|
1f8a781dc2 | ||
|
|
fd63cf0086 | ||
|
|
60bdca8716 | ||
|
|
a2971aa03b | ||
|
|
05a3acb229 | ||
|
|
47257baba9 | ||
|
|
906a0ba189 | ||
|
|
69b02f3224 | ||
|
|
a7d0ad5f43 | ||
|
|
59f07c868d | ||
|
|
4517d80704 | ||
|
|
9bca4aa53f | ||
|
|
4c4539509c | ||
|
|
af3cebb266 | ||
|
|
d22528ca46 | ||
|
|
67267c05fd | ||
|
|
d23ab88add | ||
|
|
1d78d675f7 | ||
|
|
3079ad37ce | ||
|
|
c7b7d56229 | ||
|
|
c97b97c677 | ||
|
|
96a62551b2 | ||
|
|
300c9b9ccb | ||
|
|
342085db40 | ||
|
|
862f76fea2 | ||
|
|
3cce33415d | ||
|
|
d09455f78e | ||
|
|
e947881aca | ||
|
|
077c9ea00d | ||
|
|
f8af4597f2 | ||
|
|
32dc96ae93 | ||
|
|
153e83ee3e | ||
|
|
6402dfd9ea | ||
|
|
98bafb1f26 | ||
|
|
6d92937892 | ||
|
|
28d31d0cf5 | ||
|
|
07fd509e74 | ||
|
|
37a5dc7abe | ||
|
|
8604097ada | ||
|
|
ea587d97c8 | ||
|
|
fb272b07aa | ||
|
|
7067a8e411 | ||
|
|
50800b1d44 | ||
|
|
dcf6f94d77 | ||
|
|
8131995006 | ||
|
|
7de1634a36 | ||
|
|
b252781f8d | ||
|
|
023cb12079 | ||
|
|
b5b87f5272 | ||
|
|
f287bd4d1d | ||
|
|
222a154290 | ||
|
|
9b8af2455f | ||
|
|
493c934463 | ||
|
|
83f1d74a76 | ||
|
|
e7c8d1c1c1 | ||
|
|
305578e7e6 | ||
|
|
651f0aa15c | ||
|
|
51e7cd725e | ||
|
|
32473af7c2 | ||
|
|
b5fc6e3d12 | ||
|
|
dc65bdb913 | ||
|
|
d4ef1a7302 | ||
|
|
f8c01b2168 | ||
|
|
d7e2b18247 | ||
|
|
12a275918e | ||
|
|
eda8bff10b | ||
|
|
76105de4c7 | ||
|
|
eed56cdf55 | ||
|
|
da7adc1068 | ||
|
|
f1ff947697 | ||
|
|
9250853854 | ||
|
|
d1b634511d | ||
|
|
cf7b7191f8 | ||
|
|
0dcd8227da | ||
|
|
089eb9b604 | ||
|
|
f04a9c4f3e | ||
|
|
e2d15c8764 | ||
|
|
9a25fb63ad | ||
|
|
0e48076d25 | ||
|
|
a956de3df7 | ||
|
|
455a047242 | ||
|
|
27bb22de09 | ||
|
|
285c70f24f | ||
|
|
c7c1691d75 | ||
|
|
6c7e70f78a | ||
|
|
97338b016d | ||
|
|
473c8e0a15 | ||
|
|
090e59e99a | ||
|
|
5712bc11d2 | ||
|
|
323339b0b2 | ||
|
|
c001897590 | ||
|
|
8fd3e5070d | ||
|
|
01e739d524 | ||
|
|
16a184a92f | ||
|
|
1a1c0beabc | ||
|
|
ff0b022357 | ||
|
|
c0e6e54496 | ||
|
|
16bc9cb203 | ||
|
|
196a325f7f | ||
|
|
da70dc0565 | ||
|
|
f7a8b764d0 | ||
|
|
16949ffb21 | ||
|
|
de0dfb9265 | ||
|
|
9cde49f5f8 | ||
|
|
644bcfba27 | ||
|
|
a4d393ae28 | ||
|
|
a7a5eed0f2 | ||
|
|
80a6e6809c | ||
|
|
861efa5e75 | ||
|
|
6c8f85afe9 | ||
|
|
6b1a6c054e | ||
|
|
f2502ac431 | ||
|
|
76151deba0 | ||
|
|
4a6790f0aa | ||
|
|
95298202a3 | ||
|
|
1c30d14910 | ||
|
|
8aec1583df | ||
|
|
04036cf63a | ||
|
|
68aae70b44 | ||
|
|
0907eadb55 | ||
|
|
77818d669f | ||
|
|
70aee177c3 | ||
|
|
5e417affa5 | ||
|
|
783ee4328a | ||
|
|
caa857f318 | ||
|
|
20a1b77b58 | ||
|
|
960900dafa | ||
|
|
9bf287a1ac | ||
|
|
f886b0eed1 | ||
|
|
1f1f2d2e90 | ||
|
|
8ad619ebc1 | ||
|
|
85f1a31be3 | ||
|
|
4a57d050f6 | ||
|
|
3a1e32f5aa | ||
|
|
b407221ce6 | ||
|
|
96b92aabae | ||
|
|
d87dab2e25 | ||
|
|
b2f9d937e1 | ||
|
|
c9ac954bfd | ||
|
|
dea2da52f9 | ||
|
|
487a97c31e | ||
|
|
c90bdbfb93 | ||
|
|
598ed66a3b | ||
|
|
59b0b79a32 | ||
|
|
0172606747 | ||
|
|
65c2a0fd7c | ||
|
|
68926cef20 | ||
|
|
447ca6cabb | ||
|
|
0b0239bcf1 | ||
|
|
e021d5a56b | ||
|
|
36abf8450e | ||
|
|
d67b4a0b35 | ||
|
|
e4a376acdd | ||
|
|
8cfdb2fbf2 | ||
|
|
886b2d6b42 | ||
|
|
2193281c6a | ||
|
|
eb7ee420fc | ||
|
|
5a1d953278 | ||
|
|
67c291e15a | ||
|
|
3722bc9ae6 | ||
|
|
1fb0944e2b | ||
|
|
61c7ee0958 | ||
|
|
9c5e5b5e10 | ||
|
|
b3e11d47b7 | ||
|
|
31419fef03 | ||
|
|
b2e3686f59 | ||
|
|
9b90ae0c81 | ||
|
|
39beb4912b | ||
|
|
98d7bc980c | ||
|
|
2ff449b241 | ||
|
|
83f6ae4e54 | ||
|
|
d26d29e9a6 | ||
|
|
d0e8a0c4e5 | ||
|
|
35344b27c5 | ||
|
|
6b6b7f90c8 | ||
|
|
eeb3242573 | ||
|
|
cd5c295484 | ||
|
|
4ffe6dfc2b | ||
|
|
072c1c521a | ||
|
|
314fca3f89 | ||
|
|
dae5a06734 | ||
|
|
4b62236638 | ||
|
|
5117f9b30d | ||
|
|
818ffcab29 | ||
|
|
efe2ceebe0 | ||
|
|
67f9c07b44 | ||
|
|
c5978f5845 | ||
|
|
929cdb971a | ||
|
|
1317fa3e2a | ||
|
|
8a65850f1a | ||
|
|
5c1eceb8a9 | ||
|
|
2db289a658 | ||
|
|
201844a45b | ||
|
|
93a3bbd849 | ||
|
|
86dddd81c7 | ||
|
|
105abeba06 | ||
|
|
b3a6919ea0 |
@@ -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
|
||||||
@@ -1,63 +1 @@
|
|||||||
###############################################################################
|
* text=auto
|
||||||
# Set default behavior to automatically normalize line endings.
|
|
||||||
###############################################################################
|
|
||||||
* text=auto
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set default behavior for command prompt diff.
|
|
||||||
#
|
|
||||||
# This is need for earlier builds of msysgit that does not have it on by
|
|
||||||
# default for csharp files.
|
|
||||||
# Note: This is only used by command line
|
|
||||||
###############################################################################
|
|
||||||
#*.cs diff=csharp
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set the merge driver for project and solution files
|
|
||||||
#
|
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
|
||||||
# these files as binary and thus will always conflict and require user
|
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
|
||||||
###############################################################################
|
|
||||||
#*.sln merge=binary
|
|
||||||
#*.csproj merge=binary
|
|
||||||
#*.vbproj merge=binary
|
|
||||||
#*.vcxproj merge=binary
|
|
||||||
#*.vcproj merge=binary
|
|
||||||
#*.dbproj merge=binary
|
|
||||||
#*.fsproj merge=binary
|
|
||||||
#*.lsproj merge=binary
|
|
||||||
#*.wixproj merge=binary
|
|
||||||
#*.modelproj merge=binary
|
|
||||||
#*.sqlproj merge=binary
|
|
||||||
#*.wwaproj merge=binary
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# behavior for image files
|
|
||||||
#
|
|
||||||
# image files are treated as binary by default.
|
|
||||||
###############################################################################
|
|
||||||
#*.jpg binary
|
|
||||||
#*.png binary
|
|
||||||
#*.gif binary
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# diff behavior for common document formats
|
|
||||||
#
|
|
||||||
# Convert binary document formats to text before diffing them. This feature
|
|
||||||
# is only available from the command line. Turn it on by uncommenting the
|
|
||||||
# entries below.
|
|
||||||
###############################################################################
|
|
||||||
#*.doc diff=astextplain
|
|
||||||
#*.DOC diff=astextplain
|
|
||||||
#*.docx diff=astextplain
|
|
||||||
#*.DOCX diff=astextplain
|
|
||||||
#*.dot diff=astextplain
|
|
||||||
#*.DOT diff=astextplain
|
|
||||||
#*.pdf diff=astextplain
|
|
||||||
#*.PDF diff=astextplain
|
|
||||||
#*.rtf diff=astextplain
|
|
||||||
#*.RTF diff=astextplain
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve.
|
||||||
|
title: ''
|
||||||
|
labels: 'bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
Before opening a bug make sure that the following conditions are met.
|
||||||
|
<!-- Remove this chapter when all conditions are met. -->
|
||||||
|
|
||||||
|
1. Performance issues are also appearing in RELEASE mode of your application.
|
||||||
|
2. An increased memory consumption or high CPU load also happens when your application runs in RELEASE mode AND logging is DISABLED.
|
||||||
|
3. Client issues with not received messages, connection drops etc. can be reproduced via another client application like "MQTTnetApp" (https://github.com/chkr1011/MQTTnetApp) or similar.
|
||||||
|
4. The bug also appears in the VERY LATEST version of this library. There is no support for older version (due to limited resources) but pull requests for older versions are welcome.
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
### Which component is your bug related to?
|
||||||
|
<!-- Remove the items which don't apply from the following list. -->
|
||||||
|
- Client
|
||||||
|
- ManagedClient
|
||||||
|
- RpcClient
|
||||||
|
- Server
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
**Ideally a Unit Test (which shows the error) is provided so that the behavior can be reproduced easily.**
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
\\ Put your code here.
|
||||||
|
```
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
- Server
|
||||||
|
- Generic
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
- 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 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
VERSION: "4.1.3.${{github.run_number}}"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: windows-2022
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup Windows SDK
|
||||||
|
uses: GuillaumeFalourd/setup-windows10-sdk-action@v1
|
||||||
|
with:
|
||||||
|
sdk-version: 18362
|
||||||
|
|
||||||
|
- name: Setup .NET SDK
|
||||||
|
uses: actions/setup-dotnet@v1.9.0
|
||||||
|
with:
|
||||||
|
dotnet-version: |
|
||||||
|
3.1.x
|
||||||
|
6.0.x
|
||||||
|
|
||||||
|
- name: Setup MSBuild
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Signing Certificate
|
||||||
|
run: |
|
||||||
|
$secret = '${{ secrets.SNC_BASE64 }}'
|
||||||
|
$decoded = [System.Convert]::FromBase64CharArray($secret, 0, $secret.Length)
|
||||||
|
Set-Content -Path ${{ github.workspace }}\certificate.snk -Value $decoded -AsByteStream
|
||||||
|
|
||||||
|
- name: Restore nuget packages
|
||||||
|
run: msbuild MQTTnet.sln /t:Restore /p:Configuration="Release" /verbosity:m
|
||||||
|
|
||||||
|
- name: Build solution
|
||||||
|
run: msbuild MQTTnet.sln /t:Build /p:Configuration="Release" /verbosity:m /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.VERSION }} /p:PackageVersion=${{ env.VERSION }} /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=${{ github.workspace }}\certificate.snk
|
||||||
|
|
||||||
|
- name: Collect nuget Packages
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: nuget Packages
|
||||||
|
path: |
|
||||||
|
**\*.nupkg
|
||||||
|
**\*.snupkg
|
||||||
|
|
||||||
|
- name: Setup VSTest
|
||||||
|
uses: darenm/Setup-VSTest@v1
|
||||||
|
|
||||||
|
- name: Core Tests
|
||||||
|
run: vstest.console.exe Source\MQTTnet.Tests\bin\Release\net6.0\MQTTnet.Tests.dll
|
||||||
|
|
||||||
|
- name: ASP.NET Tests
|
||||||
|
run: vstest.console.exe Source\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp3.1\MQTTnet.AspNetCore.Tests.dll
|
||||||
|
|
||||||
|
- name: Publish MyGet nugets
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
|
run: dotnet nuget push **/*.nupkg -k ${{ secrets.MYGET_API_KEY }} -s https://www.myget.org/F/mqttnet/api/v3/index.json --skip-duplicate
|
||||||
|
|
||||||
|
# - name: Publish nugets
|
||||||
|
# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
|
# run: dotnet nuget push **/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.suo
|
*.suo
|
||||||
@@ -15,12 +17,12 @@
|
|||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
[Xx]64/
|
x64/
|
||||||
[Xx]86/
|
x86/
|
||||||
[Bb]uild/
|
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
@@ -40,9 +42,11 @@ TestResult.xml
|
|||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
dlldata.c
|
dlldata.c
|
||||||
|
|
||||||
# DNX
|
# .NET Core
|
||||||
project.lock.json
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
**/Properties/launchSettings.json
|
||||||
|
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
@@ -81,6 +85,7 @@ ipch/
|
|||||||
*.sdf
|
*.sdf
|
||||||
*.cachefile
|
*.cachefile
|
||||||
*.VC.db
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
@@ -108,6 +113,10 @@ _TeamCity*
|
|||||||
# DotCover is a Code Coverage Tool
|
# DotCover is a Code Coverage Tool
|
||||||
*.dotCover
|
*.dotCover
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
@@ -139,13 +148,16 @@ publish/
|
|||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.[Pp]ublish.xml
|
*.[Pp]ublish.xml
|
||||||
*.azurePubxml
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
# TODO: Un-comment the next line if you do not want to checkin
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
# your web deploy settings because they may include unencrypted
|
*.pubxml
|
||||||
# passwords
|
|
||||||
#*.pubxml
|
|
||||||
*.publishproj
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
@@ -154,7 +166,7 @@ publish/
|
|||||||
!**/packages/build/
|
!**/packages/build/
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
#!**/packages/repositories.config
|
#!**/packages/repositories.config
|
||||||
# NuGet v3's project.json files produces more ignoreable files
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
@@ -166,12 +178,11 @@ csx/
|
|||||||
ecf/
|
ecf/
|
||||||
rcf/
|
rcf/
|
||||||
|
|
||||||
# Microsoft Azure ApplicationInsights config file
|
# Windows Store app package directories and files
|
||||||
ApplicationInsights.config
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
|
||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
@@ -181,16 +192,19 @@ BundleArtifacts/
|
|||||||
|
|
||||||
# Others
|
# Others
|
||||||
ClientBin/
|
ClientBin/
|
||||||
[Ss]tyle[Cc]op.*
|
|
||||||
~$*
|
~$*
|
||||||
*~
|
*~
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
*.pfx
|
*.jfm
|
||||||
|
# *.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
node_modules/
|
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
# RIA/Silverlight projects
|
||||||
Generated_Code/
|
Generated_Code/
|
||||||
|
|
||||||
@@ -205,6 +219,7 @@ UpgradeLog*.htm
|
|||||||
# SQL Server files
|
# SQL Server files
|
||||||
*.mdf
|
*.mdf
|
||||||
*.ldf
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
# Business Intelligence projects
|
# Business Intelligence projects
|
||||||
*.rdl.data
|
*.rdl.data
|
||||||
@@ -219,6 +234,11 @@ FakesAssemblies/
|
|||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
.ntvs_analysis.dat
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
/*/**/package-lock.json
|
||||||
|
|
||||||
|
# Typescript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
# Visual Studio 6 build log
|
||||||
*.plg
|
*.plg
|
||||||
@@ -226,6 +246,9 @@ FakesAssemblies/
|
|||||||
# Visual Studio 6 workspace options file
|
# Visual Studio 6 workspace options file
|
||||||
*.opt
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
# Visual Studio LightSwitch build output
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
@@ -234,13 +257,42 @@ FakesAssemblies/
|
|||||||
**/*.Server/ModelManifest.xml
|
**/*.Server/ModelManifest.xml
|
||||||
_Pvt_Extensions
|
_Pvt_Extensions
|
||||||
|
|
||||||
# LightSwitch generated files
|
|
||||||
GeneratedArtifacts/
|
|
||||||
ModelManifest.xml
|
|
||||||
|
|
||||||
# Paket dependency manager
|
# Paket dependency manager
|
||||||
.paket/paket.exe
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
.fake/
|
.fake/
|
||||||
nuget.exe
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
*.js
|
||||||
|
*.map
|
||||||
|
|
||||||
|
/Tests/MQTTnet.TestApp.NetCore/RetainedMessages.json
|
||||||
|
|
||||||
|
Build/NuGet/
|
||||||
|
|
||||||
|
Build/nuget.exe
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
This project has adopted the code of conduct defined by the Contributor Covenant
|
||||||
|
to clarify expected behavior in our community.
|
||||||
|
|
||||||
|
For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
|
||||||
<Authors>Christian Kratky</Authors>
|
|
||||||
<Company>Christian Kratky</Company>
|
|
||||||
<Product>MQTTnet</Product>
|
|
||||||
<Description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</Description>
|
|
||||||
<Copyright>Copyright © Christian Kratky 2016-2017</Copyright>
|
|
||||||
<Version>2.1.1.0</Version>
|
|
||||||
<AssemblyVersion>2.1.1.0</AssemblyVersion>
|
|
||||||
<FileVersion>2.1.1.0</FileVersion>
|
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
|
||||||
<AssemblyName>MQTTnet</AssemblyName>
|
|
||||||
<RootNamespace>MQTTnet</RootNamespace>
|
|
||||||
<PackageId>MQTTnet.NetCore</PackageId>
|
|
||||||
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
|
|
||||||
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
|
|
||||||
<PackageTags>MQTT MQTTClient MQTTServer MQTTBroker Broker</PackageTags>
|
|
||||||
<PackageIconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</PackageIconUrl>
|
|
||||||
<PackageLicenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</PackageLicenseUrl>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|AnyCPU'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x64'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttClientFactory
|
|
||||||
{
|
|
||||||
public MqttClient CreateMqttClient(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
|
|
||||||
{
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
private Socket _socket;
|
|
||||||
|
|
||||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
|
||||||
|
|
||||||
public void Start(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (_socket != null) throw new InvalidOperationException("Server is already started.");
|
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
|
|
||||||
_socket.Listen(options.ConnectionBacklog);
|
|
||||||
|
|
||||||
Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_cancellationTokenSource?.Dispose();
|
|
||||||
_cancellationTokenSource = null;
|
|
||||||
|
|
||||||
_socket?.Dispose();
|
|
||||||
_socket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
var clientSocket = await _socket.AcceptAsync();
|
|
||||||
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket), new DefaultMqttV311PacketSerializer());
|
|
||||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttServerFactory
|
|
||||||
{
|
|
||||||
public MqttServer CreateMqttServer(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttServer(options, new MqttServerAdapter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
|
||||||
{
|
|
||||||
private readonly Socket _socket;
|
|
||||||
|
|
||||||
public MqttTcpChannel()
|
|
||||||
{
|
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttTcpChannel(Socket socket)
|
|
||||||
{
|
|
||||||
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _socket.ConnectAsync(options.Server, options.Port);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_socket.Dispose();
|
|
||||||
await Task.FromResult(0);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _socket.SendAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ReadAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var buffer2 = new ArraySegment<byte>(buffer);
|
|
||||||
await _socket.ReceiveAsync(buffer2, SocketFlags.None);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_socket?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>MQTTnet</RootNamespace>
|
|
||||||
<AssemblyName>MQTTnet</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
|
|
||||||
<OutputPath>bin\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
|
|
||||||
<OutputPath>bin\x86\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
|
|
||||||
<OutputPath>bin\x64\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="MqttClientFactory.cs" />
|
|
||||||
<Compile Include="MqttServerAdapter.cs" />
|
|
||||||
<Compile Include="MqttServerFactory.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="MqttTcpChannel.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
|
|
||||||
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
|
|
||||||
<Name>MQTTnet.Core</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttClientFactory
|
|
||||||
{
|
|
||||||
public MqttClient CreateMqttClient(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
|
|
||||||
{
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
private Socket _socket;
|
|
||||||
|
|
||||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
|
||||||
|
|
||||||
public void Start(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (_socket != null) throw new InvalidOperationException("Server is already started.");
|
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
|
|
||||||
_socket.Listen(options.ConnectionBacklog);
|
|
||||||
|
|
||||||
Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_cancellationTokenSource?.Dispose();
|
|
||||||
_cancellationTokenSource = null;
|
|
||||||
|
|
||||||
_socket?.Dispose();
|
|
||||||
_socket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
var clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, _socket.EndAccept, null);
|
|
||||||
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket), new DefaultMqttV311PacketSerializer());
|
|
||||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttServerFactory
|
|
||||||
{
|
|
||||||
public MqttServer CreateMqttServer(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttServer(options, new MqttServerAdapter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
|
||||||
{
|
|
||||||
private readonly Socket _socket;
|
|
||||||
|
|
||||||
public MqttTcpChannel()
|
|
||||||
{
|
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttTcpChannel(Socket socket)
|
|
||||||
{
|
|
||||||
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.Port, null);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Factory.FromAsync(
|
|
||||||
// ReSharper disable once AssignNullToNotNullAttribute
|
|
||||||
_socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null),
|
|
||||||
_socket.EndSend);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ReadAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Factory.FromAsync(
|
|
||||||
// ReSharper disable once AssignNullToNotNullAttribute
|
|
||||||
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null),
|
|
||||||
_socket.EndReceive);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_socket?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("MQTTnet")]
|
|
||||||
[assembly: AssemblyDescription("MQTTnet for .NET Framework")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("Christian Kratky")]
|
|
||||||
[assembly: AssemblyProduct("MQTTnet")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Christian Kratky 2016-2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
[assembly: Guid("a480ef90-0eaa-4d9a-b271-47a9c47f6f7d")]
|
|
||||||
[assembly: AssemblyVersion("2.1.1.0")]
|
|
||||||
[assembly: AssemblyFileVersion("2.1.1.0")]
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{BD60C727-D8E8-40C3-B8E3-C95A864AE611}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>MQTTnet</RootNamespace>
|
|
||||||
<AssemblyName>MQTTnet</AssemblyName>
|
|
||||||
<DefaultLanguage>en-US</DefaultLanguage>
|
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
|
||||||
<TargetPlatformVersion>10.0.14393.0</TargetPlatformVersion>
|
|
||||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
|
||||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<DocumentationFile>bin\x86\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\ARM\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<OutputPath>bin\ARM\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<DocumentationFile>bin\ARM\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<GenerateLibraryLayout>false</GenerateLibraryLayout>
|
|
||||||
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
|
|
||||||
<None Include="project.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="MqttClientFactory.cs" />
|
|
||||||
<Compile Include="MqttServerAdapter.cs" />
|
|
||||||
<Compile Include="MqttServerFactory.cs" />
|
|
||||||
<Compile Include="MqttTcpChannel.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<EmbeddedResource Include="Properties\MQTTnet.Universal.rd.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
|
|
||||||
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
|
|
||||||
<Name>MQTTnet.Core</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
|
||||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
|
|
||||||
<OutputPath>bin\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoStdLib>true</NoStdLib>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
|
|
||||||
<OutputPath>bin\x86\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<DocumentationFile>bin\x86\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<NoStdLib>true</NoStdLib>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|ARM'">
|
|
||||||
<OutputPath>bin\ARM\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<DocumentationFile>bin\ARM\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<NoStdLib>true</NoStdLib>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
|
|
||||||
<OutputPath>bin\x64\Any CPU\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<NoStdLib>true</NoStdLib>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttClientFactory
|
|
||||||
{
|
|
||||||
public MqttClient CreateMqttClient(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using Windows.Networking.Sockets;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
|
|
||||||
{
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
private StreamSocketListener _socket;
|
|
||||||
|
|
||||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
|
||||||
|
|
||||||
public void Start(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (_socket != null) throw new InvalidOperationException("Server is already started.");
|
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
_socket = new StreamSocketListener();
|
|
||||||
_socket.BindServiceNameAsync(options.Port.ToString()).AsTask().Wait();
|
|
||||||
_socket.ConnectionReceived += ConnectionReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
|
|
||||||
{
|
|
||||||
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new DefaultMqttV311PacketSerializer());
|
|
||||||
|
|
||||||
var identifier = $"{args.Socket.Information.RemoteAddress}:{args.Socket.Information.RemotePort}";
|
|
||||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(identifier, clientAdapter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_cancellationTokenSource?.Dispose();
|
|
||||||
|
|
||||||
if (_socket != null)
|
|
||||||
{
|
|
||||||
_socket.ConnectionReceived -= ConnectionReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
_socket?.Dispose();
|
|
||||||
_socket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public class MqttServerFactory
|
|
||||||
{
|
|
||||||
public MqttServer CreateMqttServer(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
return new MqttServer(options, new MqttServerAdapter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Windows.Networking;
|
|
||||||
using Windows.Networking.Sockets;
|
|
||||||
using Windows.Storage.Streams;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using Buffer = Windows.Storage.Streams.Buffer;
|
|
||||||
|
|
||||||
namespace MQTTnet
|
|
||||||
{
|
|
||||||
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
|
||||||
{
|
|
||||||
private readonly StreamSocket _socket;
|
|
||||||
|
|
||||||
public MqttTcpChannel()
|
|
||||||
{
|
|
||||||
_socket = new StreamSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttTcpChannel(StreamSocket socket)
|
|
||||||
{
|
|
||||||
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
await _socket.ConnectAsync(new HostName(options.Server), options.Port.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
await _socket.CancelIOAsync();
|
|
||||||
_socket.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
|
|
||||||
|
|
||||||
await _socket.OutputStream.WriteAsync(buffer.AsBuffer());
|
|
||||||
await _socket.OutputStream.FlushAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ReadAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
var buffer2 = new Buffer((uint)buffer.Length);
|
|
||||||
await _socket.InputStream.ReadAsync(buffer2, (uint)buffer.Length, InputStreamOptions.None);
|
|
||||||
|
|
||||||
var array2 = buffer2.ToArray();
|
|
||||||
Array.Copy(array2, buffer, array2.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_socket?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("MQTTnet")]
|
|
||||||
[assembly: AssemblyDescription("MQTTnet for Universal Windows")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("Christian Kratky")]
|
|
||||||
[assembly: AssemblyProduct("MQTTnet")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Christian Kratky 2016-2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
[assembly: AssemblyVersion("2.1.1.0")]
|
|
||||||
[assembly: AssemblyFileVersion("2.1.1.0")]
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
|
||||||
<Library Name="MQTTnet.Universal">
|
|
||||||
</Library>
|
|
||||||
</Directives>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"uap10.0": {},
|
|
||||||
"netstandard1.1": {}
|
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"win10-arm": {},
|
|
||||||
"win10-arm-aot": {},
|
|
||||||
"win10-x86": {},
|
|
||||||
"win10-x86-aot": {},
|
|
||||||
"win10-x64": {},
|
|
||||||
"win10-x64-aot": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 2.3 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 |
|
After Width: | Height: | Size: 4.0 KiB |
@@ -1,6 +1,7 @@
|
|||||||
MIT License
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2017 Christian
|
Copyright (c) .NET Foundation and Contributors
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
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,18 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Adapter
|
|
||||||
{
|
|
||||||
public interface IMqttCommunicationAdapter
|
|
||||||
{
|
|
||||||
Task ConnectAsync(MqttClientOptions options, TimeSpan timeout);
|
|
||||||
|
|
||||||
Task DisconnectAsync();
|
|
||||||
|
|
||||||
Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout);
|
|
||||||
|
|
||||||
Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Adapter
|
|
||||||
{
|
|
||||||
public interface IMqttServerAdapter
|
|
||||||
{
|
|
||||||
event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
|
||||||
|
|
||||||
void Start(MqttServerOptions options);
|
|
||||||
|
|
||||||
void Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Adapter
|
|
||||||
{
|
|
||||||
public class MqttChannelCommunicationAdapter : IMqttCommunicationAdapter
|
|
||||||
{
|
|
||||||
private readonly IMqttPacketSerializer _serializer;
|
|
||||||
private readonly IMqttCommunicationChannel _channel;
|
|
||||||
|
|
||||||
public MqttChannelCommunicationAdapter(IMqttCommunicationChannel channel, IMqttPacketSerializer serializer)
|
|
||||||
{
|
|
||||||
_channel = channel ?? throw new ArgumentNullException(nameof(channel));
|
|
||||||
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
var task = _channel.ConnectAsync(options);
|
|
||||||
if (await Task.WhenAny(Task.Delay(timeout), task) != task)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationTimedOutException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
await _channel.DisconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), $"TX >>> {packet} [Timeout={timeout}]");
|
|
||||||
|
|
||||||
bool hasTimeout;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var task = _serializer.SerializeAsync(packet, _channel);
|
|
||||||
hasTimeout = await Task.WhenAny(Task.Delay(timeout), task) != task;
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasTimeout)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationTimedOutException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout)
|
|
||||||
{
|
|
||||||
MqttBasePacket packet;
|
|
||||||
if (timeout > TimeSpan.Zero)
|
|
||||||
{
|
|
||||||
var workerTask = _serializer.DeserializeAsync(_channel);
|
|
||||||
var timeoutTask = Task.Delay(timeout);
|
|
||||||
var hasTimeout = Task.WhenAny(timeoutTask, workerTask) == timeoutTask;
|
|
||||||
|
|
||||||
if (hasTimeout)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationTimedOutException();
|
|
||||||
}
|
|
||||||
|
|
||||||
packet = workerTask.Result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packet = await _serializer.DeserializeAsync(_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet == null)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Received malformed packet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), $"RX <<< {packet}");
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Adapter
|
|
||||||
{
|
|
||||||
public class MqttClientConnectedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public MqttClientConnectedEventArgs(string identifier, IMqttCommunicationAdapter clientAdapter)
|
|
||||||
{
|
|
||||||
Identifier = identifier ?? throw new ArgumentNullException(nameof(identifier));
|
|
||||||
ClientAdapter = clientAdapter ?? throw new ArgumentNullException(nameof(clientAdapter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Identifier { get; }
|
|
||||||
|
|
||||||
public IMqttCommunicationAdapter ClientAdapter { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Adapter
|
|
||||||
{
|
|
||||||
public class MqttConnectingFailedException : MqttCommunicationException
|
|
||||||
{
|
|
||||||
public MqttConnectingFailedException(MqttConnectReturnCode returnCode)
|
|
||||||
: base($"Connecting with MQTT server failed ({returnCode}).")
|
|
||||||
{
|
|
||||||
ReturnCode = returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttConnectReturnCode ReturnCode { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Channel
|
|
||||||
{
|
|
||||||
public interface IMqttCommunicationChannel
|
|
||||||
{
|
|
||||||
Task ConnectAsync(MqttClientOptions options);
|
|
||||||
|
|
||||||
Task DisconnectAsync();
|
|
||||||
|
|
||||||
Task WriteAsync(byte[] buffer);
|
|
||||||
|
|
||||||
Task ReadAsync(byte[] buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,370 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Internal;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public class MqttClient
|
|
||||||
{
|
|
||||||
private readonly ConcurrentDictionary<ushort, MqttPublishPacket> _pendingExactlyOncePublishPackets = new ConcurrentDictionary<ushort, MqttPublishPacket>();
|
|
||||||
private readonly HashSet<ushort> _processedPublishPackets = new HashSet<ushort>();
|
|
||||||
|
|
||||||
private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
|
|
||||||
private readonly MqttClientOptions _options;
|
|
||||||
private readonly IMqttCommunicationAdapter _adapter;
|
|
||||||
|
|
||||||
private int _latestPacketIdentifier;
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
|
|
||||||
public MqttClient(MqttClientOptions options, IMqttCommunicationAdapter adapter)
|
|
||||||
{
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler Connected;
|
|
||||||
|
|
||||||
public event EventHandler Disconnected;
|
|
||||||
|
|
||||||
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
|
|
||||||
|
|
||||||
public bool IsConnected { get; private set; }
|
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttApplicationMessage willApplicationMessage = null)
|
|
||||||
{
|
|
||||||
MqttTrace.Verbose(nameof(MqttClient), "Trying to connect.");
|
|
||||||
|
|
||||||
if (IsConnected)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("It is not allowed to connect with a server after the connection is established.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectPacket = new MqttConnectPacket
|
|
||||||
{
|
|
||||||
ClientId = _options.ClientId,
|
|
||||||
Username = _options.UserName,
|
|
||||||
Password = _options.Password,
|
|
||||||
KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds,
|
|
||||||
WillMessage = willApplicationMessage
|
|
||||||
};
|
|
||||||
|
|
||||||
await _adapter.ConnectAsync(_options, _options.DefaultCommunicationTimeout);
|
|
||||||
MqttTrace.Verbose(nameof(MqttClient), "Connection with server established.");
|
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
_latestPacketIdentifier = 0;
|
|
||||||
_processedPublishPackets.Clear();
|
|
||||||
_packetDispatcher.Reset();
|
|
||||||
IsConnected = true;
|
|
||||||
|
|
||||||
Task.Run(() => ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
|
|
||||||
|
|
||||||
var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket);
|
|
||||||
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
|
|
||||||
{
|
|
||||||
throw new MqttConnectingFailedException(response.ConnectReturnCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_options.KeepAlivePeriod != TimeSpan.Zero)
|
|
||||||
{
|
|
||||||
Task.Run(() => SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
Connected?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
await SendAsync(new MqttDisconnectPacket());
|
|
||||||
await DisconnectInternalAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IList<MqttSubscribeResult>> SubscribeAsync(params TopicFilter[] topicFilters)
|
|
||||||
{
|
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
|
||||||
|
|
||||||
return SubscribeAsync(topicFilters.ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IList<MqttSubscribeResult>> SubscribeAsync(IList<TopicFilter> topicFilters)
|
|
||||||
{
|
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
|
||||||
if (!topicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
|
|
||||||
ThrowIfNotConnected();
|
|
||||||
|
|
||||||
var subscribePacket = new MqttSubscribePacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = GetNewPacketIdentifier(),
|
|
||||||
TopicFilters = topicFilters
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket);
|
|
||||||
|
|
||||||
if (response.SubscribeReturnCodes.Count != topicFilters.Count)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
|
|
||||||
}
|
|
||||||
|
|
||||||
return topicFilters.Select((t, i) => new MqttSubscribeResult(t, response.SubscribeReturnCodes[i])).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task Unsubscribe(params string[] topicFilters)
|
|
||||||
{
|
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
|
||||||
|
|
||||||
return Unsubscribe(topicFilters.ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Unsubscribe(IList<string> topicFilters)
|
|
||||||
{
|
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
|
||||||
if (!topicFilters.Any()) throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
|
|
||||||
ThrowIfNotConnected();
|
|
||||||
|
|
||||||
var unsubscribePacket = new MqttUnsubscribePacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = GetNewPacketIdentifier(),
|
|
||||||
TopicFilters = topicFilters
|
|
||||||
};
|
|
||||||
|
|
||||||
await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task PublishAsync(MqttApplicationMessage applicationMessage)
|
|
||||||
{
|
|
||||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
|
||||||
ThrowIfNotConnected();
|
|
||||||
|
|
||||||
var publishPacket = applicationMessage.ToPublishPacket();
|
|
||||||
|
|
||||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
await SendAsync(publishPacket);
|
|
||||||
}
|
|
||||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
|
||||||
{
|
|
||||||
publishPacket.PacketIdentifier = GetNewPacketIdentifier();
|
|
||||||
await SendAndReceiveAsync<MqttPubAckPacket>(publishPacket);
|
|
||||||
}
|
|
||||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
|
||||||
{
|
|
||||||
publishPacket.PacketIdentifier = GetNewPacketIdentifier();
|
|
||||||
await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket);
|
|
||||||
await SendAsync(publishPacket.CreateResponse<MqttPubCompPacket>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThrowIfNotConnected()
|
|
||||||
{
|
|
||||||
if (!IsConnected) throw new MqttCommunicationException("The client is not connected.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DisconnectInternalAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _adapter.DisconnectAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_cancellationTokenSource?.Cancel();
|
|
||||||
IsConnected = false;
|
|
||||||
Disconnected?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ProcessReceivedPacket(MqttBasePacket mqttPacket)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (mqttPacket is MqttPingReqPacket)
|
|
||||||
{
|
|
||||||
await SendAsync(new MqttPingRespPacket());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mqttPacket is MqttDisconnectPacket)
|
|
||||||
{
|
|
||||||
await DisconnectAsync();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var publishPacket = mqttPacket as MqttPublishPacket;
|
|
||||||
if (publishPacket != null)
|
|
||||||
{
|
|
||||||
await ProcessReceivedPublishPacket(publishPacket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubRelPacket = mqttPacket as MqttPubRelPacket;
|
|
||||||
if (pubRelPacket != null)
|
|
||||||
{
|
|
||||||
await ProcessReceivedPubRelPacket(pubRelPacket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_packetDispatcher.Dispatch(mqttPacket);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttClient), exception, "Error while processing received packet.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (publishPacket.QualityOfServiceLevel != MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
_processedPublishPackets.Add(publishPacket.PacketIdentifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
var applicationMessage = new MqttApplicationMessage(
|
|
||||||
publishPacket.Topic,
|
|
||||||
publishPacket.Payload,
|
|
||||||
publishPacket.QualityOfServiceLevel,
|
|
||||||
publishPacket.Retain
|
|
||||||
);
|
|
||||||
|
|
||||||
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(applicationMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ProcessReceivedPublishPacket(MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
FireApplicationMessageReceivedEvent(publishPacket);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
|
||||||
{
|
|
||||||
FireApplicationMessageReceivedEvent(publishPacket);
|
|
||||||
await SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
|
||||||
}
|
|
||||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
|
||||||
{
|
|
||||||
_pendingExactlyOncePublishPackets[publishPacket.PacketIdentifier] = publishPacket;
|
|
||||||
await SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket)
|
|
||||||
{
|
|
||||||
MqttPublishPacket originalPublishPacket;
|
|
||||||
if (!_pendingExactlyOncePublishPackets.TryRemove(pubRelPacket.PacketIdentifier, out originalPublishPacket))
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
await SendAsync(originalPublishPacket.CreateResponse<MqttPubCompPacket>());
|
|
||||||
|
|
||||||
FireApplicationMessageReceivedEvent(originalPublishPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SendAsync(MqttBasePacket packet)
|
|
||||||
{
|
|
||||||
return _adapter.SendPacketAsync(packet, _options.DefaultCommunicationTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket
|
|
||||||
{
|
|
||||||
bool ResponsePacketSelector(MqttBasePacket p)
|
|
||||||
{
|
|
||||||
var p1 = p as TResponsePacket;
|
|
||||||
if (p1 == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pi1 = requestPacket as IPacketWithIdentifier;
|
|
||||||
var pi2 = p as IPacketWithIdentifier;
|
|
||||||
|
|
||||||
if (pi1 != null && pi2 != null)
|
|
||||||
{
|
|
||||||
if (pi1.PacketIdentifier != pi2.PacketIdentifier)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _adapter.SendPacketAsync(requestPacket, _options.DefaultCommunicationTimeout);
|
|
||||||
return (TResponsePacket)await _packetDispatcher.WaitForPacketAsync(ResponsePacketSelector, _options.DefaultCommunicationTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ushort GetNewPacketIdentifier()
|
|
||||||
{
|
|
||||||
return (ushort)Interlocked.Increment(ref _latestPacketIdentifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendKeepAliveMessagesAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttClient), "Start sending keep alive packets.");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
await Task.Delay(_options.KeepAlivePeriod, cancellationToken);
|
|
||||||
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MqttCommunicationException exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets.");
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Warning(nameof(MqttClient), exception, "Error while sending/receiving keep alive packets.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttClient), "Stopped sending keep alive packets.");
|
|
||||||
await DisconnectInternalAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReceivePackets(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttClient), "Start receiving packets.");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero);
|
|
||||||
MqttTrace.Information(nameof(MqttClient), $"Received <<< {mqttPacket}");
|
|
||||||
|
|
||||||
Task.Run(() => ProcessReceivedPacket(mqttPacket), cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MqttCommunicationException exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets.");
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttClient), exception, "Error while receiving packets.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttClient), "Stopped receiving packets.");
|
|
||||||
await DisconnectInternalAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public class MqttClientOptions
|
|
||||||
{
|
|
||||||
public string Server { get; set; }
|
|
||||||
|
|
||||||
public int Port { get; set; } = 1883;
|
|
||||||
|
|
||||||
public string UserName { get; set; }
|
|
||||||
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
public string ClientId { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
|
||||||
|
|
||||||
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);
|
|
||||||
|
|
||||||
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public class MqttPacketAwaiter : TaskCompletionSource<MqttBasePacket>
|
|
||||||
{
|
|
||||||
public MqttPacketAwaiter(Func<MqttBasePacket, bool> packetSelector)
|
|
||||||
{
|
|
||||||
PacketSelector = packetSelector ?? throw new ArgumentNullException(nameof(packetSelector));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Func<MqttBasePacket, bool> PacketSelector { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public class MqttPacketDispatcher
|
|
||||||
{
|
|
||||||
private readonly object _syncRoot = new object();
|
|
||||||
private readonly List<MqttBasePacket> _receivedPackets = new List<MqttBasePacket>();
|
|
||||||
private readonly List<MqttPacketAwaiter> _packetAwaiters = new List<MqttPacketAwaiter>();
|
|
||||||
|
|
||||||
public async Task<MqttBasePacket> WaitForPacketAsync(Func<MqttBasePacket, bool> selector, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
if (selector == null) throw new ArgumentNullException(nameof(selector));
|
|
||||||
|
|
||||||
var packetAwaiter = AddPacketAwaiter(selector);
|
|
||||||
DispatchPendingPackets();
|
|
||||||
|
|
||||||
var hasTimeout = await Task.WhenAny(Task.Delay(timeout), packetAwaiter.Task) != packetAwaiter.Task;
|
|
||||||
RemovePacketAwaiter(packetAwaiter);
|
|
||||||
|
|
||||||
if (hasTimeout)
|
|
||||||
{
|
|
||||||
MqttTrace.Warning(nameof(MqttPacketDispatcher), "Timeout while waiting for packet.");
|
|
||||||
throw new MqttCommunicationTimedOutException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return packetAwaiter.Task.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispatch(MqttBasePacket packet)
|
|
||||||
{
|
|
||||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
|
||||||
|
|
||||||
var packetDispatched = false;
|
|
||||||
foreach (var packetAwaiter in GetPacketAwaiters())
|
|
||||||
{
|
|
||||||
if (packetAwaiter.PacketSelector(packet))
|
|
||||||
{
|
|
||||||
packetAwaiter.SetResult(packet);
|
|
||||||
packetDispatched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_syncRoot)
|
|
||||||
{
|
|
||||||
if (!packetDispatched)
|
|
||||||
{
|
|
||||||
_receivedPackets.Add(packet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_receivedPackets.Remove(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
lock (_syncRoot)
|
|
||||||
{
|
|
||||||
_packetAwaiters.Clear();
|
|
||||||
_receivedPackets.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MqttPacketAwaiter> GetPacketAwaiters()
|
|
||||||
{
|
|
||||||
lock (_packetAwaiters)
|
|
||||||
{
|
|
||||||
return new List<MqttPacketAwaiter>(_packetAwaiters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MqttPacketAwaiter AddPacketAwaiter(Func<MqttBasePacket, bool> selector)
|
|
||||||
{
|
|
||||||
lock (_syncRoot)
|
|
||||||
{
|
|
||||||
var packetAwaiter = new MqttPacketAwaiter(selector);
|
|
||||||
_packetAwaiters.Add(packetAwaiter);
|
|
||||||
return packetAwaiter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemovePacketAwaiter(MqttPacketAwaiter packetAwaiter)
|
|
||||||
{
|
|
||||||
lock (_syncRoot)
|
|
||||||
{
|
|
||||||
_packetAwaiters.Remove(packetAwaiter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DispatchPendingPackets()
|
|
||||||
{
|
|
||||||
List<MqttBasePacket> receivedPackets;
|
|
||||||
lock (_syncRoot)
|
|
||||||
{
|
|
||||||
receivedPackets = new List<MqttBasePacket>(_receivedPackets);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var pendingPacket in receivedPackets)
|
|
||||||
{
|
|
||||||
Dispatch(pendingPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public class MqttSubscribeResult
|
|
||||||
{
|
|
||||||
public MqttSubscribeResult(TopicFilter topicFilter, MqttSubscribeReturnCode returnCode)
|
|
||||||
{
|
|
||||||
TopicFilter = topicFilter;
|
|
||||||
ReturnCode = returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TopicFilter TopicFilter { get; }
|
|
||||||
|
|
||||||
public MqttSubscribeReturnCode ReturnCode { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Diagnostics
|
|
||||||
{
|
|
||||||
public static class MqttTrace
|
|
||||||
{
|
|
||||||
public static event EventHandler<MqttTraceMessagePublishedEventArgs> TraceMessagePublished;
|
|
||||||
|
|
||||||
public static void Verbose(string source, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Verbose, null, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Information(string source, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Information, null, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string source, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Warning, null, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string source, Exception exception, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Warning, exception, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string source, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Error, null, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string source, Exception exception, string message)
|
|
||||||
{
|
|
||||||
Publish(source, MqttTraceLevel.Error, exception, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Publish(string source, MqttTraceLevel traceLevel, Exception exception, string message)
|
|
||||||
{
|
|
||||||
TraceMessagePublished?.Invoke(null, new MqttTraceMessagePublishedEventArgs(Environment.CurrentManagedThreadId, source, traceLevel, message, exception));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Diagnostics
|
|
||||||
{
|
|
||||||
public enum MqttTraceLevel
|
|
||||||
{
|
|
||||||
Verbose,
|
|
||||||
Information,
|
|
||||||
Warning,
|
|
||||||
Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Diagnostics
|
|
||||||
{
|
|
||||||
public class MqttTraceMessagePublishedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public MqttTraceMessagePublishedEventArgs(int threadId, string source, MqttTraceLevel level, string message, Exception exception)
|
|
||||||
{
|
|
||||||
ThreadId = threadId;
|
|
||||||
Source = source;
|
|
||||||
Level = level;
|
|
||||||
Message = message;
|
|
||||||
Exception = exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ThreadId { get; }
|
|
||||||
|
|
||||||
public string Source { get; }
|
|
||||||
|
|
||||||
public MqttTraceLevel Level { get; }
|
|
||||||
|
|
||||||
public string Message { get; }
|
|
||||||
|
|
||||||
public Exception Exception { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Exceptions
|
|
||||||
{
|
|
||||||
public class MqttCommunicationException : Exception
|
|
||||||
{
|
|
||||||
public MqttCommunicationException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttCommunicationException(Exception innerException)
|
|
||||||
: base(innerException.Message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttCommunicationException(string message)
|
|
||||||
: base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Exceptions
|
|
||||||
{
|
|
||||||
public class MqttCommunicationTimedOutException : MqttCommunicationException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Exceptions
|
|
||||||
{
|
|
||||||
public class MqttProtocolViolationException : Exception
|
|
||||||
{
|
|
||||||
public MqttProtocolViolationException(string message)
|
|
||||||
: base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Internal
|
|
||||||
{
|
|
||||||
public class AsyncGate
|
|
||||||
{
|
|
||||||
private readonly Queue<TaskCompletionSource<bool>> _waitingTasks = new Queue<TaskCompletionSource<bool>>();
|
|
||||||
|
|
||||||
public Task WaitOneAsync()
|
|
||||||
{
|
|
||||||
var tcs = new TaskCompletionSource<bool>();
|
|
||||||
lock (_waitingTasks)
|
|
||||||
{
|
|
||||||
_waitingTasks.Enqueue(tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Set()
|
|
||||||
{
|
|
||||||
lock (_waitingTasks)
|
|
||||||
{
|
|
||||||
if (_waitingTasks.Count > 0)
|
|
||||||
{
|
|
||||||
_waitingTasks.Dequeue().SetResult(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Internal
|
|
||||||
{
|
|
||||||
internal static class MqttApplicationMessageExtensions
|
|
||||||
{
|
|
||||||
public static MqttPublishPacket ToPublishPacket(this MqttApplicationMessage applicationMessage)
|
|
||||||
{
|
|
||||||
if (applicationMessage == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MqttPublishPacket
|
|
||||||
{
|
|
||||||
Topic = applicationMessage.Topic,
|
|
||||||
Payload = applicationMessage.Payload,
|
|
||||||
QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel,
|
|
||||||
Retain = applicationMessage.Retain,
|
|
||||||
Dup = false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Internal
|
|
||||||
{
|
|
||||||
internal static class TaskExtensions
|
|
||||||
{
|
|
||||||
public static void Forget(this Task task)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard1.1</TargetFramework>
|
|
||||||
<AssemblyName>MQTTnet.Core</AssemblyName>
|
|
||||||
<RootNamespace>MQTTnet.Core</RootNamespace>
|
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
|
||||||
<Description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</Description>
|
|
||||||
<Product>MQTTnet</Product>
|
|
||||||
<Company>Christian Kratky</Company>
|
|
||||||
<Authors>Christian Kratky</Authors>
|
|
||||||
<Version>2.1.1.0</Version>
|
|
||||||
<PackageId>MQTTnet.Core</PackageId>
|
|
||||||
<Copyright>Copyright © Christian Kratky 2016-2017</Copyright>
|
|
||||||
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
|
|
||||||
<PackageIconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</PackageIconUrl>
|
|
||||||
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
|
|
||||||
<PackageTags>MQTT MQTTClient MQTTServer MQTTBroker Broker</PackageTags>
|
|
||||||
<FileVersion>2.1.1.0</FileVersion>
|
|
||||||
<AssemblyVersion>2.1.1.0</AssemblyVersion>
|
|
||||||
<PackageLicenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</PackageLicenseUrl>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|AnyCPU'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x64'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" />
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" />
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core
|
|
||||||
{
|
|
||||||
public class MqttApplicationMessage
|
|
||||||
{
|
|
||||||
public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
|
||||||
{
|
|
||||||
Topic = topic ?? throw new ArgumentNullException(nameof(topic));
|
|
||||||
Payload = payload ?? throw new ArgumentNullException(nameof(payload));
|
|
||||||
QualityOfServiceLevel = qualityOfServiceLevel;
|
|
||||||
Retain = retain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Topic { get; }
|
|
||||||
|
|
||||||
public byte[] Payload { get; }
|
|
||||||
|
|
||||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; }
|
|
||||||
|
|
||||||
public bool Retain { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core
|
|
||||||
{
|
|
||||||
public class MqttApplicationMessageReceivedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public MqttApplicationMessageReceivedEventArgs(MqttApplicationMessage applicationMessage)
|
|
||||||
{
|
|
||||||
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttApplicationMessage ApplicationMessage { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public interface IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
ushort PacketIdentifier { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public abstract class MqttBasePacket
|
|
||||||
{
|
|
||||||
public TResponsePacket CreateResponse<TResponsePacket>()
|
|
||||||
{
|
|
||||||
var responsePacket = Activator.CreateInstance<TResponsePacket>();
|
|
||||||
var responsePacketWithIdentifier = responsePacket as IPacketWithIdentifier;
|
|
||||||
if (responsePacketWithIdentifier != null)
|
|
||||||
{
|
|
||||||
var requestPacketWithIdentifier = this as IPacketWithIdentifier;
|
|
||||||
if (requestPacketWithIdentifier == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Response packet has PacketIdentifier but request packet does not.");
|
|
||||||
}
|
|
||||||
|
|
||||||
responsePacketWithIdentifier.PacketIdentifier = requestPacketWithIdentifier.PacketIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
return responsePacket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttBasePublishPacket : MqttBasePacket, IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
public ushort PacketIdentifier { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttConnAckPacket : MqttBasePacket
|
|
||||||
{
|
|
||||||
public bool IsSessionPresent { get; set; }
|
|
||||||
|
|
||||||
public MqttConnectReturnCode ConnectReturnCode { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{nameof(MqttConnAckPacket)}: [ConnectReturnCode={ConnectReturnCode}] [IsSessionPresent={IsSessionPresent}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttConnectPacket: MqttBasePacket
|
|
||||||
{
|
|
||||||
public string ClientId { get; set; }
|
|
||||||
|
|
||||||
public string Username { get; set; }
|
|
||||||
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
public ushort KeepAlivePeriod { get; set; }
|
|
||||||
|
|
||||||
public bool CleanSession { get; set; }
|
|
||||||
|
|
||||||
public MqttApplicationMessage WillMessage { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{nameof(MqttConnectPacket)} [ClientId={ClientId}] [Username={Username}] [Password={Password}] [KeepAlivePeriod={KeepAlivePeriod}] [CleanSession={CleanSession}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttDisconnectPacket : MqttBasePacket
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPingReqPacket : MqttBasePacket
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return nameof(MqttPingReqPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPingRespPacket : MqttBasePacket
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return nameof(MqttPingRespPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPubAckPacket : MqttBasePublishPacket
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPubCompPacket : MqttBasePublishPacket
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPubRecPacket : MqttBasePublishPacket
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPubRelPacket : MqttBasePublishPacket
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using System.Text;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttPublishPacket : MqttBasePublishPacket
|
|
||||||
{
|
|
||||||
public bool Retain { get; set; }
|
|
||||||
|
|
||||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }
|
|
||||||
|
|
||||||
public bool Dup { get; set; }
|
|
||||||
|
|
||||||
public string Topic { get; set; }
|
|
||||||
|
|
||||||
public byte[] Payload { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
$"{nameof(MqttPublishPacket)} [Topic={Topic}] [Payload={Encoding.UTF8.GetString(Payload, 0, Payload.Length)}] [QoSLevel={QualityOfServiceLevel}] [Dup={Dup}] [Retain={Retain}] [PacketIdentifier={PacketIdentifier}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttSubAckPacket : MqttBasePacket, IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
public ushort PacketIdentifier { get; set; }
|
|
||||||
|
|
||||||
public IList<MqttSubscribeReturnCode> SubscribeReturnCodes { get; set; } = new List<MqttSubscribeReturnCode>();
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
var subscribeReturnCodesText = string.Join(",", SubscribeReturnCodes.Select(f => f.ToString()));
|
|
||||||
return
|
|
||||||
$"{nameof(MqttSubAckPacket)} [PacketIdentifier={PacketIdentifier}] [SubscribeReturnCodes={subscribeReturnCodesText}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttSubscribePacket : MqttBasePacket, IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
public ushort PacketIdentifier { get; set; }
|
|
||||||
|
|
||||||
public IList<TopicFilter> TopicFilters { get; set; } = new List<TopicFilter>();
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
var topicFiltersText = string.Join(",", TopicFilters.Select(f => $"{f.Topic}@{f.QualityOfServiceLevel}"));
|
|
||||||
return
|
|
||||||
$"{nameof(MqttSubscribePacket)} [PacketIdentifier={PacketIdentifier}] [TopicFilters={topicFiltersText}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttUnsubAckPacket : MqttBasePacket, IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
public ushort PacketIdentifier { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class MqttUnsubscribePacket : MqttBasePacket, IPacketWithIdentifier
|
|
||||||
{
|
|
||||||
public ushort PacketIdentifier { get; set; }
|
|
||||||
|
|
||||||
public IList<string> TopicFilters { get; set; } = new List<string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Packets
|
|
||||||
{
|
|
||||||
public class TopicFilter
|
|
||||||
{
|
|
||||||
public TopicFilter(string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
|
||||||
{
|
|
||||||
Topic = topic;
|
|
||||||
QualityOfServiceLevel = qualityOfServiceLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Topic { get; }
|
|
||||||
|
|
||||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Protocol
|
|
||||||
{
|
|
||||||
public enum MqttQualityOfServiceLevel
|
|
||||||
{
|
|
||||||
AtMostOnce = 0x00,
|
|
||||||
AtLeastOnce = 0x01,
|
|
||||||
ExactlyOnce = 0x02
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Protocol
|
|
||||||
{
|
|
||||||
public enum MqttSubscribeReturnCode
|
|
||||||
{
|
|
||||||
SuccessMaximumQoS0 = 0x00,
|
|
||||||
SuccessMaximumQoS1 = 0x01,
|
|
||||||
SuccessMaximumQoS2 = 0x02,
|
|
||||||
Failure = 0x80
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public class ByteReader
|
|
||||||
{
|
|
||||||
private readonly int _source;
|
|
||||||
private int _index;
|
|
||||||
|
|
||||||
public ByteReader(int source)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Read()
|
|
||||||
{
|
|
||||||
if (_index >= 8)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("End of byte reached.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = ((1 << _index) & _source) > 0;
|
|
||||||
_index++;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte Read(int count)
|
|
||||||
{
|
|
||||||
if (_index + count > 8)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("End of byte will be reached.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = 0;
|
|
||||||
for (var i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (((1 << _index) & _source) > 0)
|
|
||||||
{
|
|
||||||
result |= 1 << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (byte)result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public class ByteWriter
|
|
||||||
{
|
|
||||||
private int _index;
|
|
||||||
private int _byte;
|
|
||||||
|
|
||||||
public byte Value => (byte)_byte;
|
|
||||||
|
|
||||||
public void Write(int @byte, int count)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var value = ((1 << i) & @byte) > 0;
|
|
||||||
Write(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(bool bit)
|
|
||||||
{
|
|
||||||
if (_index >= 8)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("End of the byte reached.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bit)
|
|
||||||
{
|
|
||||||
_byte |= 1 << _index;
|
|
||||||
}
|
|
||||||
|
|
||||||
_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,616 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public class DefaultMqttV311PacketSerializer : IMqttPacketSerializer
|
|
||||||
{
|
|
||||||
public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
if (packet == null) throw new ArgumentNullException(nameof(packet));
|
|
||||||
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
|
||||||
|
|
||||||
var connectPacket = packet as MqttConnectPacket;
|
|
||||||
if (connectPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(connectPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var connAckPacket = packet as MqttConnAckPacket;
|
|
||||||
if (connAckPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(connAckPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var disconnectPacket = packet as MqttDisconnectPacket;
|
|
||||||
if (disconnectPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(disconnectPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pingReqPacket = packet as MqttPingReqPacket;
|
|
||||||
if (pingReqPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pingReqPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pingRespPacket = packet as MqttPingRespPacket;
|
|
||||||
if (pingRespPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pingRespPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var publishPacket = packet as MqttPublishPacket;
|
|
||||||
if (publishPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(publishPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubAckPacket = packet as MqttPubAckPacket;
|
|
||||||
if (pubAckPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pubAckPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubRecPacket = packet as MqttPubRecPacket;
|
|
||||||
if (pubRecPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pubRecPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubRelPacket = packet as MqttPubRelPacket;
|
|
||||||
if (pubRelPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pubRelPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubCompPacket = packet as MqttPubCompPacket;
|
|
||||||
if (pubCompPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(pubCompPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var subscribePacket = packet as MqttSubscribePacket;
|
|
||||||
if (subscribePacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(subscribePacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var subAckPacket = packet as MqttSubAckPacket;
|
|
||||||
if (subAckPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(subAckPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var unsubscribePacket = packet as MqttUnsubscribePacket;
|
|
||||||
if (unsubscribePacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(unsubscribePacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
var unsubAckPacket = packet as MqttUnsubAckPacket;
|
|
||||||
if (unsubAckPacket != null)
|
|
||||||
{
|
|
||||||
return SerializeAsync(unsubAckPacket, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new MqttProtocolViolationException("Packet type invalid.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<MqttBasePacket> DeserializeAsync(IMqttCommunicationChannel source)
|
|
||||||
{
|
|
||||||
if (source == null) throw new ArgumentNullException(nameof(source));
|
|
||||||
|
|
||||||
using (var mqttPacketReader = new MqttPacketReader(source))
|
|
||||||
{
|
|
||||||
await mqttPacketReader.ReadToEndAsync();
|
|
||||||
|
|
||||||
switch (mqttPacketReader.ControlPacketType)
|
|
||||||
{
|
|
||||||
case MqttControlPacketType.Connect:
|
|
||||||
{
|
|
||||||
return await DeserializeConnectAsync(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.ConnAck:
|
|
||||||
{
|
|
||||||
return await DeserializeConnAck(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Disconnect:
|
|
||||||
{
|
|
||||||
return new MqttDisconnectPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Publish:
|
|
||||||
{
|
|
||||||
return await DeserializePublishAsync(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubAck:
|
|
||||||
{
|
|
||||||
return new MqttPubAckPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubRec:
|
|
||||||
{
|
|
||||||
return new MqttPubRecPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubRel:
|
|
||||||
{
|
|
||||||
return new MqttPubRelPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubComp:
|
|
||||||
{
|
|
||||||
return new MqttPubCompPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PingReq:
|
|
||||||
{
|
|
||||||
return new MqttPingReqPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PingResp:
|
|
||||||
{
|
|
||||||
return new MqttPingRespPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Subscribe:
|
|
||||||
{
|
|
||||||
return await DeserializeSubscribeAsync(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.SubAck:
|
|
||||||
{
|
|
||||||
return await DeserializeSubAck(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Unsubscibe:
|
|
||||||
{
|
|
||||||
return await DeserializeUnsubscribeAsync(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.UnsubAck:
|
|
||||||
{
|
|
||||||
return new MqttUnsubAckPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Packet type not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializeUnsubscribeAsync(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var packet = new MqttUnsubscribePacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await reader.ReadRemainingDataUShortAsync(),
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!reader.EndOfRemainingData)
|
|
||||||
{
|
|
||||||
packet.TopicFilters.Add(await reader.ReadRemainingDataStringWithLengthPrefixAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializeSubscribeAsync(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var packet = new MqttSubscribePacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await reader.ReadRemainingDataUShortAsync(),
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!reader.EndOfRemainingData)
|
|
||||||
{
|
|
||||||
packet.TopicFilters.Add(new TopicFilter(
|
|
||||||
await reader.ReadRemainingDataStringWithLengthPrefixAsync(),
|
|
||||||
(MqttQualityOfServiceLevel)await reader.ReadRemainingDataByteAsync()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializePublishAsync(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var fixedHeader = new ByteReader(reader.FixedHeader);
|
|
||||||
var retain = fixedHeader.Read();
|
|
||||||
var qualityOfServiceLevel = (MqttQualityOfServiceLevel)fixedHeader.Read(2);
|
|
||||||
var dup = fixedHeader.Read();
|
|
||||||
|
|
||||||
var topic = await reader.ReadRemainingDataStringWithLengthPrefixAsync();
|
|
||||||
|
|
||||||
ushort packetIdentifier = 0;
|
|
||||||
if (qualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
packetIdentifier = await reader.ReadRemainingDataUShortAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
var packet = new MqttPublishPacket
|
|
||||||
{
|
|
||||||
Retain = retain,
|
|
||||||
QualityOfServiceLevel = qualityOfServiceLevel,
|
|
||||||
Dup = dup,
|
|
||||||
Topic = topic,
|
|
||||||
Payload = await reader.ReadRemainingDataAsync(),
|
|
||||||
PacketIdentifier = packetIdentifier
|
|
||||||
};
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializeConnectAsync(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var packet = new MqttConnectPacket();
|
|
||||||
|
|
||||||
await reader.ReadRemainingDataByteAsync();
|
|
||||||
await reader.ReadRemainingDataByteAsync();
|
|
||||||
|
|
||||||
var protocolName = await reader.ReadRemainingDataAsync(4);
|
|
||||||
|
|
||||||
if (Encoding.UTF8.GetString(protocolName, 0, protocolName.Length) != "MQTT")
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Protocol name is not 'MQTT'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var protocolLevel = await reader.ReadRemainingDataByteAsync();
|
|
||||||
var connectFlags = await reader.ReadRemainingDataByteAsync();
|
|
||||||
|
|
||||||
var connectFlagsReader = new ByteReader(connectFlags);
|
|
||||||
connectFlagsReader.Read(); // Reserved.
|
|
||||||
packet.CleanSession = connectFlagsReader.Read();
|
|
||||||
var willFlag = connectFlagsReader.Read();
|
|
||||||
var willQoS = connectFlagsReader.Read(2);
|
|
||||||
var willRetain = connectFlagsReader.Read();
|
|
||||||
var passwordFlag = connectFlagsReader.Read();
|
|
||||||
var usernameFlag = connectFlagsReader.Read();
|
|
||||||
|
|
||||||
packet.KeepAlivePeriod = await reader.ReadRemainingDataUShortAsync();
|
|
||||||
packet.ClientId = await reader.ReadRemainingDataStringWithLengthPrefixAsync();
|
|
||||||
|
|
||||||
if (willFlag)
|
|
||||||
{
|
|
||||||
packet.WillMessage = new MqttApplicationMessage(
|
|
||||||
await reader.ReadRemainingDataStringWithLengthPrefixAsync(),
|
|
||||||
await reader.ReadRemainingDataWithLengthPrefixAsync(),
|
|
||||||
(MqttQualityOfServiceLevel)willQoS,
|
|
||||||
willRetain);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usernameFlag)
|
|
||||||
{
|
|
||||||
packet.Username = await reader.ReadRemainingDataStringWithLengthPrefixAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passwordFlag)
|
|
||||||
{
|
|
||||||
packet.Password = await reader.ReadRemainingDataStringWithLengthPrefixAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
ValidateConnectPacket(packet);
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializeSubAck(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var packet = new MqttSubAckPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = await reader.ReadRemainingDataUShortAsync()
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!reader.EndOfRemainingData)
|
|
||||||
{
|
|
||||||
packet.SubscribeReturnCodes.Add((MqttSubscribeReturnCode)await reader.ReadRemainingDataByteAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MqttBasePacket> DeserializeConnAck(MqttPacketReader reader)
|
|
||||||
{
|
|
||||||
var variableHeader1 = await reader.ReadRemainingDataByteAsync();
|
|
||||||
var variableHeader2 = await reader.ReadRemainingDataByteAsync();
|
|
||||||
|
|
||||||
var packet = new MqttConnAckPacket
|
|
||||||
{
|
|
||||||
IsSessionPresent = new ByteReader(variableHeader1).Read(),
|
|
||||||
ConnectReturnCode = (MqttConnectReturnCode)variableHeader2
|
|
||||||
};
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ValidateConnectPacket(MqttConnectPacket packet)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(packet.ClientId) && !Regex.IsMatch(packet.ClientId, "^[a-zA-Z0-9]*$"))
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("ClientId contains invalid characters [MQTT-3.1.3-5].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ValidatePublishPacket(MqttPublishPacket packet)
|
|
||||||
{
|
|
||||||
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly byte[] MqttPrefix = Encoding.UTF8.GetBytes("MQTT");
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttConnectPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
ValidateConnectPacket(packet);
|
|
||||||
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
// Write variable header
|
|
||||||
output.Write(0x00, 0x04); // 3.1.2.1 Protocol Name
|
|
||||||
output.Write(MqttPrefix);
|
|
||||||
output.Write(0x04); // 3.1.2.2 Protocol Level
|
|
||||||
|
|
||||||
var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags
|
|
||||||
connectFlags.Write(false); // Reserved
|
|
||||||
connectFlags.Write(packet.CleanSession);
|
|
||||||
connectFlags.Write(packet.WillMessage != null);
|
|
||||||
|
|
||||||
if (packet.WillMessage != null)
|
|
||||||
{
|
|
||||||
connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2);
|
|
||||||
connectFlags.Write(packet.WillMessage.Retain);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectFlags.Write(0, 2);
|
|
||||||
connectFlags.Write(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
connectFlags.Write(packet.Password != null);
|
|
||||||
connectFlags.Write(packet.Username != null);
|
|
||||||
|
|
||||||
output.Write(connectFlags);
|
|
||||||
output.Write(packet.KeepAlivePeriod);
|
|
||||||
output.WriteWithLengthPrefix(packet.ClientId);
|
|
||||||
|
|
||||||
if (packet.WillMessage != null)
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(packet.WillMessage.Topic);
|
|
||||||
output.WriteWithLengthPrefix(packet.WillMessage.Payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.Username != null)
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(packet.Username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.Password != null)
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(packet.Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.Connect);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttConnAckPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
var connectAcknowledgeFlags = new ByteWriter();
|
|
||||||
connectAcknowledgeFlags.Write(packet.IsSessionPresent);
|
|
||||||
|
|
||||||
output.Write(connectAcknowledgeFlags);
|
|
||||||
output.Write((byte)packet.ConnectReturnCode);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.ConnAck);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttDisconnectPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
return SerializeEmptyPacketAsync(MqttControlPacketType.Disconnect, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPingReqPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
return SerializeEmptyPacketAsync(MqttControlPacketType.PingReq, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPingRespPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
return SerializeEmptyPacketAsync(MqttControlPacketType.PingResp, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPublishPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
ValidatePublishPacket(packet);
|
|
||||||
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(packet.Topic);
|
|
||||||
|
|
||||||
if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (packet.PacketIdentifier > 0)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Packet identifier must be empty if QoS == 0 [MQTT-2.3.1-5].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.Payload?.Length > 0)
|
|
||||||
{
|
|
||||||
output.Write(packet.Payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
var fixedHeader = new ByteWriter();
|
|
||||||
fixedHeader.Write(packet.Retain);
|
|
||||||
fixedHeader.Write((byte)packet.QualityOfServiceLevel, 2);
|
|
||||||
fixedHeader.Write(packet.Dup);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.Publish, fixedHeader.Value);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPubAckPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.PubAck);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPubRecPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.PubRec);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SerializeAsync(MqttPubRelPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.PubRel, 0x02);
|
|
||||||
await output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttPubCompPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.PubComp);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttSubscribePacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
if (packet.TopicFilters?.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var topicFilter in packet.TopicFilters)
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(topicFilter.Topic);
|
|
||||||
output.Write((byte)topicFilter.QualityOfServiceLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.Subscribe, 0x02);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttSubAckPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
if (packet.SubscribeReturnCodes?.Any() == true)
|
|
||||||
{
|
|
||||||
foreach (var packetSubscribeReturnCode in packet.SubscribeReturnCodes)
|
|
||||||
{
|
|
||||||
output.Write((byte)packetSubscribeReturnCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.SubAck);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttUnsubscribePacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
if (packet.TopicFilters?.Any() == true)
|
|
||||||
{
|
|
||||||
foreach (var topicFilter in packet.TopicFilters)
|
|
||||||
{
|
|
||||||
output.WriteWithLengthPrefix(topicFilter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeAsync(MqttUnsubAckPacket packet, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.Write(packet.PacketIdentifier);
|
|
||||||
|
|
||||||
output.InjectFixedHeader(MqttControlPacketType.UnsubAck);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SerializeEmptyPacketAsync(MqttControlPacketType type, IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
using (var output = new MqttPacketWriter())
|
|
||||||
{
|
|
||||||
output.InjectFixedHeader(type);
|
|
||||||
return output.WriteToAsync(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public interface IMqttPacketSerializer
|
|
||||||
{
|
|
||||||
Task SerializeAsync(MqttBasePacket mqttPacket, IMqttCommunicationChannel destination);
|
|
||||||
|
|
||||||
Task<MqttBasePacket> DeserializeAsync(IMqttCommunicationChannel source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public sealed class MqttPacketReader : IDisposable
|
|
||||||
{
|
|
||||||
private readonly MemoryStream _remainingData = new MemoryStream();
|
|
||||||
private readonly IMqttCommunicationChannel _source;
|
|
||||||
|
|
||||||
public MqttPacketReader(IMqttCommunicationChannel source)
|
|
||||||
{
|
|
||||||
_source = source ?? throw new ArgumentNullException(nameof(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttControlPacketType ControlPacketType { get; private set; }
|
|
||||||
|
|
||||||
public byte FixedHeader { get; private set; }
|
|
||||||
|
|
||||||
public int RemainingLength { get; private set; }
|
|
||||||
|
|
||||||
public bool EndOfRemainingData => _remainingData.Position == _remainingData.Length;
|
|
||||||
|
|
||||||
public async Task ReadToEndAsync()
|
|
||||||
{
|
|
||||||
await ReadFixedHeaderAsync();
|
|
||||||
await ReadRemainingLengthAsync();
|
|
||||||
|
|
||||||
if (RemainingLength == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buffer = new byte[RemainingLength];
|
|
||||||
await _source.ReadAsync(buffer);
|
|
||||||
|
|
||||||
_remainingData.Write(buffer, 0, buffer.Length);
|
|
||||||
_remainingData.Position = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReadFixedHeaderAsync()
|
|
||||||
{
|
|
||||||
FixedHeader = await ReadStreamByteAsync();
|
|
||||||
|
|
||||||
var byteReader = new ByteReader(FixedHeader);
|
|
||||||
byteReader.Read(4);
|
|
||||||
ControlPacketType = (MqttControlPacketType)byteReader.Read(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<byte> ReadStreamByteAsync()
|
|
||||||
{
|
|
||||||
var buffer = new byte[1];
|
|
||||||
await _source.ReadAsync(buffer);
|
|
||||||
return buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReadRemainingLengthAsync()
|
|
||||||
{
|
|
||||||
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
|
|
||||||
var multiplier = 1;
|
|
||||||
var value = 0;
|
|
||||||
byte encodedByte;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
encodedByte = await ReadStreamByteAsync();
|
|
||||||
value += (encodedByte & 127) * multiplier;
|
|
||||||
multiplier *= 128;
|
|
||||||
if (multiplier > 128 * 128 * 128)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("Remaining length is ivalid.");
|
|
||||||
}
|
|
||||||
} while ((encodedByte & 128) != 0);
|
|
||||||
|
|
||||||
RemainingLength = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte> ReadRemainingDataByteAsync()
|
|
||||||
{
|
|
||||||
return (await ReadRemainingDataAsync(1))[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ushort> ReadRemainingDataUShortAsync()
|
|
||||||
{
|
|
||||||
var buffer = await ReadRemainingDataAsync(2);
|
|
||||||
|
|
||||||
var temp = buffer[0];
|
|
||||||
buffer[0] = buffer[1];
|
|
||||||
buffer[1] = temp;
|
|
||||||
|
|
||||||
return BitConverter.ToUInt16(buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReadRemainingDataStringWithLengthPrefixAsync()
|
|
||||||
{
|
|
||||||
var buffer = await ReadRemainingDataWithLengthPrefixAsync();
|
|
||||||
return Encoding.UTF8.GetString(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte[]> ReadRemainingDataWithLengthPrefixAsync()
|
|
||||||
{
|
|
||||||
var length = await ReadRemainingDataUShortAsync();
|
|
||||||
return await ReadRemainingDataAsync(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<byte[]> ReadRemainingDataAsync()
|
|
||||||
{
|
|
||||||
return ReadRemainingDataAsync(RemainingLength - (int)_remainingData.Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte[]> ReadRemainingDataAsync(int length)
|
|
||||||
{
|
|
||||||
var buffer = new byte[length];
|
|
||||||
await _remainingData.ReadAsync(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_remainingData?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Serializer
|
|
||||||
{
|
|
||||||
public sealed class MqttPacketWriter : IDisposable
|
|
||||||
{
|
|
||||||
private readonly MemoryStream _buffer = new MemoryStream(512);
|
|
||||||
|
|
||||||
public void InjectFixedHeader(byte fixedHeader)
|
|
||||||
{
|
|
||||||
if (_buffer.Length == 0)
|
|
||||||
{
|
|
||||||
Write(fixedHeader);
|
|
||||||
Write(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var backupBuffer = _buffer.ToArray();
|
|
||||||
var remainingLength = (int)_buffer.Length;
|
|
||||||
|
|
||||||
_buffer.SetLength(0);
|
|
||||||
|
|
||||||
_buffer.WriteByte(fixedHeader);
|
|
||||||
|
|
||||||
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
|
|
||||||
var x = remainingLength;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var encodedByte = x % 128;
|
|
||||||
x = x / 128;
|
|
||||||
if (x > 0)
|
|
||||||
{
|
|
||||||
encodedByte = encodedByte | 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer.WriteByte((byte)encodedByte);
|
|
||||||
} while (x > 0);
|
|
||||||
|
|
||||||
_buffer.Write(backupBuffer, 0, backupBuffer.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InjectFixedHeader(MqttControlPacketType packetType, byte flags = 0)
|
|
||||||
{
|
|
||||||
var fixedHeader = (byte)((byte)packetType << 4);
|
|
||||||
fixedHeader |= flags;
|
|
||||||
InjectFixedHeader(fixedHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(byte value)
|
|
||||||
{
|
|
||||||
_buffer.WriteByte(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(ushort value)
|
|
||||||
{
|
|
||||||
var buffer = BitConverter.GetBytes(value);
|
|
||||||
_buffer.WriteByte(buffer[1]);
|
|
||||||
_buffer.WriteByte(buffer[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(ByteWriter value)
|
|
||||||
{
|
|
||||||
if (value == null) throw new ArgumentNullException(nameof(value));
|
|
||||||
|
|
||||||
_buffer.WriteByte(value.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(params byte[] value)
|
|
||||||
{
|
|
||||||
if (value == null) throw new ArgumentNullException(nameof(value));
|
|
||||||
|
|
||||||
_buffer.Write(value, 0, value.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteWithLengthPrefix(string value)
|
|
||||||
{
|
|
||||||
WriteWithLengthPrefix(Encoding.UTF8.GetBytes(value ?? string.Empty));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteWithLengthPrefix(byte[] value)
|
|
||||||
{
|
|
||||||
var length = (ushort)value.Length;
|
|
||||||
|
|
||||||
Write(length);
|
|
||||||
Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task WriteToAsync(IMqttCommunicationChannel destination)
|
|
||||||
{
|
|
||||||
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
|
||||||
|
|
||||||
return destination.WriteAsync(_buffer.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_buffer?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttClientPublishPacketContext
|
|
||||||
{
|
|
||||||
public MqttClientPublishPacketContext(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
SenderClientSession = senderClientSession ?? throw new ArgumentNullException(nameof(senderClientSession));
|
|
||||||
PublishPacket = publishPacket ?? throw new ArgumentNullException(nameof(publishPacket));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientSession SenderClientSession { get; }
|
|
||||||
|
|
||||||
public MqttPublishPacket PublishPacket { get; }
|
|
||||||
|
|
||||||
public int SendTries { get; set; }
|
|
||||||
|
|
||||||
public bool IsSent { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Internal;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttClientSession
|
|
||||||
{
|
|
||||||
private readonly ConcurrentDictionary<ushort, MqttPublishPacket> _pendingIncomingPublications = new ConcurrentDictionary<ushort, MqttPublishPacket>();
|
|
||||||
|
|
||||||
private readonly MqttClientSubscriptionsManager _subscriptionsManager = new MqttClientSubscriptionsManager();
|
|
||||||
private readonly MqttOutgoingPublicationsManager _outgoingPublicationsManager;
|
|
||||||
private readonly Action<MqttClientSession, MqttPublishPacket> _publishPacketReceivedCallback;
|
|
||||||
private readonly MqttServerOptions _options;
|
|
||||||
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
private IMqttCommunicationAdapter _adapter;
|
|
||||||
private string _identifier;
|
|
||||||
private MqttApplicationMessage _willApplicationMessage;
|
|
||||||
|
|
||||||
public MqttClientSession(MqttServerOptions options, Action<MqttClientSession, MqttPublishPacket> publishPacketReceivedCallback)
|
|
||||||
{
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
_publishPacketReceivedCallback = publishPacketReceivedCallback ?? throw new ArgumentNullException(nameof(publishPacketReceivedCallback));
|
|
||||||
|
|
||||||
_outgoingPublicationsManager = new MqttOutgoingPublicationsManager(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync(string identifier, MqttApplicationMessage willApplicationMessage, IMqttCommunicationAdapter adapter)
|
|
||||||
{
|
|
||||||
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
|
|
||||||
|
|
||||||
_willApplicationMessage = willApplicationMessage;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_identifier = identifier;
|
|
||||||
_adapter = adapter;
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
_outgoingPublicationsManager.Start(adapter);
|
|
||||||
while (!_cancellationTokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero);
|
|
||||||
await HandleIncomingPacketAsync(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MqttCommunicationException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttClientSession), exception, $"Client '{_identifier}': Unhandled exception while processing client packets.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (willApplicationMessage != null)
|
|
||||||
{
|
|
||||||
_publishPacketReceivedCallback(this, _willApplicationMessage.ToPublishPacket());
|
|
||||||
}
|
|
||||||
|
|
||||||
_outgoingPublicationsManager.Stop();
|
|
||||||
_cancellationTokenSource.Cancel();
|
|
||||||
_adapter = null;
|
|
||||||
|
|
||||||
MqttTrace.Information(nameof(MqttClientSession), $"Client '{_identifier}': Disconnected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnqueuePublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (senderClientSession == null) throw new ArgumentNullException(nameof(senderClientSession));
|
|
||||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
|
||||||
|
|
||||||
if (!_subscriptionsManager.IsTopicSubscribed(publishPacket))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_outgoingPublicationsManager.Enqueue(senderClientSession, publishPacket);
|
|
||||||
MqttTrace.Verbose(nameof(MqttClientSession), $"Client '{_identifier}: Enqueued pending publish packet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleIncomingPacketAsync(MqttBasePacket packet)
|
|
||||||
{
|
|
||||||
var subscribePacket = packet as MqttSubscribePacket;
|
|
||||||
if (subscribePacket != null)
|
|
||||||
{
|
|
||||||
await _adapter.SendPacketAsync(_subscriptionsManager.Subscribe(subscribePacket), _options.DefaultCommunicationTimeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var unsubscribePacket = packet as MqttUnsubscribePacket;
|
|
||||||
if (unsubscribePacket != null)
|
|
||||||
{
|
|
||||||
await _adapter.SendPacketAsync(_subscriptionsManager.Unsubscribe(unsubscribePacket), _options.DefaultCommunicationTimeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var publishPacket = packet as MqttPublishPacket;
|
|
||||||
if (publishPacket != null)
|
|
||||||
{
|
|
||||||
await HandleIncomingPublishPacketAsync(publishPacket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubRelPacket = packet as MqttPubRelPacket;
|
|
||||||
if (pubRelPacket != null)
|
|
||||||
{
|
|
||||||
await HandleIncomingPubRelPacketAsync(pubRelPacket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pubAckPacket = packet as MqttPubAckPacket;
|
|
||||||
if (pubAckPacket != null)
|
|
||||||
{
|
|
||||||
await HandleIncomingPubAckPacketAsync(pubAckPacket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet is MqttPingReqPacket)
|
|
||||||
{
|
|
||||||
await _adapter.SendPacketAsync(new MqttPingRespPacket(), _options.DefaultCommunicationTimeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet is MqttDisconnectPacket || packet is MqttConnectPacket)
|
|
||||||
{
|
|
||||||
_cancellationTokenSource.Cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MqttTrace.Warning(nameof(MqttClientSession), $"Client '{_identifier}': Received not supported packet ({packet}). Closing connection.");
|
|
||||||
_cancellationTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleIncomingPubAckPacketAsync(MqttPubAckPacket pubAckPacket)
|
|
||||||
{
|
|
||||||
await Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleIncomingPublishPacketAsync(MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
{
|
|
||||||
_publishPacketReceivedCallback(this, publishPacket);
|
|
||||||
}
|
|
||||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
|
||||||
{
|
|
||||||
await _adapter.SendPacketAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier }, _options.DefaultCommunicationTimeout);
|
|
||||||
_publishPacketReceivedCallback(this, publishPacket);
|
|
||||||
}
|
|
||||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
|
||||||
{
|
|
||||||
_pendingIncomingPublications[publishPacket.PacketIdentifier] = publishPacket;
|
|
||||||
await _adapter.SendPacketAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }, _options.DefaultCommunicationTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleIncomingPubRelPacketAsync(MqttPubRelPacket pubRelPacket)
|
|
||||||
{
|
|
||||||
MqttPublishPacket publishPacket;
|
|
||||||
if (!_pendingIncomingPublications.TryRemove(pubRelPacket.PacketIdentifier, out publishPacket))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _adapter.SendPacketAsync(new MqttPubCompPacket { PacketIdentifier = publishPacket.PacketIdentifier }, _options.DefaultCommunicationTimeout);
|
|
||||||
_publishPacketReceivedCallback(this, publishPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttClientSessionManager
|
|
||||||
{
|
|
||||||
private readonly ConcurrentDictionary<string, MqttClientSession> _clientSessions = new ConcurrentDictionary<string, MqttClientSession>();
|
|
||||||
private readonly MqttServerOptions _options;
|
|
||||||
|
|
||||||
public MqttClientSessionManager(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunClientSessionAsync(MqttClientConnectedEventArgs eventArgs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var connectPacket = await eventArgs.ClientAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout) as MqttConnectPacket;
|
|
||||||
if (connectPacket == null)
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException("The first packet from a client must be a 'Connect' packet [MQTT-3.1.0-1].");
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectReturnCode = MqttConnectReturnCode.ConnectionAccepted;
|
|
||||||
if (_options.ConnectionValidator != null)
|
|
||||||
{
|
|
||||||
connectReturnCode = _options.ConnectionValidator(connectPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
MqttClientSession clientSession = null;
|
|
||||||
var isSessionPresent = _clientSessions.ContainsKey(connectPacket.ClientId);
|
|
||||||
if (isSessionPresent && connectPacket.CleanSession)
|
|
||||||
{
|
|
||||||
MqttClientSession _;
|
|
||||||
_clientSessions.TryRemove(connectPacket.ClientId, out _);
|
|
||||||
}
|
|
||||||
else if (!connectPacket.CleanSession)
|
|
||||||
{
|
|
||||||
_clientSessions.TryGetValue(connectPacket.ClientId, out clientSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket
|
|
||||||
{
|
|
||||||
ConnectReturnCode = connectReturnCode,
|
|
||||||
IsSessionPresent = clientSession != null
|
|
||||||
}, _options.DefaultCommunicationTimeout);
|
|
||||||
|
|
||||||
if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientSession == null)
|
|
||||||
{
|
|
||||||
clientSession = new MqttClientSession(_options, DispatchPublishPacket);
|
|
||||||
_clientSessions.TryAdd(connectPacket.ClientId, clientSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
await clientSession.RunAsync(eventArgs.Identifier, connectPacket.WillMessage, eventArgs.ClientAdapter);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttServer), exception, exception.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
await eventArgs.ClientAdapter.DisconnectAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_clientSessions.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
foreach (var clientSession in _clientSessions.Values.ToList())
|
|
||||||
{
|
|
||||||
clientSession.EnqueuePublishPacket(senderClientSession, publishPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttClientSubscriptionsManager
|
|
||||||
{
|
|
||||||
private readonly ConcurrentDictionary<string, MqttQualityOfServiceLevel> _subscribedTopics = new ConcurrentDictionary<string, MqttQualityOfServiceLevel>();
|
|
||||||
|
|
||||||
public MqttSubAckPacket Subscribe(MqttSubscribePacket subscribePacket)
|
|
||||||
{
|
|
||||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
|
||||||
|
|
||||||
var responsePacket = subscribePacket.CreateResponse<MqttSubAckPacket>();
|
|
||||||
foreach (var topicFilter in subscribePacket.TopicFilters)
|
|
||||||
{
|
|
||||||
_subscribedTopics[topicFilter.Topic] = topicFilter.QualityOfServiceLevel;
|
|
||||||
responsePacket.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS1); // TODO: Add support for QoS 2.
|
|
||||||
}
|
|
||||||
|
|
||||||
return responsePacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttUnsubAckPacket Unsubscribe(MqttUnsubscribePacket unsubscribePacket)
|
|
||||||
{
|
|
||||||
if (unsubscribePacket == null) throw new ArgumentNullException(nameof(unsubscribePacket));
|
|
||||||
|
|
||||||
foreach (var topicFilter in unsubscribePacket.TopicFilters)
|
|
||||||
{
|
|
||||||
MqttQualityOfServiceLevel _;
|
|
||||||
_subscribedTopics.TryRemove(topicFilter, out _);
|
|
||||||
}
|
|
||||||
|
|
||||||
return unsubscribePacket.CreateResponse<MqttUnsubAckPacket>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsTopicSubscribed(MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
|
||||||
|
|
||||||
foreach (var subscribedTopic in _subscribedTopics)
|
|
||||||
{
|
|
||||||
if (!MqttTopicFilterComparer.IsMatch(publishPacket.Topic, subscribedTopic.Key))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subscribedTopic.Value < publishPacket.QualityOfServiceLevel)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Exceptions;
|
|
||||||
using MQTTnet.Core.Internal;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttOutgoingPublicationsManager
|
|
||||||
{
|
|
||||||
private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>();
|
|
||||||
private readonly AsyncGate _gate = new AsyncGate();
|
|
||||||
|
|
||||||
private readonly MqttServerOptions _options;
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
private IMqttCommunicationAdapter _adapter;
|
|
||||||
|
|
||||||
public MqttOutgoingPublicationsManager(MqttServerOptions options)
|
|
||||||
{
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(IMqttCommunicationAdapter adapter)
|
|
||||||
{
|
|
||||||
if (_cancellationTokenSource != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"{nameof(MqttOutgoingPublicationsManager)} already started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
Task.Run(() => SendPendingPublishPacketsAsync(_cancellationTokenSource.Token)).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_adapter = null;
|
|
||||||
_cancellationTokenSource?.Cancel();
|
|
||||||
_cancellationTokenSource = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Enqueue(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
|
|
||||||
{
|
|
||||||
if (senderClientSession == null) throw new ArgumentNullException(nameof(senderClientSession));
|
|
||||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
|
||||||
|
|
||||||
lock (_pendingPublishPackets)
|
|
||||||
{
|
|
||||||
_pendingPublishPackets.Add(new MqttClientPublishPacketContext(senderClientSession, publishPacket));
|
|
||||||
_gate.Set();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendPendingPublishPacketsAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _gate.WaitOneAsync();
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_adapter == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MqttClientPublishPacketContext> pendingPublishPackets;
|
|
||||||
lock (_pendingPublishPackets)
|
|
||||||
{
|
|
||||||
pendingPublishPackets = _pendingPublishPackets.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var publishPacket in pendingPublishPackets)
|
|
||||||
{
|
|
||||||
await TrySendPendingPublishPacketAsync(publishPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttOutgoingPublicationsManager), e, "Error while sending pending publish packets.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task TrySendPendingPublishPacketAsync(MqttClientPublishPacketContext publishPacketContext)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_adapter == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishPacketContext.PublishPacket.Dup = publishPacketContext.SendTries > 0;
|
|
||||||
await _adapter.SendPacketAsync(publishPacketContext.PublishPacket, _options.DefaultCommunicationTimeout);
|
|
||||||
|
|
||||||
publishPacketContext.IsSent = true;
|
|
||||||
}
|
|
||||||
catch (MqttCommunicationException exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Warning(nameof(MqttOutgoingPublicationsManager), exception, "Sending publish packet failed.");
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MqttTrace.Error(nameof(MqttOutgoingPublicationsManager), exception, "Sending publish packet failed.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
publishPacketContext.SendTries++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Cleanup()
|
|
||||||
{
|
|
||||||
lock (_pendingPublishPackets)
|
|
||||||
{
|
|
||||||
_pendingPublishPackets.RemoveAll(p => p.IsSent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Diagnostics;
|
|
||||||
using MQTTnet.Core.Internal;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttServer
|
|
||||||
{
|
|
||||||
private readonly MqttClientSessionManager _clientSessionManager;
|
|
||||||
private readonly IMqttServerAdapter _adapter;
|
|
||||||
private readonly MqttServerOptions _options;
|
|
||||||
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
|
||||||
|
|
||||||
public MqttServer(MqttServerOptions options, IMqttServerAdapter adapter)
|
|
||||||
{
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
|
|
||||||
|
|
||||||
_clientSessionManager = new MqttClientSessionManager(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
|
||||||
|
|
||||||
public void InjectClient(string identifier, IMqttCommunicationAdapter adapter)
|
|
||||||
{
|
|
||||||
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
|
|
||||||
|
|
||||||
if (_cancellationTokenSource == null) throw new InvalidOperationException("The MQTT server is not started.");
|
|
||||||
|
|
||||||
OnClientConnected(this, new MqttClientConnectedEventArgs(identifier, adapter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (_cancellationTokenSource != null) throw new InvalidOperationException("The MQTT server is already started.");
|
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
_adapter.ClientConnected += OnClientConnected;
|
|
||||||
_adapter.Start(_options);
|
|
||||||
|
|
||||||
MqttTrace.Information(nameof(MqttServer), "Started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_cancellationTokenSource?.Cancel();
|
|
||||||
_cancellationTokenSource = null;
|
|
||||||
|
|
||||||
_adapter.ClientConnected -= OnClientConnected;
|
|
||||||
_adapter.Stop();
|
|
||||||
|
|
||||||
_clientSessionManager.Clear();
|
|
||||||
|
|
||||||
MqttTrace.Information(nameof(MqttServer), "Stopped.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnClientConnected(object sender, MqttClientConnectedEventArgs eventArgs)
|
|
||||||
{
|
|
||||||
MqttTrace.Information(nameof(MqttServer), $"Client '{eventArgs.Identifier}': Connected.");
|
|
||||||
ClientConnected?.Invoke(this, eventArgs);
|
|
||||||
|
|
||||||
Task.Run(async () => await _clientSessionManager.RunClientSessionAsync(eventArgs), _cancellationTokenSource.Token).Forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MQTTnet.Core.Packets;
|
|
||||||
using MQTTnet.Core.Protocol;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public class MqttServerOptions
|
|
||||||
{
|
|
||||||
public int Port { get; set; } = 1883;
|
|
||||||
|
|
||||||
public int ConnectionBacklog { get; set; } = 10;
|
|
||||||
|
|
||||||
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
|
||||||
|
|
||||||
public Func<MqttConnectPacket, MqttConnectReturnCode> ConnectionValidator { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
|
||||||
{
|
|
||||||
public static class MqttTopicFilterComparer
|
|
||||||
{
|
|
||||||
private const char TopicLevelSeparator = '/';
|
|
||||||
|
|
||||||
public static bool IsMatch(string topic, string filter)
|
|
||||||
{
|
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
if (filter == null) throw new ArgumentNullException(nameof(filter));
|
|
||||||
|
|
||||||
if (string.Equals(topic, filter, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fragmentsTopic = topic.Split(new[] { TopicLevelSeparator }, StringSplitOptions.None);
|
|
||||||
var fragmentsFilter = filter.Split(new[] { TopicLevelSeparator }, StringSplitOptions.None);
|
|
||||||
|
|
||||||
for (var i = 0; i < fragmentsFilter.Length; i++)
|
|
||||||
{
|
|
||||||
if (fragmentsFilter[i] == "+")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragmentsFilter[i] == "#" && i == fragmentsFilter.Length - 1)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= fragmentsTopic.Length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(fragmentsFilter[i], fragmentsTopic[i]))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragmentsTopic.Length > fragmentsFilter.Length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<package >
|
|
||||||
<metadata>
|
|
||||||
<id>MQTTnet</id>
|
|
||||||
<version>2.1.1.0</version>
|
|
||||||
<authors>Christian Kratky</authors>
|
|
||||||
<owners>Christian Kratky</owners>
|
|
||||||
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
|
|
||||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
|
|
||||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
|
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
|
||||||
<description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
|
|
||||||
<releaseNotes>* Added MQTT server.</releaseNotes>
|
|
||||||
<copyright>Copyright Christian Kratky 2016-2017</copyright>
|
|
||||||
<tags>MQTT MQTTClient MQTTServer MQTTBroker Broker</tags>
|
|
||||||
</metadata>
|
|
||||||
|
|
||||||
<files>
|
|
||||||
<!-- Universal Windows -->
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.Core.dll" target="lib\uap10.0"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.dll" target="lib\uap10.0"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.pri" target="lib\uap10.0"/>
|
|
||||||
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.Core.dll" target="lib\uap10.0-arm"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.dll" target="lib\uap10.0-arm"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.pri" target="lib\uap10.0-arm"/>
|
|
||||||
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.Core.dll" target="lib\uap10.0-x64"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.dll" target="lib\uap10.0-x64"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.pri" target="lib\uap10.0-x64"/>
|
|
||||||
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.Core.dll" target="lib\uap10.0-x86"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.dll" target="lib\uap10.0-x86"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.pri" target="lib\uap10.0-x86"/>
|
|
||||||
|
|
||||||
<!-- .NET Framework -->
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\Release\MQTTnet.Core.dll" target="lib\net45"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\Release\MQTTnet.dll" target="lib\net45"/>
|
|
||||||
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.Core.dll" target="lib\net45-x86"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.dll" target="lib\net45-x86"/>
|
|
||||||
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.Core.dll" target="lib\net45-x64"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.dll" target="lib\net45-x64"/>
|
|
||||||
|
|
||||||
<!-- .NET Core App -->
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetCoreApp\bin\Release\netcoreapp1.1\MQTTnet.Core.dll" target="lib\netcoreapp1.1"/>
|
|
||||||
<file src=".\Frameworks\MQTTnet.NetCoreApp\bin\Release\netcoreapp1.1\MQTTnet.dll" target="lib\netcoreapp1.1"/>
|
|
||||||
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
@@ -1,225 +1,94 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 15.0.26228.9
|
VisualStudioVersion = 17.0.31919.166
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttClient", "Tests\MQTTnet.TestMqttClient\MQTTnet.TestMqttClient.csproj", "{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Source\MQTTnet\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}"
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.UniversalWindows", "Frameworks\MQTTnet.UniversalWindows\MQTTnet.UniversalWindows.csproj", "{BD60C727-D8E8-40C3-B8E3-C95A864AE611}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1-B9D6-40BF-81EC-86004D7765B4}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttServer", "Tests\MQTTnet.TestMqttServer\MQTTnet.TestMqttServer.csproj", "{6F8C0C0C-59EC-4921-9267-370AE113C34F}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core", "MQTTnet.Core\MQTTnet.Core.csproj", "{2ECB99E4-72D0-4C23-99BA-93D511D3967D}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{002203AF-2565-4C0D-95ED-027FDEFE0C35}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
MQTTnet.nuspec = MQTTnet.nuspec
|
LICENSE = LICENSE
|
||||||
|
README.md = README.md
|
||||||
|
CODE-OF-CONDUCT.md = CODE-OF-CONDUCT.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetCoreApp", "Frameworks\MQTTnet.NetCoreApp\MQTTnet.NetCoreApp.csproj", "{1A1B7F51-5328-4395-9D9C-07D70965825E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore", "Source\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj", "{F10C4060-F7EE-4A83-919F-FF723E72F94A}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.Rpc", "Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj", "{C444E9C8-95FA-430E-9126-274129DE16CD}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.ManagedClient", "Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj", "{C400533A-8EBA-4F0B-BF4D-295C3708604B}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{2BD01D53-4CA5-4142-BE8D-313876395E3E}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Samples", "Samples\MQTTnet.Samples.csproj", "{71CF35F5-3327-4A91-AAF4-5340F6701771}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Tests", "Source\MQTTnet.Tests\MQTTnet.Tests.csproj", "{B270F32A-9F3E-42EE-A989-813E35E29ADB}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.AspNetCore.Tests", "Source\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj", "{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Benchmarks", "Source\MQTTnet.Benchmarks\MQTTnet.Benchmarks.csproj", "{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp", "Source\MQTTnet.TestApp\MQTTnet.TestApp.csproj", "{175D5340-CC5B-4542-939D-4E7D15A0BC8D}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.AspTestApp", "Source\MQTTnet.AspTestApp\MQTTnet.AspTestApp.csproj", "{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Any CPU|Any CPU = Any CPU|Any CPU
|
|
||||||
Any CPU|ARM = Any CPU|ARM
|
|
||||||
Any CPU|x64 = Any CPU|x64
|
|
||||||
Any CPU|x86 = Any CPU|x86
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|ARM = Debug|ARM
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|ARM = Release|ARM
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
{3587E506-55A2-4EB3-99C7-DC01E42D25D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.Build.0 = Any CPU|x64
|
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.Build.0 = Any CPU|x86
|
{F10C4060-F7EE-4A83-919F-FF723E72F94A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C444E9C8-95FA-430E-9126-274129DE16CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.Build.0 = Debug|Any CPU
|
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.ActiveCfg = Debug|x64
|
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.Build.0 = Debug|x64
|
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.ActiveCfg = Debug|x86
|
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.Build.0 = Debug|x86
|
{C400533A-8EBA-4F0B-BF4D-295C3708604B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.ActiveCfg = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.Build.0 = Release|Any CPU
|
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.ActiveCfg = Release|x64
|
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.Build.0 = Release|x64
|
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.ActiveCfg = Release|x86
|
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.Build.0 = Release|x86
|
{71CF35F5-3327-4A91-AAF4-5340F6701771}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
{B270F32A-9F3E-42EE-A989-813E35E29ADB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x64.Build.0 = Any CPU|x64
|
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x86.Build.0 = Any CPU|x86
|
{A238BBBF-C75F-482D-9CC3-BB34ABA9B675}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.Build.0 = Debug|Any CPU
|
{2F516E76-AAC4-4219-B7D1-34CDD3CFF381}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.ActiveCfg = Debug|x64
|
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.Build.0 = Debug|x64
|
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.ActiveCfg = Debug|x86
|
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.Build.0 = Debug|x86
|
{175D5340-CC5B-4542-939D-4E7D15A0BC8D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.ActiveCfg = Release|Any CPU
|
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.Build.0 = Release|Any CPU
|
{72867E4C-4E15-4E8E-8FAB-AE9253286BBC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|x64
|
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x64.Build.0 = Any CPU|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x86.Build.0 = Any CPU|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.Build.0 = Release|x64
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.Build.0 = Release|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|ARM.ActiveCfg = Any CPU|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|ARM.Build.0 = Any CPU|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x64.Build.0 = Any CPU|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x86.Build.0 = Any CPU|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|ARM.ActiveCfg = Debug|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|ARM.Build.0 = Debug|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|ARM.ActiveCfg = Release|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|ARM.Build.0 = Release|ARM
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x64.Build.0 = Release|x64
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.Build.0 = Release|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.Build.0 = Any CPU|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.Build.0 = Any CPU|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.Build.0 = Release|x64
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.Build.0 = Release|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x64.Build.0 = Any CPU|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x86.Build.0 = Any CPU|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x64.Build.0 = Release|x64
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x86.Build.0 = Release|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x64.ActiveCfg = Any CPU|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x64.Build.0 = Any CPU|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x86.ActiveCfg = Any CPU|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x86.Build.0 = Any CPU|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x64.Build.0 = Release|x64
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.Build.0 = Release|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
EndGlobalSection
|
||||||
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
|
||||||
{BD60C727-D8E8-40C3-B8E3-C95A864AE611} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
|
||||||
{6F8C0C0C-59EC-4921-9267-370AE113C34F} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
|
|
||||||
{1A1B7F51-5328-4395-9D9C-07D70965825E} = {32A630A7-2598-41D7-B625-204CD906F5FB}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_PROPERTY_PATTERN_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_METHOD_CALL_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_METHOD_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||||
|
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">180</s:Int64>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/KeepUserLineBreaks/@EntryValue">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/ProcessingInstructionAttributesFormat/@EntryValue">OnDifferentLines</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/XmlDocFormatter/TagAttributesFormat/@EntryValue">OnDifferentLines</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?>
|
||||||
|
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
|
||||||
|
<TypePattern DisplayName="Non-reorderable types">
|
||||||
|
<TypePattern.Match>
|
||||||
|
<Or>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Interface" />
|
||||||
|
<Or>
|
||||||
|
<HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
|
||||||
|
<HasAttribute Name="System.Runtime.InteropServices.ComImport" />
|
||||||
|
</Or>
|
||||||
|
</And>
|
||||||
|
<Kind Is="Struct" />
|
||||||
|
<HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" />
|
||||||
|
<HasAttribute Name="JetBrains.Annotations.NoReorder" />
|
||||||
|
</Or>
|
||||||
|
</TypePattern.Match>
|
||||||
|
</TypePattern>
|
||||||
|
<TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All">
|
||||||
|
<TypePattern.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Class" />
|
||||||
|
<HasMember>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<HasAttribute Name="Xunit.FactAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="Xunit.TheoryAttribute" Inherited="True" />
|
||||||
|
</And>
|
||||||
|
</HasMember>
|
||||||
|
</And>
|
||||||
|
</TypePattern.Match>
|
||||||
|
<Entry DisplayName="Setup/Teardown Methods">
|
||||||
|
<Entry.Match>
|
||||||
|
<Or>
|
||||||
|
<Kind Is="Constructor" />
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<ImplementsInterface Name="System.IDisposable" />
|
||||||
|
</And>
|
||||||
|
</Or>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Kind Order="Constructor" />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="All other members" />
|
||||||
|
<Entry Priority="100" DisplayName="Test Methods">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<HasAttribute Name="Xunit.FactAttribute" />
|
||||||
|
<HasAttribute Name="Xunit.TheoryAttribute" />
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
</TypePattern>
|
||||||
|
<TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
|
||||||
|
<TypePattern.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Class" />
|
||||||
|
<Or>
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestFixtureSourceAttribute" Inherited="True" />
|
||||||
|
<HasMember>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestAttribute" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestCaseAttribute" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestCaseSourceAttribute" />
|
||||||
|
</And>
|
||||||
|
</HasMember>
|
||||||
|
</Or>
|
||||||
|
</And>
|
||||||
|
</TypePattern.Match>
|
||||||
|
<Entry DisplayName="Setup/Teardown Methods">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<Or>
|
||||||
|
<HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestFixtureSetUpAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestFixtureTearDownAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.OneTimeSetUpAttribute" Inherited="True" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.OneTimeTearDownAttribute" Inherited="True" />
|
||||||
|
</Or>
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="All other members" />
|
||||||
|
<Entry Priority="100" DisplayName="Test Methods">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Method" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestAttribute" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestCaseAttribute" />
|
||||||
|
<HasAttribute Name="NUnit.Framework.TestCaseSourceAttribute" />
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
</TypePattern>
|
||||||
|
<TypePattern DisplayName="Default Pattern">
|
||||||
|
<Entry Priority="100" DisplayName="Public Delegates">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Access Is="Public" />
|
||||||
|
<Kind Is="Delegate" />
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry Priority="100" DisplayName="Public Enums">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Access Is="Public" />
|
||||||
|
<Kind Is="Enum" />
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Static Fields and Constants">
|
||||||
|
<Entry.Match>
|
||||||
|
<Or>
|
||||||
|
<Kind Is="Constant" />
|
||||||
|
<And>
|
||||||
|
<Kind Is="Field" />
|
||||||
|
<Static />
|
||||||
|
</And>
|
||||||
|
</Or>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Kind Order="Constant Field" />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Fields">
|
||||||
|
<Entry.Match>
|
||||||
|
<And>
|
||||||
|
<Kind Is="Field" />
|
||||||
|
<Not>
|
||||||
|
<Static />
|
||||||
|
</Not>
|
||||||
|
</And>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Readonly />
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Constructors">
|
||||||
|
<Entry.Match>
|
||||||
|
<Kind Is="Constructor" />
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Static />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Events">
|
||||||
|
<Entry.Match>
|
||||||
|
<Kind Is="Event" />
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Properties, Indexers">
|
||||||
|
<Entry.Match>
|
||||||
|
<Or>
|
||||||
|
<Kind Is="Property" />
|
||||||
|
<Kind Is="Indexer" />
|
||||||
|
</Or>
|
||||||
|
</Entry.Match>
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Access Order="Public Internal Protected Private" />
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="All other members">
|
||||||
|
<Entry.SortBy>
|
||||||
|
<Access Order="Public Internal Protected Private" />
|
||||||
|
<Name />
|
||||||
|
</Entry.SortBy>
|
||||||
|
</Entry>
|
||||||
|
<Entry DisplayName="Nested Types">
|
||||||
|
<Entry.Match>
|
||||||
|
<Kind Is="Type" />
|
||||||
|
</Entry.Match>
|
||||||
|
</Entry>
|
||||||
|
</TypePattern>
|
||||||
|
</Patterns></s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
See the LICENSE file in the project root for more information.</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=PINGREQ/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=PINGRESP/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=PUBCOMP/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tnet/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsub/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
@@ -1,127 +1,60 @@
|
|||||||
<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/dotnet/MQTTnet/blob/master/Images/icon_det_256.png?raw=true" width="196">
|
||||||
|
<br/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
[](https://www.nuget.org/packages/MQTTnet)
|
||||||
|
[](https://github.com/dotnet/MQTTnet/actions/workflows/ci.yml)
|
||||||
|
[](https://www.myget.org/feed/mqttnet/package/nuget/MQTTnet)
|
||||||
|

|
||||||
|
[](https://gitter.im/MQTTnet/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[](https://raw.githubusercontent.com/dotnet/MQTTnet/master/LICENSE)
|
||||||
|
|
||||||
# MQTTnet
|
# MQTTnet
|
||||||
MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server. The implementation is based on the documentation from http://mqtt.org/.
|
|
||||||
|
|
||||||
## Supported frameworks
|
MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports the MQTT protocol up to version 5. It is compatible with mostly any supported .NET Framework version and CPU architecture.
|
||||||
|
|
||||||
* .NET Standard 1.1+
|
## Features
|
||||||
* .NET Core 1.1+
|
|
||||||
* .NET Core App 1.1+
|
|
||||||
* .NET Framework 4.5.2+ (x86, x64, AnyCPU)
|
|
||||||
* Universal Windows (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU)
|
|
||||||
|
|
||||||
## Supported MQTT versions
|
### General
|
||||||
|
|
||||||
* 3.1.1
|
* Async support
|
||||||
|
* TLS support for client and server (but not UWP servers)
|
||||||
|
* Extensible communication channels (e.g. In-Memory, TCP, TCP+TLS, WS)
|
||||||
|
* Lightweight (only the low level implementation of MQTT, no overhead)
|
||||||
|
* Performance optimized (processing ~150.000 messages / second)*
|
||||||
|
* Uniform API across all supported versions of the MQTT protocol
|
||||||
|
* Access to internal trace messages
|
||||||
|
* Unit tested (~636 tests)
|
||||||
|
* No external dependencies
|
||||||
|
|
||||||
## Nuget
|
\* 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_.
|
||||||
This library is available as a nuget package: https://www.nuget.org/packages/MQTTnet/
|
|
||||||
|
|
||||||
## Contributions
|
### Client
|
||||||
If you want to contribute to this project just create a pull request.
|
|
||||||
|
|
||||||
# MqttClient
|
* Communication via TCP (+TLS) or WS (WebSocket) supported
|
||||||
## Example
|
* Included core _LowLevelMqttClient_ with low level functionality
|
||||||
|
* Also included _ManagedMqttClient_ which maintains the connection and subscriptions automatically. Also application messages are queued and re-scheduled for higher QoS levels automatically.
|
||||||
|
* Rx support (via another project)
|
||||||
|
* Compatible with Microsoft Azure IoT Hub
|
||||||
|
|
||||||
```c#
|
### Server (broker)
|
||||||
var options = new MqttClientOptions
|
|
||||||
{
|
|
||||||
Server = "localhost"
|
|
||||||
};
|
|
||||||
|
|
||||||
var client = new MqttClientFactory().CreateMqttClient(options);
|
* List of connected clients available
|
||||||
client.ApplicationMessageReceived += (s, e) =>
|
* Supports connected clients with different protocol versions at the same time
|
||||||
{
|
* Able to publish its own messages (no loopback client required)
|
||||||
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
|
* Able to receive every message (no loopback client required)
|
||||||
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
|
* Extensible client credential validation
|
||||||
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
|
* Retained messages are supported including persisting via interface methods (own implementation required)
|
||||||
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
|
* WebSockets supported (via ASP.NET Core 2.0, separate nuget)
|
||||||
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
|
* A custom message interceptor can be added which allows transforming or extending every received application message
|
||||||
Console.WriteLine();
|
* Validate subscriptions and deny subscribing of certain topics depending on requesting clients
|
||||||
};
|
|
||||||
|
|
||||||
client.Connected += async (s, e) =>
|
## Code of Conduct
|
||||||
{
|
|
||||||
Console.WriteLine("### CONNECTED WITH SERVER ###");
|
|
||||||
|
|
||||||
await client.SubscribeAsync(new List<TopicFilter>
|
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
|
||||||
{
|
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
|
||||||
new TopicFilter("#", MqttQualityOfServiceLevel.AtMostOnce)
|
|
||||||
});
|
|
||||||
|
|
||||||
Console.WriteLine("### SUBSCRIBED ###");
|
## .NET Foundation
|
||||||
};
|
|
||||||
|
|
||||||
client.Disconnected += async (s, e) =>
|
This project is supported by the [.NET Foundation](https://dotnetfoundation.org).
|
||||||
{
|
|
||||||
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await client.ConnectAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine("### RECONNECTING FAILED ###");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await client.ConnectAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine("### CONNECTING FAILED ###");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
Console.ReadLine();
|
|
||||||
|
|
||||||
var applicationMessage = new MqttApplicationMessage(
|
|
||||||
"A/B/C",
|
|
||||||
Encoding.UTF8.GetBytes("Hello World"),
|
|
||||||
MqttQualityOfServiceLevel.AtLeastOnce,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
await client.PublishAsync(applicationMessage);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# MqttServer
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```c#
|
|
||||||
var options = new MqttServerOptions
|
|
||||||
{
|
|
||||||
ConnectionValidator = p =>
|
|
||||||
{
|
|
||||||
if (p.ClientId == "SpecialClient")
|
|
||||||
{
|
|
||||||
if (p.Username != "USER" || p.Password != "PASS")
|
|
||||||
{
|
|
||||||
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MqttConnectReturnCode.ConnectionAccepted;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var mqttServer = new MqttServerFactory().CreateMqttServer(options);
|
|
||||||
mqttServer.Start();
|
|
||||||
|
|
||||||
Console.WriteLine("Press any key to exit.");
|
|
||||||
Console.ReadLine();
|
|
||||||
|
|
||||||
mqttServer.Stop();
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -0,0 +1,389 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
// ReSharper disable UnusedType.Global
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using MQTTnet.Client;
|
||||||
|
using MQTTnet.Extensions.WebSocket4Net;
|
||||||
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Samples.Helpers;
|
||||||
|
|
||||||
|
namespace MQTTnet.Samples.Client;
|
||||||
|
|
||||||
|
public static class Client_Connection_Samples
|
||||||
|
{
|
||||||
|
public static async Task Connect_Client()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker.
|
||||||
|
*
|
||||||
|
* Always dispose the client when it is no longer used.
|
||||||
|
* The default version of MQTT is 3.1.1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
// Use builder classes where possible in this project.
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
// This will throw an exception if the server is not available.
|
||||||
|
// The result from this message returns additional data which was sent
|
||||||
|
// from the server. Please refer to the MQTT protocol specification for details.
|
||||||
|
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
|
||||||
|
response.DumpToConsole();
|
||||||
|
|
||||||
|
// Send a clean disconnect to the server by calling _DisconnectAsync_. Without this the TCP connection
|
||||||
|
// gets dropped and the server will handle this as a non clean disconnect (see MQTT spec for details).
|
||||||
|
var mqttClientDisconnectOptions = mqttFactory.CreateClientDisconnectOptionsBuilder().Build();
|
||||||
|
|
||||||
|
await mqttClient.DisconnectAsync(mqttClientDisconnectOptions, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_Timeout()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to an invalid broker using a timeout.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(1)))
|
||||||
|
{
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Timeout while connecting.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_Using_MQTTv5()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker using MQTTv5.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").WithProtocolVersion(MqttProtocolVersion.V500).Build();
|
||||||
|
|
||||||
|
// In MQTTv5 the response contains much more information.
|
||||||
|
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
|
||||||
|
response.DumpToConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_Using_TLS_1_2()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker using TLS 1.2 encryption.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io")
|
||||||
|
.WithTls(
|
||||||
|
o =>
|
||||||
|
{
|
||||||
|
// The used public broker sometimes has invalid certificates. This sample accepts all
|
||||||
|
// certificates. This should not be used in live environments.
|
||||||
|
o.CertificateValidationHandler = _ => true;
|
||||||
|
|
||||||
|
// The default value is determined by the OS. Set manually to force version.
|
||||||
|
o.SslProtocol = SslProtocols.Tls12;
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
using (var timeout = new CancellationTokenSource(5000))
|
||||||
|
{
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_Using_WebSocket4Net()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker using a WebSocket connection.
|
||||||
|
* Instead of the .NET implementation of WebSockets the implementaion from WebSocket4Net is used. It provides more
|
||||||
|
* encryption algorithms and supports more platforms.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory().UseWebSocket4Net();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt").Build();
|
||||||
|
|
||||||
|
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
|
||||||
|
response.DumpToConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_Using_WebSockets()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker using a WebSocket connection.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt").Build();
|
||||||
|
|
||||||
|
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
|
||||||
|
response.DumpToConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Connect_Client_With_TLS_Encryption()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample creates a simple MQTT client and connects to a public broker with enabled TLS encryption.
|
||||||
|
*
|
||||||
|
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8883)
|
||||||
|
.WithTls(
|
||||||
|
o =>
|
||||||
|
{
|
||||||
|
// The used public broker sometimes has invalid certificates. This sample accepts all
|
||||||
|
// certificates. This should not be used in live environments.
|
||||||
|
o.CertificateValidationHandler = _ => true;
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// In MQTTv5 the response contains much more information.
|
||||||
|
using (var timeout = new CancellationTokenSource(5000))
|
||||||
|
{
|
||||||
|
var response = await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
|
||||||
|
response.DumpToConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Disconnect_Clean()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample disconnects from the server with sending a DISCONNECT packet.
|
||||||
|
* This way of disconnecting is treated as a clean disconnect which will not
|
||||||
|
* trigger sending the last will etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
// Calling _DisconnectAsync_ will send a DISCONNECT packet before closing the connection.
|
||||||
|
// Using a reason code requires MQTT version 5.0.0!
|
||||||
|
await mqttClient.DisconnectAsync(MqttClientDisconnectReason.ImplementationSpecificError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Disconnect_Non_Clean()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample disconnects from the server without sending a DISCONNECT packet.
|
||||||
|
* This way of disconnecting is treated as a non clean disconnect which will
|
||||||
|
* trigger sending the last will etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
var mqttClient = mqttFactory.CreateMqttClient();
|
||||||
|
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
// Calling _Dispose_ or use of a _using_ statement will close the transport connection
|
||||||
|
// without sending a DISCONNECT packet to the server.
|
||||||
|
mqttClient.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Inspect_Certificate_Validation_Errors()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample prints the certificate information while connection. This data can be used to decide whether a connection is secure or not
|
||||||
|
* including the reason for that status.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io", 8883)
|
||||||
|
.WithTls(
|
||||||
|
o =>
|
||||||
|
{
|
||||||
|
o.CertificateValidationHandler = eventArgs =>
|
||||||
|
{
|
||||||
|
eventArgs.Certificate.Subject.DumpToConsole();
|
||||||
|
eventArgs.Certificate.GetExpirationDateString().DumpToConsole();
|
||||||
|
eventArgs.Chain.ChainPolicy.RevocationMode.DumpToConsole();
|
||||||
|
eventArgs.Chain.ChainStatus.DumpToConsole();
|
||||||
|
eventArgs.SslPolicyErrors.DumpToConsole();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// In MQTTv5 the response contains much more information.
|
||||||
|
using (var timeout = new CancellationTokenSource(5000))
|
||||||
|
{
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Ping_Server()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample sends a PINGREQ packet to the server and waits for a reply.
|
||||||
|
*
|
||||||
|
* This is only supported in METTv5.0.0+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
// This will throw an exception if the server does not reply.
|
||||||
|
await mqttClient.PingAsync(CancellationToken.None);
|
||||||
|
|
||||||
|
Console.WriteLine("The MQTT server replied to the ping request.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Reconnect_Using_Event()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample shows how to reconnect when the connection was dropped.
|
||||||
|
* This approach uses one of the events from the client.
|
||||||
|
* This approach has a risk of dead locks! Consider using the timer approach (see sample).
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
mqttClient.DisconnectedAsync += async e =>
|
||||||
|
{
|
||||||
|
if (e.ClientWasConnected)
|
||||||
|
{
|
||||||
|
// Use the current options as the new options.
|
||||||
|
await mqttClient.ConnectAsync(mqttClient.Options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Reconnect_Using_Timer()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample shows how to reconnect when the connection was dropped.
|
||||||
|
* This approach uses a custom Task/Thread which will monitor the connection status.
|
||||||
|
* This is the recommended way but requires more custom code!
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
using (var mqttClient = mqttFactory.CreateMqttClient())
|
||||||
|
{
|
||||||
|
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();
|
||||||
|
|
||||||
|
_ = Task.Run(
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
// User proper cancellation and no while(true).
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This code will also do the very first connect! So no call to _ConnectAsync_ is required in the first place.
|
||||||
|
if (!await mqttClient.TryPingAsync())
|
||||||
|
{
|
||||||
|
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
|
||||||
|
|
||||||
|
// Subscribe to topics when session is clean etc.
|
||||||
|
Console.WriteLine("The MQTT client is connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Handle the exception properly (logging etc.).
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Check the connection state every 5 seconds and perform a reconnect if required.
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||