diff --git a/.ci/mosquitto.conf b/.ci/mosquitto.conf new file mode 100644 index 0000000..4479cc6 --- /dev/null +++ b/.ci/mosquitto.conf @@ -0,0 +1,2 @@ +allow_anonymous false +password_file /home/runner/work/rust-mqtt/rust-mqtt/.ci/mqtt_pass.txt diff --git a/.ci/mqtt_pass.txt b/.ci/mqtt_pass.txt new file mode 100644 index 0000000..8c1809f --- /dev/null +++ b/.ci/mqtt_pass.txt @@ -0,0 +1 @@ +test:$7$101$XGspXBoC6refncib$u5t0Adz5h8Xn9XfYtKfa5kWrPNMGd+H7u2vbl0S8qmr/HCREZjjEyqU88QybSV0SsgmyFrXMIkCozEmnPeTm+g== \ No newline at end of file diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml new file mode 100644 index 0000000..365ae5c --- /dev/null +++ b/.github/workflows/integration_tests.yaml @@ -0,0 +1,25 @@ +on: [pull_request] + +name: IntegrationTests + +jobs: + unit_tests: + name: Integration tests + runs-on: ubuntu-latest + steps: + - name: Git checkout + uses: actions/checkout@v2 + + - name: Build + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + - run: cargo build + + - name: Start Mosquitto + run: | + sudo apt-get install mosquitto + mosquitto -c .ci/mosquitto.conf -d + + - name: Run integration tests + run: cargo test integration \ No newline at end of file diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml new file mode 100644 index 0000000..8d01707 --- /dev/null +++ b/.github/workflows/unit_tests.yaml @@ -0,0 +1,14 @@ +on: [pull_request] + +name: UnitTests + +jobs: + unit_tests: + name: Unit tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + - run: cargo test unit \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2674b3d..80e7ef8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target .idea -.vscode \ No newline at end of file +.vscode +Cargo.lock \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 49bd919..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1056 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "atomic-polyfill" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686d748538a32325b28d6411dd8a939e7ad5128e5d0023cc4fd3573db456042" -dependencies = [ - "critical-section", - "riscv-target", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "config" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" -dependencies = [ - "lazy_static", - "nom", - "rust-ini", - "serde 1.0.136", - "serde-hjson", - "serde_json", - "toml", - "yaml-rust", -] - -[[package]] -name = "cortex-m" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ff967e867ca14eba0c34ac25cd71ea98c678e741e3915d923999bb2fe7c826" -dependencies = [ - "bare-metal 0.2.5", - "bitfield", - "embedded-hal 0.2.6", - "volatile-register", -] - -[[package]] -name = "critical-section" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e191a5a6f6edad9b679777ef6b6c0f2bdd4a333f2ecb8f61c3e28109a03d70" -dependencies = [ - "bare-metal 1.0.0", - "cfg-if", - "cortex-m", - "riscv", -] - -[[package]] -name = "darling" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "defmt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fb5df4d2b06a2dbf6ba26b49031f5f45f1aafdfca4b9259719466d362f34a0" -dependencies = [ - "bitflags", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "098396b763a1786b329405f69bc3677e00d45eb4534bc9f31cd23011ee2ba267" -dependencies = [ - "defmt-parser", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "defmt-parser" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1ce010e1a51aef925c98f12ed81a4e0e96ce0185a87c33f1b3b9c8f20749c7" - -[[package]] -name = "drogue-device" -version = "0.1.0" -source = "git+https://github.com/drogue-iot/drogue-device.git?rev=ce915ad027880992789a73bfc53094e8b155c66b#ce915ad027880992789a73bfc53094e8b155c66b" -dependencies = [ - "atomic-polyfill", - "base64", - "critical-section", - "drogue-device-macros", - "embassy", - "embedded-hal 0.2.6", - "embedded-hal 1.0.0-alpha.6", - "embedded-hal-async", - "futures", - "heapless", - "log", - "rand_core", -] - -[[package]] -name = "drogue-device-macros" -version = "0.1.0" -source = "git+https://github.com/drogue-iot/drogue-device.git?rev=ce915ad027880992789a73bfc53094e8b155c66b#ce915ad027880992789a73bfc53094e8b155c66b" -dependencies = [ - "cfg-if", - "config", - "lazy_static", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "embassy" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy.git?rev=d76cd5ceaf5140c48ef97180beae156c0c0e07c8#d76cd5ceaf5140c48ef97180beae156c0c0e07c8" -dependencies = [ - "atomic-polyfill", - "cfg-if", - "cortex-m", - "critical-section", - "embassy-macros", - "embassy-traits", - "embedded-hal 0.2.6", - "futures", - "heapless", - "pin-project", -] - -[[package]] -name = "embassy-macros" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy.git?rev=d76cd5ceaf5140c48ef97180beae156c0c0e07c8#d76cd5ceaf5140c48ef97180beae156c0c0e07c8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "embassy-traits" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy.git?rev=d76cd5ceaf5140c48ef97180beae156c0c0e07c8#d76cd5ceaf5140c48ef97180beae156c0c0e07c8" -dependencies = [ - "embedded-hal 0.2.6", - "embedded-hal 1.0.0-alpha.6", - "embedded-hal-async", - "nb 1.0.0", -] - -[[package]] -name = "embedded-hal" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9" -dependencies = [ - "nb 0.1.3", - "void", -] - -[[package]] -name = "embedded-hal" -version = "1.0.0-alpha.6" -source = "git+https://github.com/embassy-rs/embedded-hal?branch=embassy#1fa64a1d2f9cc1a1ae632dbfcc4064a9f6504a3f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "embedded-hal-async" -version = "0.0.1" -source = "git+https://github.com/embassy-rs/embedded-hal?branch=embassy#1fa64a1d2f9cc1a1ae632dbfcc4064a9f6504a3f" -dependencies = [ - "embedded-hal 1.0.0-alpha.6", -] - -[[package]] -name = "env_logger" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" - -[[package]] -name = "futures-io" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" - -[[package]] -name = "futures-sink" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" - -[[package]] -name = "futures-task" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" - -[[package]] -name = "futures-util" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d076121838e03f862871315477528debffdb7462fb229216ecef91b1a3eb31eb" -dependencies = [ - "atomic-polyfill", - "defmt", - "hash32", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", -] - -[[package]] -name = "libc" -version = "0.2.116" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "mio" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" - -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "lexical-core", - "memchr", - "version_check", -] - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.14", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "parking_lot" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "riscv" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "riscv-target", -] - -[[package]] -name = "riscv-target" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "rust-ini" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" - -[[package]] -name = "rust-mqtt" -version = "0.0.1" -dependencies = [ - "drogue-device", - "embassy", - "env_logger", - "heapless", - "log", - "rand_core", - "tokio", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" - -[[package]] -name = "serde" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" - -[[package]] -name = "serde-hjson" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" -dependencies = [ - "lazy_static", - "num-traits 0.1.43", - "regex", - "serde 0.8.23", -] - -[[package]] -name = "serde_json" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" -dependencies = [ - "itoa", - "ryu", - "serde 1.0.136", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "socket2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "tokio" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" -dependencies = [ - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "once_cell", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-macros" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde 1.0.136", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile-register" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" -dependencies = [ - "vcell", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" - -[[package]] -name = "windows_i686_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" - -[[package]] -name = "windows_i686_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/Cargo.toml b/Cargo.toml index e6a4395..f48f40c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,12 @@ -[package] -name = "rust-mqtt" -version = "0.0.1" -authors = ["Ondrej Babec "] -edition = "2021" +[workspace] +members = [ + "examples/drogue", + "mqtt", +] resolver = "2" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -embassy = { version = "0.1.0", default-features = false, features = ["std"] } -drogue-device = { version = "0.1.0", default-features = false, features = ["log", "std"] } -env_logger = "0.9.0" -log = "0.4.14" -heapless = "0.7.10" -tokio = { version = "1", features = ["full"] } -rand_core = "0.6.0" - [patch.crates-io] -embassy = { git = "https://github.com/embassy-rs/embassy.git", rev = "d76cd5ceaf5140c48ef97180beae156c0c0e07c8" } -drogue-device = { git = "https://github.com/drogue-iot/drogue-device.git", rev = "ce915ad027880992789a73bfc53094e8b155c66b" } \ No newline at end of file +embassy = { git = "https://github.com/embassy-rs/embassy.git", rev = "3d6b8bd9832d5a29cab4aa21434663e6ea6f4488" } +embassy-traits = { git = "https://github.com/embassy-rs/embassy.git", rev = "3d6b8bd9832d5a29cab4aa21434663e6ea6f4488" } +embassy-net = { git = "https://github.com/embassy-rs/embassy.git", rev = "3d6b8bd9832d5a29cab4aa21434663e6ea6f4488" } +drogue-device = { git = "https://github.com/drogue-iot/drogue-device.git", rev = "62ff20e278a6a705056173171714b1bbdc078df5" } \ No newline at end of file diff --git a/README.md b/README.md index 2028dd9..e1d0c23 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,37 @@ # Rust-mqtt +## About Rust-mqtt is native MQTT client for both std and no_std environments. Client library provides async API which can be used with various executors. +Currently, supporting only MQTTv5 but everything is prepared to extend support also +for MQTTv3 which is planned during year 2022. ## Async executors -For desktop usage I reccomend using Tokio async executor and for embedded -you should use Drogue-device +For desktop usage I recommend using Tokio async executor and for embedded there is prepared wrapper for Drogue device +framework in crate [examples](examples/drogue) crate. + +## Restrains +Client supports following: +- QoS 0 & QoS 1 (All QoS 2 packets are mapped for future client extension) +- Only clean session +- Retain not supported +- Auth packet not supported +- Packet size is not limited, it is totally up to user (packet size and buffer sizes have to align) ## Building ``` cargo build ``` -## Running (on std) +## Running tests +Integration tests are written using tokio network tcp stack and can be find under tokio_net. ``` -cargo run +cargo test unit +cargo test integration ``` +## Acknowledgment +This project could not be in state in which currently is without Ulf Lilleengen and rest of the community +from [Drogue IoT](https://github.com/drogue-iot). + ## Contact For any information contact me on email \ No newline at end of file diff --git a/examples/drogue/Cargo.toml b/examples/drogue/Cargo.toml new file mode 100644 index 0000000..61155ca --- /dev/null +++ b/examples/drogue/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "embassy-network" +version = "0.0.1" +authors = ["Ondrej Babec "] +edition = "2021" +resolver = "2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +env_logger = "0.9.0" +rust-mqtt = { path = "../../mqtt"} +embassy = { version = "0.1.0", features = ["std"] } +log = "0.4.14" +embedded-hal = { version = "0.2", features = ["unproven"] } +embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy" } +embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"} + + +drogue-device = { version = "0.1.0", features = ["std"] } diff --git a/examples/drogue/src/drogue_network.rs b/examples/drogue/src/drogue_network.rs new file mode 100644 index 0000000..2e30f4f --- /dev/null +++ b/examples/drogue/src/drogue_network.rs @@ -0,0 +1,155 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publishistribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIMAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::future::Future; +use core::ops::Range; +use drogue_device::actors::net::ConnectionFactory; +use drogue_device::actors::socket::Socket; +use drogue_device::actors::tcp::TcpActor; +use drogue_device::traits::ip::{IpAddress, IpAddressV4, IpProtocol, SocketAddress}; +use drogue_device::Address; +use rust_mqtt::packet::v5::reason_codes::ReasonCode; + +use drogue_device::traits::tcp; +use drogue_device::traits::tcp::TcpStack; +use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; +use embassy::time::Delay; +use embedded_hal_async::delay::DelayUs; +use rust_mqtt::network::network_trait::{NetworkConnection, NetworkConnectionFactory}; + +pub struct DrogueNetwork +where + A: TcpActor + 'static, +{ + socket: Socket, +} + +impl DrogueNetwork +where + A: TcpActor + 'static, +{ + fn new(socket: Socket) -> Self { + Self { socket } + } +} + +impl NetworkConnection for DrogueNetwork +where + A: TcpActor + 'static, +{ + type WriteFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + type ReadFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + type CloseFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + fn send(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m> { + async move { + self.socket + .write(&buffer[0..len]) + .await + .map_err(|_| ReasonCode::NetworkError) + .map(|_| ()) + } + } + + fn receive(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m> { + async move { + self.socket + .read(buffer) + .await + .map_err(|_| ReasonCode::NetworkError) + } + } + + fn close(mut self) -> Self::CloseFuture<'m> { + async move { + self.socket + .close() + .await + .map_err(|_| ReasonCode::NetworkError) + } + } +} + +pub struct DrogueConnectionFactory +where + A: TcpActor + 'static, +{ + network: Address, +} + +impl DrogueConnectionFactory +where + A: TcpActor + 'static, +{ + pub fn new(network: Address) -> Self { + Self { network } + } +} + +impl NetworkConnectionFactory for DrogueConnectionFactory +where + A: TcpActor + 'static, +{ + type Connection = DrogueNetwork; + + type ConnectionFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + fn connect<'m>(&'m mut self, ip: [u8; 4], port: u16) -> Self::ConnectionFuture<'m> { + async move { + let mut socket = Socket::new(self.network.clone(), self.network.open().await.unwrap()); + + match socket + .connect( + IpProtocol::Tcp, + SocketAddress::new(IpAddress::new_v4(ip[0], ip[1], ip[2], ip[3]), port), + ) + .await + { + Ok(_) => { + log::trace!("Connection established"); + Ok(DrogueNetwork::new(socket)) + } + Err(e) => { + log::warn!("Error creating connection: {:?}", e); + socket.close().await.map_err(|e| ReasonCode::NetworkError)?; + Err(ReasonCode::NetworkError) + } + } + } + } +} diff --git a/examples/drogue/src/lib.rs b/examples/drogue/src/lib.rs new file mode 100644 index 0000000..5cd6f18 --- /dev/null +++ b/examples/drogue/src/lib.rs @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![no_std] +#![feature(in_band_lifetimes)] +#![macro_use] +#![allow(dead_code)] +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] +pub mod drogue_network; diff --git a/mqtt/Cargo.toml b/mqtt/Cargo.toml new file mode 100644 index 0000000..fc4b1cc --- /dev/null +++ b/mqtt/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "rust-mqtt" +version = "0.0.1" +authors = ["Ondrej Babec "] +edition = "2021" +resolver = "2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +env_logger = "0.9.0" +log = "0.4.14" +heapless = "0.7.10" +rand_core = "0.6.0" + +tokio = { version = "1", features = ["full"], optional = true } +tokio-test = { version = "0.4.2", optional = true} + +[dev-dependencies] +tokio = { version = "1", features = ["full"] } +tokio-test = "0.4.2" + +[features] +default = ["tokio", "std", "tokio-test"] +std = [] +no_std = [] \ No newline at end of file diff --git a/src/client/client_config.rs b/mqtt/src/client/client_config.rs similarity index 97% rename from src/client/client_config.rs rename to mqtt/src/client/client_config.rs index 546def9..7a7703b 100644 --- a/src/client/client_config.rs +++ b/mqtt/src/client/client_config.rs @@ -22,10 +22,10 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::property::Property; use crate::packet::v5::publish_packet::QualityOfService; use crate::utils::types::{BinaryData, EncodedString}; +use heapless::Vec; pub struct ClientConfig<'a, const MAX_PROPERTIES: usize> { pub qos: QualityOfService, @@ -41,7 +41,7 @@ pub struct ClientConfig<'a, const MAX_PROPERTIES: usize> { impl<'a, const MAX_PROPERTIES: usize> ClientConfig<'a, MAX_PROPERTIES> { pub fn new() -> Self { - Self { + Self { qos: QualityOfService::QoS0, keep_alive: 60, client_id: EncodedString::new(), @@ -80,7 +80,7 @@ impl<'a, const MAX_PROPERTIES: usize> ClientConfig<'a, MAX_PROPERTIES> { } } - pub fn add_max_packet_size_as_prop(& mut self) -> u32 { + pub fn add_max_packet_size_as_prop(&mut self) -> u32 { if self.properties.len() < MAX_PROPERTIES { let prop = Property::MaximumPacketSize(self.max_packet_size); self.properties.push(prop); diff --git a/src/client/client_v5.rs b/mqtt/src/client/client_v5.rs similarity index 87% rename from src/client/client_v5.rs rename to mqtt/src/client/client_v5.rs index eadffb7..3d051dc 100644 --- a/src/client/client_v5.rs +++ b/mqtt/src/client/client_v5.rs @@ -1,5 +1,29 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + use crate::client::client_config::ClientConfig; -use crate::network::network_trait::Network; +use crate::network::network_trait::NetworkConnection; use crate::packet::v5::connack_packet::ConnackPacket; use crate::packet::v5::connect_packet::ConnectPacket; use crate::packet::v5::disconnect_packet::DisconnectPacket; @@ -17,8 +41,6 @@ use crate::utils::rng_generator::CountingRng; use crate::utils::types::BufferError; use heapless::Vec; use rand_core::RngCore; -use crate::packet::v5::property::Property; -use crate::packet::v5::reason_codes::ReasonCode::BuffError; pub struct MqttClientV5<'a, T, const MAX_PROPERTIES: usize> { network_driver: &'a mut T, @@ -32,7 +54,7 @@ pub struct MqttClientV5<'a, T, const MAX_PROPERTIES: usize> { impl<'a, T, const MAX_PROPERTIES: usize> MqttClientV5<'a, T, MAX_PROPERTIES> where - T: Network, + T: NetworkConnection, { pub fn new( network_driver: &'a mut T, @@ -82,7 +104,10 @@ where if let Err(err) = packet.decode(&mut BuffReader::new(self.buffer, self.buffer_len)) { if err == BufferError::PacketTypeMismatch { let mut disc = DisconnectPacket::<'b, 5>::new(); - if disc.decode(&mut BuffReader::new(self.buffer, self.buffer_len)).is_ok() { + if disc + .decode(&mut BuffReader::new(self.buffer, self.buffer_len)) + .is_ok() + { log::error!("Client was disconnected with reason: "); return Err(ReasonCode::from(disc.disconnect_reason)); } @@ -272,7 +297,10 @@ where { if err == BufferError::PacketTypeMismatch { let mut disc = DisconnectPacket::<'b, 5>::new(); - if disc.decode(&mut BuffReader::new(self.buffer, self.buffer_len)).is_ok() { + if disc + .decode(&mut BuffReader::new(self.buffer, self.buffer_len)) + .is_ok() + { log::error!("Client was disconnected with reason: "); return Err(ReasonCode::from(disc.disconnect_reason)); } diff --git a/src/client/mod.rs b/mqtt/src/client/mod.rs similarity index 97% rename from src/client/mod.rs rename to mqtt/src/client/mod.rs index 6e6b344..445d2ba 100644 --- a/src/client/mod.rs +++ b/mqtt/src/client/mod.rs @@ -22,5 +22,6 @@ * SOFTWARE. */ +#[allow(unused_must_use)] pub mod client_config; pub mod client_v5; diff --git a/src/encoding/mod.rs b/mqtt/src/encoding/mod.rs similarity index 100% rename from src/encoding/mod.rs rename to mqtt/src/encoding/mod.rs diff --git a/src/encoding/variable_byte_integer.rs b/mqtt/src/encoding/variable_byte_integer.rs similarity index 100% rename from src/encoding/variable_byte_integer.rs rename to mqtt/src/encoding/variable_byte_integer.rs diff --git a/src/lib.rs b/mqtt/src/lib.rs similarity index 97% rename from src/lib.rs rename to mqtt/src/lib.rs index e1d08c9..bb592ae 100644 --- a/src/lib.rs +++ b/mqtt/src/lib.rs @@ -29,12 +29,10 @@ #![feature(type_alias_impl_trait)] #![feature(generic_associated_types)] -extern crate alloc; - pub mod client; pub mod encoding; pub mod network; pub mod packet; -pub mod tokio_network; -pub mod utils; pub mod tests; +pub mod tokio_net; +pub mod utils; diff --git a/src/network/mod.rs b/mqtt/src/network/mod.rs similarity index 100% rename from src/network/mod.rs rename to mqtt/src/network/mod.rs diff --git a/mqtt/src/network/network_trait.rs b/mqtt/src/network/network_trait.rs new file mode 100644 index 0000000..0dae540 --- /dev/null +++ b/mqtt/src/network/network_trait.rs @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::future::Future; + +use crate::packet::v5::reason_codes::ReasonCode; + +#[derive(Debug)] +pub enum NetworkError { + Connection, + Unknown, + QoSAck, + IDNotMatchedOnAck, + NoMatchingSubs, +} + +pub trait NetworkConnectionFactory: Sized { + type Connection: NetworkConnection; + + type ConnectionFuture<'m>: Future> + where + Self: 'm; + + fn connect<'m>(&'m mut self, ip: [u8; 4], port: u16) -> Self::ConnectionFuture<'m>; +} + +pub trait NetworkConnection { + type WriteFuture<'m>: Future> + where + Self: 'm; + + type ReadFuture<'m>: Future> + where + Self: 'm; + + type CloseFuture<'m>: Future> + where + Self: 'm; + + fn send(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m>; + + fn receive(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m>; + + fn close(self) -> Self::CloseFuture<'m>; +} diff --git a/src/tests/unit/encoding/mod.rs b/mqtt/src/packet/mod.rs similarity index 96% rename from src/tests/unit/encoding/mod.rs rename to mqtt/src/packet/mod.rs index 3dc3a6b..c108ca5 100644 --- a/src/tests/unit/encoding/mod.rs +++ b/mqtt/src/packet/mod.rs @@ -22,4 +22,5 @@ * SOFTWARE. */ -pub mod variable_byte_integer_unit; \ No newline at end of file +#[allow(unused_must_use)] +pub mod v5; diff --git a/src/packet/v5/auth_packet.rs b/mqtt/src/packet/v5/auth_packet.rs similarity index 100% rename from src/packet/v5/auth_packet.rs rename to mqtt/src/packet/v5/auth_packet.rs diff --git a/src/packet/v5/connack_packet.rs b/mqtt/src/packet/v5/connack_packet.rs similarity index 99% rename from src/packet/v5/connack_packet.rs rename to mqtt/src/packet/v5/connack_packet.rs index 966ba93..c42c1fd 100644 --- a/src/packet/v5/connack_packet.rs +++ b/mqtt/src/packet/v5/connack_packet.rs @@ -42,8 +42,7 @@ pub struct ConnackPacket<'a, const MAX_PROPERTIES: usize> { pub properties: Vec, MAX_PROPERTIES>, } -impl<'a, const MAX_PROPERTIES: usize> ConnackPacket<'a, MAX_PROPERTIES> { -} +impl<'a, const MAX_PROPERTIES: usize> ConnackPacket<'a, MAX_PROPERTIES> {} impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for ConnackPacket<'a, MAX_PROPERTIES> { fn new() -> Self { diff --git a/src/packet/v5/connect_packet.rs b/mqtt/src/packet/v5/connect_packet.rs similarity index 99% rename from src/packet/v5/connect_packet.rs rename to mqtt/src/packet/v5/connect_packet.rs index 7a5b44d..5135262 100644 --- a/src/packet/v5/connect_packet.rs +++ b/mqtt/src/packet/v5/connect_packet.rs @@ -99,7 +99,7 @@ impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize> self.connect_flags = self.connect_flags | 0x40; } - pub fn add_client_id(& mut self, id: &EncodedString<'a>) { + pub fn add_client_id(&mut self, id: &EncodedString<'a>) { self.client_id = (*id).clone(); } } diff --git a/src/packet/v5/disconnect_packet.rs b/mqtt/src/packet/v5/disconnect_packet.rs similarity index 100% rename from src/packet/v5/disconnect_packet.rs rename to mqtt/src/packet/v5/disconnect_packet.rs diff --git a/src/packet/v5/mod.rs b/mqtt/src/packet/v5/mod.rs similarity index 100% rename from src/packet/v5/mod.rs rename to mqtt/src/packet/v5/mod.rs diff --git a/src/packet/v5/mqtt_packet.rs b/mqtt/src/packet/v5/mqtt_packet.rs similarity index 95% rename from src/packet/v5/mqtt_packet.rs rename to mqtt/src/packet/v5/mqtt_packet.rs index af64fa8..003afcb 100644 --- a/src/packet/v5/mqtt_packet.rs +++ b/mqtt/src/packet/v5/mqtt_packet.rs @@ -22,10 +22,10 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::packet_type::PacketType; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::BufferError; +use heapless::Vec; use super::property::Property; @@ -45,9 +45,12 @@ pub trait Packet<'a> { /// Method enables pushing new property into packet properties fn push_to_properties(&mut self, property: Property<'a>); /// Returns if property is allowed for packet - fn property_allowed(& mut self, property: & Property<'a>) -> bool; + fn property_allowed(&mut self, property: &Property<'a>) -> bool; /// Method enables adding properties from client config - each packet decides if property can be used with that or not - fn add_properties(& mut self, properties: &Vec, MAX_PROPERTIES>) -> u32 { + fn add_properties( + &mut self, + properties: &Vec, MAX_PROPERTIES>, + ) -> u32 { let mut i = 0; let max = properties.len(); let mut res: u32 = 0; diff --git a/src/packet/v5/packet_type.rs b/mqtt/src/packet/v5/packet_type.rs similarity index 100% rename from src/packet/v5/packet_type.rs rename to mqtt/src/packet/v5/packet_type.rs diff --git a/src/packet/v5/pingreq_packet.rs b/mqtt/src/packet/v5/pingreq_packet.rs similarity index 100% rename from src/packet/v5/pingreq_packet.rs rename to mqtt/src/packet/v5/pingreq_packet.rs diff --git a/src/packet/v5/pingresp_packet.rs b/mqtt/src/packet/v5/pingresp_packet.rs similarity index 100% rename from src/packet/v5/pingresp_packet.rs rename to mqtt/src/packet/v5/pingresp_packet.rs diff --git a/src/packet/v5/property.rs b/mqtt/src/packet/v5/property.rs similarity index 98% rename from src/packet/v5/property.rs rename to mqtt/src/packet/v5/property.rs index 1a0ada7..8595b89 100644 --- a/src/packet/v5/property.rs +++ b/mqtt/src/packet/v5/property.rs @@ -27,8 +27,7 @@ use crate::utils::buffer_reader::BuffReader; use crate::utils::buffer_writer::BuffWriter; use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair}; -#[derive(Debug)] -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum Property<'a> { PayloadFormat(u8), MessageExpiryInterval(u32), @@ -214,7 +213,10 @@ impl<'a> Property<'a> { Property::ContentType(u) => u.len(), Property::ResponseTopic(u) => u.len(), Property::CorrelationData(u) => u.len(), - Property::SubscriptionIdentifier(u) => VariableByteIntegerEncoder::len(VariableByteIntegerEncoder::encode(*u).unwrap()) as u16, + Property::SubscriptionIdentifier(u) => { + VariableByteIntegerEncoder::len(VariableByteIntegerEncoder::encode(*u).unwrap()) + as u16 + } Property::SessionExpiryInterval(_u) => 4, Property::AssignedClientIdentifier(u) => u.len(), Property::ServerKeepAlive(_u) => 2, diff --git a/src/packet/v5/puback_packet.rs b/mqtt/src/packet/v5/puback_packet.rs similarity index 100% rename from src/packet/v5/puback_packet.rs rename to mqtt/src/packet/v5/puback_packet.rs diff --git a/src/packet/v5/pubcomp_packet.rs b/mqtt/src/packet/v5/pubcomp_packet.rs similarity index 100% rename from src/packet/v5/pubcomp_packet.rs rename to mqtt/src/packet/v5/pubcomp_packet.rs diff --git a/src/packet/v5/publish_packet.rs b/mqtt/src/packet/v5/publish_packet.rs similarity index 100% rename from src/packet/v5/publish_packet.rs rename to mqtt/src/packet/v5/publish_packet.rs diff --git a/src/packet/v5/pubrec_packet.rs b/mqtt/src/packet/v5/pubrec_packet.rs similarity index 100% rename from src/packet/v5/pubrec_packet.rs rename to mqtt/src/packet/v5/pubrec_packet.rs diff --git a/src/packet/v5/pubrel_packet.rs b/mqtt/src/packet/v5/pubrel_packet.rs similarity index 100% rename from src/packet/v5/pubrel_packet.rs rename to mqtt/src/packet/v5/pubrel_packet.rs diff --git a/src/packet/v5/reason_codes.rs b/mqtt/src/packet/v5/reason_codes.rs similarity index 87% rename from src/packet/v5/reason_codes.rs rename to mqtt/src/packet/v5/reason_codes.rs index 808423f..57f62bf 100644 --- a/src/packet/v5/reason_codes.rs +++ b/mqtt/src/packet/v5/reason_codes.rs @@ -1,7 +1,30 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + use core::fmt::{Display, Formatter}; -#[derive(Debug)] -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub enum ReasonCode { Success, GrantedQoS1, @@ -46,6 +69,7 @@ pub enum ReasonCode { MaximumConnectTime, SubscriptionIdentifiersNotSupported, WildcardSubscriptionNotSupported, + TimerNotSupported, BuffError, NetworkError, } @@ -96,6 +120,7 @@ impl Into for ReasonCode { ReasonCode::MaximumConnectTime => 0xA0, ReasonCode::SubscriptionIdentifiersNotSupported => 0xA1, ReasonCode::WildcardSubscriptionNotSupported => 0xA2, + ReasonCode::TimerNotSupported => 0xFD, ReasonCode::BuffError => 0xFE, ReasonCode::NetworkError => 0xFF, }; @@ -147,6 +172,7 @@ impl From for ReasonCode { 0xA0 => ReasonCode::MaximumConnectTime, 0xA1 => ReasonCode::SubscriptionIdentifiersNotSupported, 0xA2 => ReasonCode::WildcardSubscriptionNotSupported, + 0xFD => ReasonCode::TimerNotSupported, 0xFE => ReasonCode::BuffError, _ => ReasonCode::NetworkError, }; @@ -207,6 +233,7 @@ impl Display for ReasonCode { ReasonCode::WildcardSubscriptionNotSupported => { write!(f, "Wildcard subscription not supported!") } + ReasonCode::TimerNotSupported => write!(f, "Timer implementation is not provided"), ReasonCode::BuffError => write!(f, "Error encountered during write / read from packet"), ReasonCode::NetworkError => write!(f, "Unknown error!"), } diff --git a/src/packet/v5/suback_packet.rs b/mqtt/src/packet/v5/suback_packet.rs similarity index 96% rename from src/packet/v5/suback_packet.rs rename to mqtt/src/packet/v5/suback_packet.rs index 16bb9ec..a8eff84 100644 --- a/src/packet/v5/suback_packet.rs +++ b/mqtt/src/packet/v5/suback_packet.rs @@ -22,8 +22,8 @@ * SOFTWARE. */ -use heapless::Vec; use crate::encoding::variable_byte_integer::VariableByteIntegerEncoder; +use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::utils::buffer_reader::BuffReader; @@ -48,10 +48,12 @@ impl<'a, const MAX_REASONS: usize, const MAX_PROPERTIES: usize> &mut self, buff_reader: &mut BuffReader<'a>, ) -> Result<(), BufferError> { - let rm_ln_ln = VariableByteIntegerEncoder::len(VariableByteIntegerEncoder::encode(self.remain_len).unwrap()); + let rm_ln_ln = VariableByteIntegerEncoder::len( + VariableByteIntegerEncoder::encode(self.remain_len).unwrap(), + ); let max = self.remain_len as usize + rm_ln_ln + 1; if buff_reader.position >= max { - return Ok(()) + return Ok(()); } loop { self.reason_codes.push(buff_reader.read_u8()?); diff --git a/src/packet/v5/subscription_packet.rs b/mqtt/src/packet/v5/subscription_packet.rs similarity index 100% rename from src/packet/v5/subscription_packet.rs rename to mqtt/src/packet/v5/subscription_packet.rs diff --git a/src/packet/v5/unsuback_packet.rs b/mqtt/src/packet/v5/unsuback_packet.rs similarity index 100% rename from src/packet/v5/unsuback_packet.rs rename to mqtt/src/packet/v5/unsuback_packet.rs diff --git a/src/packet/v5/unsubscription_packet.rs b/mqtt/src/packet/v5/unsubscription_packet.rs similarity index 100% rename from src/packet/v5/unsubscription_packet.rs rename to mqtt/src/packet/v5/unsubscription_packet.rs diff --git a/src/tests/integration/integration_test_single.rs b/mqtt/src/tests/integration/integration_test_single.rs similarity index 52% rename from src/tests/integration/integration_test_single.rs rename to mqtt/src/tests/integration/integration_test_single.rs index 71e4fa5..b621c76 100644 --- a/src/tests/integration/integration_test_single.rs +++ b/mqtt/src/tests/integration/integration_test_single.rs @@ -21,25 +21,28 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - +extern crate alloc; use alloc::string::String; use core::time::Duration; -use heapless::Vec; -use tokio::{join, task}; +use std::future::Future; use tokio::time::sleep; +use tokio::{join, task}; +use tokio_test::assert_ok; + use crate::client::client_config::ClientConfig; use crate::client::client_v5::MqttClientV5; -use crate::network::network_trait::Network; +use crate::network::network_trait::{NetworkConnection, NetworkConnectionFactory}; use crate::packet::v5::property::Property; use crate::packet::v5::publish_packet::QualityOfService; +use crate::packet::v5::reason_codes::ReasonCode; use crate::packet::v5::reason_codes::ReasonCode::NotAuthorized; -use crate::tokio_network::TokioNetwork; +use crate::tokio_net::tokio_network::{TokioNetwork, TokioNetworkFactory}; +use crate::utils::types::BufferError; static IP: [u8; 4] = [127, 0, 0, 1]; static PORT: u16 = 1883; static USERNAME: &str = "test"; static PASSWORD: &str = "testPass"; -static TOPIC: &str = "test/topic"; static MSG: &str = "testMessage"; fn init() { @@ -49,32 +52,33 @@ fn init() { .try_init(); } -async fn publish_core<'b>(client: & mut MqttClientV5<'b, TokioNetwork, 5>) { - log::info!("[Publisher] Connection to broker with username {} and password {}", USERNAME, PASSWORD); - let mut result = { - client.connect_to_broker().await - }; - assert!(result.is_ok()); - +async fn publish_core<'b>( + client: &mut MqttClientV5<'b, TokioNetwork, 5>, + topic: &str, +) -> Result<(), ReasonCode> { + log::info!( + "[Publisher] Connection to broker with username {} and password {}", + USERNAME, + PASSWORD + ); + let mut result = { client.connect_to_broker().await }; + assert_ok!(result); log::info!("[Publisher] Waiting {} seconds before sending", 5); sleep(Duration::from_secs(5)).await; - log::info!("[Publisher] Sending new message {}", MSG); - result = { - client.send_message(TOPIC, MSG).await - }; - assert!(result.is_ok()); + log::info!("[Publisher] Sending new message {} to topic {}", MSG, topic); + result = { client.send_message(topic, MSG).await }; + assert_ok!(result); log::info!("[Publisher] Disconnecting!"); - result = { - client.disconnect().await - }; - assert!(result.is_ok()); + result = { client.disconnect().await }; + assert_ok!(result); + Ok(()) } -async fn publish(qos: QualityOfService) { - let mut tokio_network: TokioNetwork = TokioNetwork::new(IP, PORT); - tokio_network.create_connection().await; +async fn publish(qos: QualityOfService, topic: &str) -> Result<(), ReasonCode> { + let mut tokio_factory: TokioNetworkFactory = TokioNetworkFactory::new(); + let mut tokio_network: TokioNetwork = tokio_factory.connect(IP, PORT).await?; let mut config = ClientConfig::new(); config.add_qos(qos); config.add_username(USERNAME); @@ -91,40 +95,40 @@ async fn publish(qos: QualityOfService) { 80, config, ); - publish_core(& mut client) - .await; + publish_core(&mut client, topic).await } -async fn receive_core<'b>(client: & mut MqttClientV5<'b, TokioNetwork, 5>) { - log::info!("[Receiver] Connection to broker with username {} and password {}", USERNAME, PASSWORD); - let mut result = {client.connect_to_broker().await}; - assert!(result.is_ok()); - - log::info!("[Receiver] Subscribing to topic {}", TOPIC); - result = { - client.subscribe_to_topic(TOPIC).await - }; - assert!(result.is_ok()); +async fn receive_core<'b>( + client: &mut MqttClientV5<'b, TokioNetwork, 5>, + topic: &str, +) -> Result<(), ReasonCode> { + log::info!( + "[Receiver] Connection to broker with username {} and password {}", + USERNAME, + PASSWORD + ); + let mut result = { client.connect_to_broker().await }; + assert_ok!(result); + log::info!("[Receiver] Subscribing to topic {}", topic); + result = { client.subscribe_to_topic(topic).await }; + assert_ok!(result); log::info!("[Receiver] Waiting for new message!"); - let msg = { - client.receive_message().await - }; - assert!(msg.is_ok()); - let act_message = String::from_utf8_lossy(msg.unwrap()); + let msg = { client.receive_message().await }; + assert_ok!(msg); + let act_message = String::from_utf8_lossy(msg?); log::info!("[Receiver] Got new message: {}", act_message); assert_eq!(act_message, MSG); log::info!("[Receiver] Disconnecting"); - result = { - client.disconnect().await - }; - assert!(result.is_ok()); + result = { client.disconnect().await }; + assert_ok!(result); + Ok(()) } -async fn receive(qos: QualityOfService) { - let mut tokio_network: TokioNetwork = TokioNetwork::new(IP, PORT); - tokio_network.create_connection().await; +async fn receive(qos: QualityOfService, topic: &str) -> Result<(), ReasonCode> { + let mut tokio_factory: TokioNetworkFactory = TokioNetworkFactory::new(); + let mut tokio_network: TokioNetwork = tokio_factory.connect(IP, PORT).await?; let mut config = ClientConfig::new(); config.add_qos(qos); config.add_username(USERNAME); @@ -142,14 +146,13 @@ async fn receive(qos: QualityOfService) { 100, config, ); - receive_core(& mut client) - .await; + + receive_core(&mut client, topic).await } - -async fn receive_with_wrong_cred(qos: QualityOfService) { - let mut tokio_network: TokioNetwork = TokioNetwork::new(IP, PORT); - tokio_network.create_connection().await; +async fn receive_with_wrong_cred(qos: QualityOfService) -> Result<(), ReasonCode> { + let mut tokio_factory: TokioNetworkFactory = TokioNetworkFactory::new(); + let mut tokio_network: TokioNetwork = tokio_factory.connect(IP, PORT).await?; let mut config = ClientConfig::new(); config.add_qos(qos); config.add_username("xyz"); @@ -168,10 +171,15 @@ async fn receive_with_wrong_cred(qos: QualityOfService) { config, ); - log::info!("[Receiver] Connection to broker with username {} and password {}", "xyz", PASSWORD); - let mut result = {client.connect_to_broker().await}; + log::info!( + "[Receiver] Connection to broker with username {} and password {}", + "xyz", + PASSWORD + ); + let result = { client.connect_to_broker().await }; assert!(result.is_err()); assert_eq!(result.unwrap_err(), NotAuthorized); + Ok(()) } #[tokio::test] @@ -179,17 +187,15 @@ async fn simple_publish_recv() { init(); log::info!("Running simple integration test"); - let recv = task::spawn(async move { - receive(QualityOfService::QoS0) - .await; - }); + let recv = + task::spawn(async move { receive(QualityOfService::QoS0, "test/recv/simple").await }); - let publ = task::spawn(async move { - publish(QualityOfService::QoS0) - .await; - }); + let publ = + task::spawn(async move { publish(QualityOfService::QoS0, "test/recv/simple").await }); - join!(recv, publ); + let (r, p) = join!(recv, publ); + assert_ok!(r.unwrap()); + assert_ok!(p.unwrap()); } #[tokio::test] @@ -197,36 +203,26 @@ async fn simple_publish_recv_qos() { init(); log::info!("Running simple integration test with Quality of Service 1"); - let recv = task::spawn(async move { - receive(QualityOfService::QoS1) - .await; - }); + let recv = task::spawn(async move { receive(QualityOfService::QoS1, "test/recv/qos").await }); - let publ = task::spawn(async move { - publish(QualityOfService::QoS1) - .await; - }); - join!(recv, publ); + let publ = task::spawn(async move { publish(QualityOfService::QoS1, "test/recv/qos").await }); + let (r, p) = join!(recv, publ); + assert_ok!(r.unwrap()); + assert_ok!(p.unwrap()); } #[tokio::test] async fn simple_publish_recv_wrong_cred() { init(); - log::info!("Running simple integration test with Quality of Service 1"); + log::info!("Running simple integration test wrong credentials"); - let recv = task::spawn(async move { - receive_with_wrong_cred(QualityOfService::QoS1) - .await; - }); + let recv = task::spawn(async move { receive_with_wrong_cred(QualityOfService::QoS1).await }); - let recv_right = task::spawn(async move { - receive(QualityOfService::QoS0) - .await; - }); + let recv_right = + task::spawn(async move { receive(QualityOfService::QoS0, "test/recv/wrong").await }); - let publ = task::spawn(async move { - publish(QualityOfService::QoS1) - .await; - }); - join!(recv, recv_right, publ); -} \ No newline at end of file + let publ = task::spawn(async move { publish(QualityOfService::QoS1, "test/recv/wrong").await }); + let (r, rv, p) = join!(recv, recv_right, publ); + assert_ok!(rv.unwrap()); + assert_ok!(p.unwrap()); +} diff --git a/src/tests/integration/mod.rs b/mqtt/src/tests/integration/mod.rs similarity index 97% rename from src/tests/integration/mod.rs rename to mqtt/src/tests/integration/mod.rs index c47f092..10c7c40 100644 --- a/src/tests/integration/mod.rs +++ b/mqtt/src/tests/integration/mod.rs @@ -21,5 +21,4 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -pub mod integration_test_single; \ No newline at end of file +pub mod integration_test_single; diff --git a/src/tests/mod.rs b/mqtt/src/tests/mod.rs similarity index 89% rename from src/tests/mod.rs rename to mqtt/src/tests/mod.rs index 6c30d3c..f80e190 100644 --- a/src/tests/mod.rs +++ b/mqtt/src/tests/mod.rs @@ -23,5 +23,11 @@ */ #[cfg(test)] +#[allow(unused_must_use)] pub mod unit; -pub mod integration; \ No newline at end of file + +#[allow(dead_code)] +#[allow(unused_must_use)] +#[allow(unused_imports)] +#[cfg(feature = "tokio")] +pub mod integration; diff --git a/src/tests/unit/packet/mod.rs b/mqtt/src/tests/unit/encoding/mod.rs similarity index 96% rename from src/tests/unit/packet/mod.rs rename to mqtt/src/tests/unit/encoding/mod.rs index b28ef3c..af66e34 100644 --- a/src/tests/unit/packet/mod.rs +++ b/mqtt/src/tests/unit/encoding/mod.rs @@ -22,4 +22,4 @@ * SOFTWARE. */ -pub mod v5; \ No newline at end of file +pub mod variable_byte_integer_unit; diff --git a/src/tests/unit/encoding/variable_byte_integer_unit.rs b/mqtt/src/tests/unit/encoding/variable_byte_integer_unit.rs similarity index 95% rename from src/tests/unit/encoding/variable_byte_integer_unit.rs rename to mqtt/src/tests/unit/encoding/variable_byte_integer_unit.rs index d812b5e..3fbf732 100644 --- a/src/tests/unit/encoding/variable_byte_integer_unit.rs +++ b/mqtt/src/tests/unit/encoding/variable_byte_integer_unit.rs @@ -22,7 +22,9 @@ * SOFTWARE. */ -use crate::encoding::variable_byte_integer::{VariableByteInteger, VariableByteIntegerDecoder, VariableByteIntegerEncoder}; +use crate::encoding::variable_byte_integer::{ + VariableByteInteger, VariableByteIntegerDecoder, VariableByteIntegerEncoder, +}; use crate::utils::types::BufferError; #[test] @@ -75,4 +77,4 @@ fn test_encode_max() { let encoded = VariableByteIntegerEncoder::encode(288_435_455); assert!(encoded.is_err()); assert_eq!(encoded.unwrap_err(), BufferError::EncodingError); -} \ No newline at end of file +} diff --git a/src/tests/unit/mod.rs b/mqtt/src/tests/unit/mod.rs similarity index 98% rename from src/tests/unit/mod.rs rename to mqtt/src/tests/unit/mod.rs index ee493a5..05831e7 100644 --- a/src/tests/unit/mod.rs +++ b/mqtt/src/tests/unit/mod.rs @@ -22,6 +22,6 @@ * SOFTWARE. */ -pub mod utils; pub mod encoding; -pub mod packet; \ No newline at end of file +pub mod packet; +pub mod utils; diff --git a/src/packet/mod.rs b/mqtt/src/tests/unit/packet/mod.rs similarity index 100% rename from src/packet/mod.rs rename to mqtt/src/tests/unit/packet/mod.rs diff --git a/src/tests/unit/packet/v5/connack_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/connack_packet_unit.rs similarity index 77% rename from src/tests/unit/packet/v5/connack_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/connack_packet_unit.rs index 49efb53..1f126b8 100644 --- a/src/tests/unit/packet/v5/connack_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/connack_packet_unit.rs @@ -38,26 +38,49 @@ fn test_encode() { connack.connect_reason_code = ReasonCode::ServerMoved.into(); connack.ack_flags = 0x45; - let res = connack.encode(& mut buffer, 100); + let res = connack.encode(&mut buffer, 100); assert!(res.is_ok()); - assert_eq!(buffer[0..res.unwrap()], [0x20, 0x06, 0x45, ReasonCode::ServerMoved.into(), 0x03, 0x21, 0x00, 0x15]) + assert_eq!( + buffer[0..res.unwrap()], + [ + 0x20, + 0x06, + 0x45, + ReasonCode::ServerMoved.into(), + 0x03, + 0x21, + 0x00, + 0x15 + ] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 8] = [0x20, 0x06, 0x45, ReasonCode::ServerMoved.into(), 0x03, 0x21, 0x00, 0x15]; + let mut buffer: [u8; 8] = [ + 0x20, + 0x06, + 0x45, + ReasonCode::ServerMoved.into(), + 0x03, + 0x21, + 0x00, + 0x15, + ]; let mut connack_res = ConnackPacket::<2>::new(); - let res = connack_res.decode(& mut BuffReader::new(& mut buffer, 8)); + let res = connack_res.decode(&mut BuffReader::new(&mut buffer, 8)); assert!(res.is_ok()); assert_eq!(connack_res.property_len, 3); assert_eq!(connack_res.ack_flags, 0x45); - assert_eq!(connack_res.connect_reason_code, ReasonCode::ServerMoved.into()); + assert_eq!( + connack_res.connect_reason_code, + ReasonCode::ServerMoved.into() + ); assert_eq!(connack_res.property_len, 3); let prop = connack_res.properties.get(0).unwrap(); assert_eq!(<&Property as Into>::into(prop), 0x21); if let Property::ReceiveMaximum(u) = *prop { assert_eq!(u, 21); } - -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/connect_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/connect_packet_unit.rs similarity index 83% rename from src/tests/unit/packet/v5/connect_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/connect_packet_unit.rs index 829093d..dafff4b 100644 --- a/src/tests/unit/packet/v5/connect_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/connect_packet_unit.rs @@ -29,10 +29,14 @@ use crate::packet::v5::mqtt_packet::Packet; fn test_encode() { let mut buffer: [u8; 100] = [0; 100]; let mut connect = ConnectPacket::<1, 0>::clean(); - let res = connect.encode(& mut buffer, 100); + let res = connect.encode(&mut buffer, 100); assert!(res.is_ok()); - assert_eq!(buffer[0..res.unwrap()], [0x10, 0x10, 0x00, 0x04, 0x4d, 0x51, - 0x54, 0x54, 0x05, 0x02, 0x00, 0x3c, - 0x03, 0x21, 0x00, 0x14, 0x00, 0x00]) -} \ No newline at end of file + assert_eq!( + buffer[0..res.unwrap()], + [ + 0x10, 0x10, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x05, 0x02, 0x00, 0x3c, 0x03, 0x21, + 0x00, 0x14, 0x00, 0x00 + ] + ) +} diff --git a/src/tests/unit/packet/v5/disconnect_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/disconnect_packet_unit.rs similarity index 87% rename from src/tests/unit/packet/v5/disconnect_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/disconnect_packet_unit.rs index dd5478e..282b487 100644 --- a/src/tests/unit/packet/v5/disconnect_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/disconnect_packet_unit.rs @@ -22,13 +22,12 @@ * SOFTWARE. */ - -use heapless::Vec; use crate::packet::v5::disconnect_packet::DisconnectPacket; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::utils::buffer_reader::BuffReader; +use heapless::Vec; #[test] fn test_encode() { @@ -38,16 +37,19 @@ fn test_encode() { let mut props = Vec::::new(); props.push(prop); packet.property_len = packet.add_properties(&props); - let res = packet.encode(& mut buffer, 100); + let res = packet.encode(&mut buffer, 100); assert!(res.is_ok()); - assert_eq!(buffer[0..res.unwrap()], [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x02, 0x00]) + assert_eq!( + buffer[0..res.unwrap()], + [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x02, 0x00] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 10] = [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x04, 0x00, 0x00]; + let buffer: [u8; 10] = [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x04, 0x00, 0x00]; let mut packet = DisconnectPacket::<1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 10)); + let res = packet.decode(&mut BuffReader::new(&buffer, 10)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Disconnect.into()); assert_eq!(packet.remain_len, 7); @@ -59,4 +61,4 @@ fn test_decode() { if let Property::SessionExpiryInterval(u) = *prop.unwrap() { assert_eq!(u, 1024); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/mod.rs b/mqtt/src/tests/unit/packet/v5/mod.rs similarity index 97% rename from src/tests/unit/packet/v5/mod.rs rename to mqtt/src/tests/unit/packet/v5/mod.rs index b4959b9..4053f3a 100644 --- a/src/tests/unit/packet/v5/mod.rs +++ b/mqtt/src/tests/unit/packet/v5/mod.rs @@ -35,4 +35,4 @@ pub mod pubrel_packet_unit; pub mod suback_packet_unit; pub mod subscription_packet_unit; pub mod unsuback_packet_unit; -pub mod unsubscription_packet_unit; \ No newline at end of file +pub mod unsubscription_packet_unit; diff --git a/src/tests/unit/packet/v5/pingreq_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/pingreq_packet_unit.rs similarity index 97% rename from src/tests/unit/packet/v5/pingreq_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/pingreq_packet_unit.rs index 9a1e49d..2963385 100644 --- a/src/tests/unit/packet/v5/pingreq_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/pingreq_packet_unit.rs @@ -32,7 +32,7 @@ fn test_encode() { let mut packet = PingreqPacket::new(); packet.fixed_header = PacketType::Pingreq.into(); packet.remain_len = 0; - let res = packet.encode(& mut buffer, 3); + let res = packet.encode(&mut buffer, 3); assert!(res.is_ok()); assert_eq!(buffer, [0xC0, 0x00, 0x45]) -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/pingresp_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/pingresp_packet_unit.rs similarity index 91% rename from src/tests/unit/packet/v5/pingresp_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/pingresp_packet_unit.rs index 02cadc3..aa912e3 100644 --- a/src/tests/unit/packet/v5/pingresp_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/pingresp_packet_unit.rs @@ -33,17 +33,17 @@ fn test_encode() { let mut packet = PingrespPacket::new(); packet.fixed_header = PacketType::Pingresp.into(); packet.remain_len = 0; - let res = packet.encode(& mut buffer, 3); + let res = packet.encode(&mut buffer, 3); assert!(res.is_ok()); assert_eq!(buffer, [0xD0, 0x00, 0x45]) } #[test] fn test_decode() { - let mut buffer: [u8; 3] = [0xD0, 0x00, 0x51]; + let buffer: [u8; 3] = [0xD0, 0x00, 0x51]; let mut packet = PingrespPacket::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 3)); + let res = packet.decode(&mut BuffReader::new(&buffer, 3)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Pingresp.into()); assert_eq!(packet.remain_len, 0); -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/puback_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/puback_packet_unit.rs similarity index 87% rename from src/tests/unit/packet/v5/puback_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/puback_packet_unit.rs index 9d9bd0a..fd80208 100644 --- a/src/tests/unit/packet/v5/puback_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/puback_packet_unit.rs @@ -22,13 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::packet::v5::puback_packet::PubackPacket; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::EncodedString; +use heapless::Vec; #[test] fn test_encode() { @@ -42,17 +42,22 @@ fn test_encode() { let mut props = Vec::::new(); props.push(Property::ReasonString(str)); packet.property_len = packet.add_properties(&props); - let res = packet.encode(& mut buffer, 14); + let res = packet.encode(&mut buffer, 14); assert!(res.is_ok()); assert_eq!(res.unwrap(), 14); - assert_eq!(buffer, [0x40, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + assert_eq!( + buffer, + [0x40, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 14] = [0x40, 0x0C, 0x8A, 0x5E, 0x15, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]; + let buffer: [u8; 14] = [ + 0x40, 0x0C, 0x8A, 0x5E, 0x15, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + ]; let mut packet = PubackPacket::<1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 14)); + let res = packet.decode(&mut BuffReader::new(&buffer, 14)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Puback.into()); assert_eq!(packet.remain_len, 12); @@ -65,4 +70,4 @@ fn test_decode() { if let Property::ReasonString(u) = (*prop.unwrap()).clone() { assert_eq!(u.string, "Hello"); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/pubcomp_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/pubcomp_packet_unit.rs similarity index 85% rename from src/tests/unit/packet/v5/pubcomp_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/pubcomp_packet_unit.rs index 8e7fe8b..b3a6bd0 100644 --- a/src/tests/unit/packet/v5/pubcomp_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/pubcomp_packet_unit.rs @@ -22,13 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::packet::v5::pubcomp_packet::PubcompPacket; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::EncodedString; +use heapless::Vec; #[test] fn test_encode() { @@ -42,18 +42,23 @@ fn test_encode() { str.len = 5; let mut props = Vec::::new(); props.push(Property::ReasonString(str)); - packet.property_len = packet.add_properties(& props); - let res = packet.encode(& mut buffer, 14); + packet.property_len = packet.add_properties(&props); + let res = packet.encode(&mut buffer, 14); assert!(res.is_ok()); assert_eq!(res.unwrap(), 14); - assert_eq!(buffer, [0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c]) + assert_eq!( + buffer, + [0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 14] = [0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c]; + let buffer: [u8; 14] = [ + 0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c, + ]; let mut packet = PubcompPacket::<1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 14)); + let res = packet.decode(&mut BuffReader::new(&buffer, 14)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Pubcomp.into()); assert_eq!(packet.packet_identifier, 35420); @@ -65,4 +70,4 @@ fn test_decode() { if let Property::ReasonString(u) = (*prop.unwrap()).clone() { assert_eq!(u.string, "Wheel"); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/publish_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/publish_packet_unit.rs similarity index 79% rename from src/tests/unit/packet/v5/publish_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/publish_packet_unit.rs index ab95f2f..93b8f95 100644 --- a/src/tests/unit/packet/v5/publish_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/publish_packet_unit.rs @@ -22,13 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::packet::v5::publish_packet::{PublishPacket, QualityOfService}; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::EncodedString; +use heapless::Vec; #[test] fn test_encode() { @@ -45,23 +45,31 @@ fn test_encode() { props.push(Property::PayloadFormat(0x01)); props.push(Property::MessageExpiryInterval(45678)); packet.property_len = packet.add_properties(&props); - static MESSAGE: [u8; 11] = [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]; + static MESSAGE: [u8; 11] = [ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + ]; packet.add_message(&MESSAGE); - let res = packet.encode(& mut buffer, 100); + let res = packet.encode(&mut buffer, 100); assert!(res.is_ok()); assert_eq!(res.unwrap(), 29); - assert_eq!(buffer, [0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88, - 0x07, 0x01, 0x01, 0x02, 0x00, 0x00, 0xB2, 0x6E, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]) + assert_eq!( + buffer, + [ + 0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88, 0x07, 0x01, 0x01, 0x02, + 0x00, 0x00, 0xB2, 0x6E, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, + 0x64 + ] + ) } #[test] fn test_decode() { - let mut buffer:[u8; 29] = [0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88, - 0x07, 0x01, 0x01, 0x02, 0x00, 0x00, 0xB2, 0x6E, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]; + let buffer: [u8; 29] = [ + 0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88, 0x07, 0x01, 0x01, 0x02, 0x00, + 0x00, 0xB2, 0x6E, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + ]; let mut packet = PublishPacket::<2>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 29)); + let res = packet.decode(&mut BuffReader::new(&buffer, 29)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, 0x32); assert_eq!(packet.topic_name.len, 4); @@ -81,6 +89,9 @@ fn test_decode() { assert_eq!(u, 45678); } if let Some(message) = packet.message { - assert_eq!(*message, [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]); + assert_eq!( + *message, + [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64] + ); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/pubrec_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/pubrec_packet_unit.rs similarity index 85% rename from src/tests/unit/packet/v5/pubrec_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/pubrec_packet_unit.rs index fca6dd7..bdf98af 100644 --- a/src/tests/unit/packet/v5/pubrec_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/pubrec_packet_unit.rs @@ -22,14 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; -use crate::packet::v5::puback_packet::PubackPacket; use crate::packet::v5::pubrec_packet::PubrecPacket; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::{EncodedString, StringPair}; +use heapless::Vec; #[test] fn test_encode() { @@ -49,17 +48,26 @@ fn test_encode() { let mut props = Vec::::new(); props.push(Property::UserProperty(pair)); packet.property_len = packet.add_properties(&props); - let res = packet.encode(& mut buffer, 20); + let res = packet.encode(&mut buffer, 20); assert!(res.is_ok()); assert_eq!(res.unwrap(), 20); - assert_eq!(buffer, [0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00, 0x04, 0x76, 0x61, 0x6c, 0x31]) + assert_eq!( + buffer, + [ + 0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, + 0x00, 0x04, 0x76, 0x61, 0x6c, 0x31 + ] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 20] = [0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00, 0x04, 0x76, 0x61, 0x6c, 0x31]; + let buffer: [u8; 20] = [ + 0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00, + 0x04, 0x76, 0x61, 0x6c, 0x31, + ]; let mut packet = PubrecPacket::<1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 20)); + let res = packet.decode(&mut BuffReader::new(&buffer, 20)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Pubrec.into()); assert_eq!(packet.remain_len, 18); @@ -75,4 +83,4 @@ fn test_decode() { assert_eq!(u.value.len, 4); assert_eq!(u.value.string, "val1"); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/pubrel_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/pubrel_packet_unit.rs similarity index 83% rename from src/tests/unit/packet/v5/pubrel_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/pubrel_packet_unit.rs index 036d48d..5ed5dac 100644 --- a/src/tests/unit/packet/v5/pubrel_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/pubrel_packet_unit.rs @@ -22,15 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; -use crate::packet::v5::puback_packet::PubackPacket; -use crate::packet::v5::pubrec_packet::PubrecPacket; use crate::packet::v5::pubrel_packet::PubrelPacket; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::{EncodedString, StringPair}; +use heapless::Vec; #[test] fn test_encode() { @@ -51,19 +49,26 @@ fn test_encode() { let mut props = Vec::::new(); props.push(Property::UserProperty(pair)); packet.property_len = packet.add_properties(&props); - let res = packet.encode(& mut buffer, 21); + let res = packet.encode(&mut buffer, 21); assert!(res.is_ok()); assert_eq!(res.unwrap(), 21); - assert_eq!(buffer, [0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04, - 0x68, 0x61, 0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39]) + assert_eq!( + buffer, + [ + 0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04, 0x68, 0x61, 0x68, 0x61, 0x00, + 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39 + ] + ) } #[test] fn test_decode() { - let mut buffer: [u8; 21] = [0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04, - 0x68, 0x61, 0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39]; + let buffer: [u8; 21] = [ + 0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04, 0x68, 0x61, 0x68, 0x61, 0x00, 0x06, + 0x68, 0x65, 0x68, 0x65, 0x38, 0x39, + ]; let mut packet = PubrelPacket::<1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 21)); + let res = packet.decode(&mut BuffReader::new(&buffer, 21)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Pubrel.into()); assert_eq!(packet.remain_len, 19); @@ -79,4 +84,4 @@ fn test_decode() { assert_eq!(u.value.len, 6); assert_eq!(u.value.string, "hehe89"); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/suback_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/suback_packet_unit.rs similarity index 83% rename from src/tests/unit/packet/v5/suback_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/suback_packet_unit.rs index db314f4..0160b2a 100644 --- a/src/tests/unit/packet/v5/suback_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/suback_packet_unit.rs @@ -22,24 +22,20 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; -use crate::packet::v5::puback_packet::PubackPacket; -use crate::packet::v5::pubrec_packet::PubrecPacket; -use crate::packet::v5::pubrel_packet::PubrelPacket; use crate::packet::v5::suback_packet::SubackPacket; use crate::utils::buffer_reader::BuffReader; -use crate::utils::types::{EncodedString, StringPair}; #[test] fn test_decode() { - let mut buffer: [u8; 23] = [0x90, 0x15, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x12, 0x34, 0x56]; + let buffer: [u8; 23] = [ + 0x90, 0x15, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x56, + ]; let mut packet = SubackPacket::<3, 1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 23)); + let res = packet.decode(&mut BuffReader::new(&buffer, 23)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Suback.into()); assert_eq!(packet.remain_len, 21); @@ -68,4 +64,4 @@ fn test_decode() { if let Some(r) = res3 { assert_eq!(*r, 0x56); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/subscription_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/subscription_packet_unit.rs similarity index 86% rename from src/tests/unit/packet/v5/subscription_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/subscription_packet_unit.rs index 99b13f8..52dc24e 100644 --- a/src/tests/unit/packet/v5/subscription_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/subscription_packet_unit.rs @@ -22,12 +22,12 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::packet::v5::publish_packet::QualityOfService::{QoS0, QoS1}; use crate::packet::v5::subscription_packet::SubscriptionPacket; +use heapless::Vec; #[test] fn test_encode() { @@ -40,10 +40,15 @@ fn test_encode() { packet.property_len = packet.add_properties(&props); packet.add_new_filter("test/topic", QoS0); packet.add_new_filter("hehe/#", QoS1); - let res = packet.encode(& mut buffer, 30); + let res = packet.encode(&mut buffer, 30); assert!(res.is_ok()); assert_eq!(res.unwrap(), 30); - assert_eq!(buffer, [0x82, 0x1C, 0x15, 0x38, 0x03, 0x0B, 0x80, 0x13, 0x00, 0x0A, - 0x74, 0x65, 0x73, 0x74, 0x2f, 0x74, 0x6f, 0x70, 0x69, 0x63, - 0x00, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, 0x23, 0x01]); -} \ No newline at end of file + assert_eq!( + buffer, + [ + 0x82, 0x1C, 0x15, 0x38, 0x03, 0x0B, 0x80, 0x13, 0x00, 0x0A, 0x74, 0x65, 0x73, 0x74, + 0x2f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x00, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, + 0x23, 0x01 + ] + ); +} diff --git a/src/tests/unit/packet/v5/unsuback_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/unsuback_packet_unit.rs similarity index 81% rename from src/tests/unit/packet/v5/unsuback_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/unsuback_packet_unit.rs index 9b99a55..df0a66f 100644 --- a/src/tests/unit/packet/v5/unsuback_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/unsuback_packet_unit.rs @@ -22,25 +22,20 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; -use crate::packet::v5::puback_packet::PubackPacket; -use crate::packet::v5::pubrec_packet::PubrecPacket; -use crate::packet::v5::pubrel_packet::PubrelPacket; -use crate::packet::v5::suback_packet::SubackPacket; use crate::packet::v5::unsuback_packet::UnsubackPacket; use crate::utils::buffer_reader::BuffReader; -use crate::utils::types::{EncodedString, StringPair}; #[test] fn test_decode() { - let mut buffer: [u8; 22] = [0xB0, 0x14, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x77, 0x55]; + let buffer: [u8; 22] = [ + 0xB0, 0x14, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x77, 0x55, + ]; let mut packet = UnsubackPacket::<2, 1>::new(); - let res = packet.decode(& mut BuffReader::new(&buffer, 22)); + let res = packet.decode(&mut BuffReader::new(&buffer, 22)); assert!(res.is_ok()); assert_eq!(packet.fixed_header, PacketType::Unsuback.into()); assert_eq!(packet.remain_len, 20); @@ -64,4 +59,4 @@ fn test_decode() { if let Some(r) = res2 { assert_eq!(*r, 0x55); } -} \ No newline at end of file +} diff --git a/src/tests/unit/packet/v5/unsubscription_packet_unit.rs b/mqtt/src/tests/unit/packet/v5/unsubscription_packet_unit.rs similarity index 85% rename from src/tests/unit/packet/v5/unsubscription_packet_unit.rs rename to mqtt/src/tests/unit/packet/v5/unsubscription_packet_unit.rs index cd22a26..6430f26 100644 --- a/src/tests/unit/packet/v5/unsubscription_packet_unit.rs +++ b/mqtt/src/tests/unit/packet/v5/unsubscription_packet_unit.rs @@ -22,14 +22,13 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::mqtt_packet::Packet; use crate::packet::v5::packet_type::PacketType; use crate::packet::v5::property::Property; use crate::packet::v5::publish_packet::QualityOfService::{QoS0, QoS1}; -use crate::packet::v5::subscription_packet::SubscriptionPacket; use crate::packet::v5::unsubscription_packet::UnsubscriptionPacket; use crate::utils::types::{EncodedString, StringPair}; +use heapless::Vec; #[test] fn test_encode() { @@ -51,11 +50,15 @@ fn test_encode() { packet.property_len = packet.add_properties(&props); packet.add_new_filter("test/topic", QoS0); packet.add_new_filter("hehe/#", QoS1); - let res = packet.encode(& mut buffer, 40); + let res = packet.encode(&mut buffer, 40); assert!(res.is_ok()); assert_eq!(res.unwrap(), 40); - assert_eq!(buffer, [0xA0, 0x26, 0x15, 0x38, 0x0F, 0x26, 0x00, 0x04, 0x68, 0x61, - 0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39, - 0x00, 0x0A, 0x74, 0x65, 0x73, 0x74, 0x2F, 0x74, 0x6F, 0x70, - 0x69, 0x63, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, 0x23]); -} \ No newline at end of file + assert_eq!( + buffer, + [ + 0xA0, 0x26, 0x15, 0x38, 0x0F, 0x26, 0x00, 0x04, 0x68, 0x61, 0x68, 0x61, 0x00, 0x06, + 0x68, 0x65, 0x68, 0x65, 0x38, 0x39, 0x00, 0x0A, 0x74, 0x65, 0x73, 0x74, 0x2F, 0x74, + 0x6F, 0x70, 0x69, 0x63, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, 0x23 + ] + ); +} diff --git a/src/tests/unit/utils/buffer_reader_unit.rs b/mqtt/src/tests/unit/utils/buffer_reader_unit.rs similarity index 86% rename from src/tests/unit/utils/buffer_reader_unit.rs rename to mqtt/src/tests/unit/utils/buffer_reader_unit.rs index 6f6943b..c8948a5 100644 --- a/src/tests/unit/utils/buffer_reader_unit.rs +++ b/mqtt/src/tests/unit/utils/buffer_reader_unit.rs @@ -22,9 +22,6 @@ * SOFTWARE. */ -use core::str; - -use log::info; use crate::utils::buffer_reader::BuffReader; use crate::utils::types::BufferError; @@ -44,7 +41,10 @@ fn buffer_read_invalid_size() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 2); let test_number = reader.read_variable_byte_int(); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -73,7 +73,10 @@ fn test_var_empty_buffer() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 0); let test_number = reader.read_variable_byte_int(); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -91,7 +94,10 @@ fn test_read_u32_oob() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 3); let test_number = reader.read_u32(); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -109,7 +115,10 @@ fn test_read_u16_oob() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 1); let test_number = reader.read_u16(); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -127,7 +136,10 @@ fn test_read_u8_oob() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 0); let test_number = reader.read_u8(); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -156,7 +168,10 @@ fn test_read_string_oob() { let mut reader: BuffReader = BuffReader::new(&BUFFER, 5); let test_string = reader.read_string(); assert!(test_string.is_err()); - assert_eq!(test_string.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_string.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -181,7 +196,9 @@ fn test_read_binary_oob() { #[test] fn test_read_string_pair() { - static BUFFER: [u8; 11] = [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x03, 0xE2, 0x93, 0x87]; + static BUFFER: [u8; 11] = [ + 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x03, 0xE2, 0x93, 0x87, + ]; let mut reader: BuffReader = BuffReader::new(&BUFFER, 11); let string_pair = reader.read_string_pair(); assert!(string_pair.is_ok()); @@ -192,22 +209,27 @@ fn test_read_string_pair() { assert_eq!(unw.value.len, 3); } - #[test] fn test_read_string_pair_wrong_utf8() { - static BUFFER: [u8; 11] = [0x00, 0x03, 0xF0, 0x9F, 0x92, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E]; + static BUFFER: [u8; 11] = [ + 0x00, 0x03, 0xF0, 0x9F, 0x92, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, + ]; let mut reader: BuffReader = BuffReader::new(&BUFFER, 11); let string_pair = reader.read_string_pair(); assert!(string_pair.is_err()); assert_eq!(string_pair.unwrap_err(), BufferError::Utf8Error) - } #[test] fn test_read_string_pair_oob() { - static BUFFER: [u8; 11] = [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x04, 0xE2, 0x93, 0x87]; + static BUFFER: [u8; 11] = [ + 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x04, 0xE2, 0x93, 0x87, + ]; let mut reader: BuffReader = BuffReader::new(&BUFFER, 11); let string_pair = reader.read_string_pair(); assert!(string_pair.is_err()); - assert_eq!(string_pair.unwrap_err(), BufferError::InsufficientBufferSize); -} \ No newline at end of file + assert_eq!( + string_pair.unwrap_err(), + BufferError::InsufficientBufferSize + ); +} diff --git a/src/tests/unit/utils/buffer_writer_unit.rs b/mqtt/src/tests/unit/utils/buffer_writer_unit.rs similarity index 80% rename from src/tests/unit/utils/buffer_writer_unit.rs rename to mqtt/src/tests/unit/utils/buffer_writer_unit.rs index ec7e9ac..0bcb675 100644 --- a/src/tests/unit/utils/buffer_writer_unit.rs +++ b/mqtt/src/tests/unit/utils/buffer_writer_unit.rs @@ -22,17 +22,17 @@ * SOFTWARE. */ -use heapless::Vec; use crate::packet::v5::property::Property; use crate::utils::buffer_writer::BuffWriter; use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair, TopicFilter}; +use heapless::Vec; #[test] fn buffer_write_ref() { static BUFFER: [u8; 5] = [0x82, 0x82, 0x03, 0x85, 0x84]; let mut res_buffer: [u8; 5] = [0; 5]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 5); let test_write = writer.insert_ref(5, &BUFFER); assert!(test_write.is_ok()); assert_eq!(writer.position, 5); @@ -44,10 +44,13 @@ fn buffer_write_ref_oob() { static BUFFER: [u8; 5] = [0x82, 0x82, 0x03, 0x85, 0x84]; let mut res_buffer: [u8; 4] = [0; 4]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 4); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 4); let test_number = writer.insert_ref(5, &BUFFER); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); assert_eq!(res_buffer, [0; 4]) } @@ -55,7 +58,7 @@ fn buffer_write_ref_oob() { fn buffer_write_u8() { let mut res_buffer: [u8; 1] = [0; 1]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 1); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 1); let test_write = writer.write_u8(0xFA); assert!(test_write.is_ok()); assert_eq!(writer.position, 1); @@ -66,17 +69,20 @@ fn buffer_write_u8() { fn buffer_write_u8_oob() { let mut res_buffer: [u8; 0] = []; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 0); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 0); let test_number = writer.write_u8(0xFA); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] fn buffer_write_u16() { let mut res_buffer: [u8; 2] = [0; 2]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 2); let test_write = writer.write_u16(0xFAED); assert!(test_write.is_ok()); assert_eq!(writer.position, 2); @@ -87,17 +93,20 @@ fn buffer_write_u16() { fn buffer_write_u16_oob() { let mut res_buffer: [u8; 1] = [0; 1]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 1); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 1); let test_number = writer.write_u16(0xFAED); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] fn buffer_write_u32() { let mut res_buffer: [u8; 4] = [0; 4]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 4); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 4); let test_write = writer.write_u32(0xFAEDCC09); assert!(test_write.is_ok()); assert_eq!(writer.position, 4); @@ -108,10 +117,13 @@ fn buffer_write_u32() { fn buffer_write_u32_oob() { let mut res_buffer: [u8; 3] = [0; 3]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 3); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 3); let test_number = writer.write_u32(0xFAEDCC08); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } #[test] @@ -120,21 +132,20 @@ fn buffer_write_string() { let mut string = EncodedString::new(); string.string = "😎"; string.len = 4; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 6); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 6); let test_write = writer.write_string_ref(&string); assert!(test_write.is_ok()); assert_eq!(writer.position, 6); assert_eq!(res_buffer, [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E]); } - #[test] fn buffer_write_string_oob() { let mut res_buffer: [u8; 5] = [0; 5]; let mut string = EncodedString::new(); string.string = "😎"; string.len = 4; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 5); let test_write = writer.write_string_ref(&string); assert!(test_write.is_err()); assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize); @@ -146,21 +157,20 @@ fn buffer_write_bin() { let mut bin = BinaryData::new(); bin.bin = &[0xAB, 0xEF, 0x88, 0x43]; bin.len = 4; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 6); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 6); let test_write = writer.write_binary_ref(&bin); assert!(test_write.is_ok()); assert_eq!(writer.position, 6); assert_eq!(res_buffer, [0x00, 0x04, 0xAB, 0xEF, 0x88, 0x43]); } - #[test] fn buffer_write_bin_oob() { let mut res_buffer: [u8; 6] = [0; 6]; let mut bin = BinaryData::new(); bin.bin = &[0xAB, 0xEF, 0x88, 0x43]; bin.len = 4; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 5); let test_write = writer.write_binary_ref(&bin); assert!(test_write.is_err()); assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize); @@ -179,11 +189,14 @@ fn buffer_write_string_pair() { let mut pair = StringPair::new(); pair.name = name; pair.value = value; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 12); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 12); let test_write = writer.write_string_pair_ref(&pair); assert!(test_write.is_ok()); assert_eq!(writer.position, 12); - assert_eq!(res_buffer, [0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E]); + assert_eq!( + res_buffer, + [0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E] + ); } #[test] @@ -199,7 +212,7 @@ fn buffer_write_string_pair_oob() { let mut pair = StringPair::new(); pair.name = name; pair.value = value; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 10); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 10); let test_write = writer.write_string_pair_ref(&pair); assert!(test_write.is_err()); assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize) @@ -209,7 +222,7 @@ fn buffer_write_string_pair_oob() { fn buffer_write_var_byte() { let mut res_buffer: [u8; 2] = [0; 2]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 2); let test_write = writer.write_variable_byte_int(512); assert!(test_write.is_ok()); assert_eq!(writer.position, 2); @@ -220,10 +233,13 @@ fn buffer_write_var_byte() { fn buffer_write_var_byte_oob() { let mut res_buffer: [u8; 2] = [0; 2]; - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 2); let test_number = writer.write_variable_byte_int(453123); assert!(test_number.is_err()); - assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize); + assert_eq!( + test_number.unwrap_err(), + BufferError::InsufficientBufferSize + ); } /*#[test] @@ -267,12 +283,14 @@ fn buffer_write_properties() { let mut properties = Vec::::new(); properties.push(prop); properties.push(prop2); - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 13); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 13); let test_write = writer.write_properties(&properties); assert!(test_write.is_ok()); assert_eq!(writer.position, 13); - assert_eq!(res_buffer, [0x08, 0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x09, 0x00, 0x03, 0x12, 0x34, 0x56]); + assert_eq!( + res_buffer, + [0x08, 0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x09, 0x00, 0x03, 0x12, 0x34, 0x56] + ); } #[test] @@ -289,7 +307,7 @@ fn buffer_write_properties_oob() { let mut properties = Vec::::new(); properties.push(prop); properties.push(prop2); - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 10); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 10); let test_write = writer.write_properties(&properties); assert!(test_write.is_err()); assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize); @@ -316,16 +334,20 @@ fn buffer_write_filters() { filter2.filter = topic2; filter2.sub_options = 0x22; - let mut filters = Vec::::new(); filters.push(filter1); filters.push(filter2); - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 15); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 15); let test_write = writer.write_topic_filters_ref(true, 2, &filters); assert!(test_write.is_ok()); assert_eq!(writer.position, 15); - assert_eq!(res_buffer, [0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0xAE, - 0x00, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22]); + assert_eq!( + res_buffer, + [ + 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0xAE, 0x00, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, + 0x22 + ] + ); } #[test] @@ -349,12 +371,11 @@ fn buffer_write_filters_oob() { filter2.filter = topic2; filter2.sub_options = 0x22; - let mut filters = Vec::::new(); filters.push(filter1); filters.push(filter2); - let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5); + let mut writer: BuffWriter = BuffWriter::new(&mut res_buffer, 5); let test_write = writer.write_topic_filters_ref(true, 2, &filters); assert!(test_write.is_err()); assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize) -} \ No newline at end of file +} diff --git a/src/tests/unit/utils/mod.rs b/mqtt/src/tests/unit/utils/mod.rs similarity index 97% rename from src/tests/unit/utils/mod.rs rename to mqtt/src/tests/unit/utils/mod.rs index 8516624..02576e9 100644 --- a/src/tests/unit/utils/mod.rs +++ b/mqtt/src/tests/unit/utils/mod.rs @@ -23,4 +23,4 @@ */ pub mod buffer_reader_unit; -pub mod buffer_writer_unit; \ No newline at end of file +pub mod buffer_writer_unit; diff --git a/mqtt/src/tokio_net/mod.rs b/mqtt/src/tokio_net/mod.rs new file mode 100644 index 0000000..c9c75da --- /dev/null +++ b/mqtt/src/tokio_net/mod.rs @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![feature(in_band_lifetimes)] +#![macro_use] +#![allow(dead_code)] +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] +#[cfg(feature = "tokio")] +pub mod tokio_network; diff --git a/mqtt/src/tokio_net/tokio_network.rs b/mqtt/src/tokio_net/tokio_network.rs new file mode 100644 index 0000000..6395bad --- /dev/null +++ b/mqtt/src/tokio_net/tokio_network.rs @@ -0,0 +1,145 @@ +/* + * MIT License + * + * Copyright (c) [2022] [Ondrej Babec ] + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +extern crate alloc; +use alloc::format; +use alloc::string::String; +use core::future::Future; +use core::time::Duration; + +use crate::network::network_trait::{NetworkConnection, NetworkConnectionFactory}; +use crate::packet::v5::reason_codes::ReasonCode; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; +use tokio::time::sleep; + +pub struct TokioNetwork { + stream: Option, +} + +impl TokioNetwork { + pub fn new(stream: TcpStream) -> Self { + Self { + stream: Some(stream), + } + } + + pub fn convert_ip(ip: [u8; 4], port: u16) -> String { + String::from(format!("{}.{}.{}.{}:{}", ip[0], ip[1], ip[2], ip[3], port)) + } +} + +impl NetworkConnection for TokioNetwork { + type WriteFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + type ReadFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + type CloseFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + /*type TimerFuture<'m> + where + Self: 'm, + = impl Future;*/ + + fn send<'m>(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m> { + async move { + return if let Some(ref mut stream) = self.stream { + stream + .write_all(&buffer[0..len]) + .await + .map_err(|_| ReasonCode::NetworkError) + } else { + Err(ReasonCode::NetworkError) + }; + } + } + + fn receive<'m>(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m> { + async move { + return if let Some(ref mut stream) = self.stream { + stream + .read(buffer) + .await + .map_err(|_| ReasonCode::NetworkError) + } else { + Err(ReasonCode::NetworkError) + }; + } + } + + fn close<'m>(mut self) -> Self::CloseFuture<'m> { + async move { + return if let Some(ref mut stream) = self.stream { + stream + .shutdown() + .await + .map_err(|_| ReasonCode::NetworkError) + } else { + Err(ReasonCode::NetworkError) + }; + } + } + + /*fn count_down(&'m mut self, time_in_secs: u64) -> Self::TimerFuture<'m> { + async move { + return sleep(Duration::from_secs(time_in_secs)) + .await + } + }*/ +} + +pub struct TokioNetworkFactory {} + +impl TokioNetworkFactory { + pub fn new() -> Self { + Self {} + } +} + +impl NetworkConnectionFactory for TokioNetworkFactory { + type Connection = TokioNetwork; + + type ConnectionFuture<'m> + where + Self: 'm, + = impl Future> + 'm; + + fn connect<'m>(&'m mut self, ip: [u8; 4], port: u16) -> Self::ConnectionFuture<'m> { + async move { + let stream = TcpStream::connect(TokioNetwork::convert_ip(ip, port)) + .await + .map_err(|_| ReasonCode::NetworkError)?; + Ok(TokioNetwork::new(stream)) + } + } +} diff --git a/src/utils/buffer_reader.rs b/mqtt/src/utils/buffer_reader.rs similarity index 92% rename from src/utils/buffer_reader.rs rename to mqtt/src/utils/buffer_reader.rs index 2cb1ecf..89cf852 100644 --- a/src/utils/buffer_reader.rs +++ b/mqtt/src/utils/buffer_reader.rs @@ -75,7 +75,7 @@ impl<'a> BuffReader<'a> { variable_byte_integer[x] = 0; x = x + 1; if x == 4 { - break + break; } } break; @@ -121,14 +121,13 @@ impl<'a> BuffReader<'a> { /// Reading UTF-8 encoded string from buffer pub fn read_string(&mut self) -> Result, BufferError> { - let len = self.read_u16() ? as usize; + let len = self.read_u16()? as usize; if self.position + len - 1 >= self.len { return Err(BufferError::InsufficientBufferSize); } - let res_str = - str::from_utf8(&(self.buffer[self.position..(self.position + len)])); + let res_str = str::from_utf8(&(self.buffer[self.position..(self.position + len)])); if res_str.is_err() { log::error!("Could not parse utf-8 string"); return Err(BufferError::Utf8Error); @@ -142,27 +141,21 @@ impl<'a> BuffReader<'a> { /// Read Binary data from buffer pub fn read_binary(&mut self) -> Result, BufferError> { - let len = self.read_u16() ?; + let len = self.read_u16()?; if self.position + len as usize - 1 >= self.len { return Err(BufferError::InsufficientBufferSize); } let res_bin = &(self.buffer[self.position..(self.position + len as usize)]); - return Ok(BinaryData { - bin: res_bin, - len, - }); + return Ok(BinaryData { bin: res_bin, len }); } /// Read string pair from buffer pub fn read_string_pair(&mut self) -> Result, BufferError> { - let name = self.read_string() ?; - let value = self.read_string() ?; - return Ok(StringPair { - name, - value, - }); + let name = self.read_string()?; + let value = self.read_string()?; + return Ok(StringPair { name, value }); } /// Read payload message from buffer diff --git a/src/utils/buffer_writer.rs b/mqtt/src/utils/buffer_writer.rs similarity index 99% rename from src/utils/buffer_writer.rs rename to mqtt/src/utils/buffer_writer.rs index 6c85c80..7903065 100644 --- a/src/utils/buffer_writer.rs +++ b/mqtt/src/utils/buffer_writer.rs @@ -91,7 +91,7 @@ impl<'a> BuffWriter<'a> { let bytes = str.string.as_bytes(); return self.insert_ref(str.len as usize, bytes); } - return Ok(()) + return Ok(()); } pub fn write_binary_ref(&mut self, bin: &BinaryData<'a>) -> Result<(), BufferError> { diff --git a/src/utils/mod.rs b/mqtt/src/utils/mod.rs similarity index 100% rename from src/utils/mod.rs rename to mqtt/src/utils/mod.rs diff --git a/src/utils/rng_generator.rs b/mqtt/src/utils/rng_generator.rs similarity index 100% rename from src/utils/rng_generator.rs rename to mqtt/src/utils/rng_generator.rs diff --git a/src/utils/types.rs b/mqtt/src/utils/types.rs similarity index 97% rename from src/utils/types.rs rename to mqtt/src/utils/types.rs index b35e962..4c141c2 100644 --- a/src/utils/types.rs +++ b/mqtt/src/utils/types.rs @@ -24,8 +24,7 @@ use core::fmt::{Display, Formatter}; -#[derive(core::fmt::Debug, Clone)] -#[derive(PartialEq)] +#[derive(core::fmt::Debug, Clone, PartialEq)] pub enum BufferError { Utf8Error, InsufficientBufferSize, @@ -101,7 +100,7 @@ impl StringPair<'_> { pub fn new() -> Self { Self { name: EncodedString::new(), - value: EncodedString::new() + value: EncodedString::new(), } } /// Returns length which is equal to sum of the lenghts of UTF-8 encoded strings in pair diff --git a/mqtt_control_example.bin b/mqtt_control_example.bin new file mode 100644 index 0000000..b77085e Binary files /dev/null and b/mqtt_control_example.bin differ diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e5d4bdb..0000000 --- a/src/main.rs +++ /dev/null @@ -1,141 +0,0 @@ -use std::time::Duration; - -use heapless::Vec; - -use tokio::time::sleep; -use tokio::{join, task}; - -use rust_mqtt::client::client_config::ClientConfig; -use rust_mqtt::client::client_v5::MqttClientV5; -use rust_mqtt::network::network_trait::{Network, NetworkError}; -use rust_mqtt::packet::v5::connect_packet::ConnectPacket; -use rust_mqtt::packet::v5::mqtt_packet::Packet; -use rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS1; -use rust_mqtt::packet::v5::publish_packet::{PublishPacket, QualityOfService}; -use rust_mqtt::packet::v5::subscription_packet::SubscriptionPacket; -use rust_mqtt::tokio_network::TokioNetwork; - -async fn receive() { - let mut ip: [u8; 4] = [127, 0, 0, 1]; - let mut port: u16 = 1883; - let mut tokio_network: TokioNetwork = TokioNetwork::new(ip, port); - tokio_network.create_connection().await; - let mut config = ClientConfig::new(); - config.add_qos(QualityOfService::QoS1); - config.add_username("test"); - config.add_password("testPass"); - let mut res2 = vec![0; 260]; - let mut res3 = vec![0; 260]; - let mut client = MqttClientV5::::new( - &mut tokio_network, - &mut res2, - 260, - &mut res3, - 260, - config, - ); - - let mut result = { client.connect_to_broker().await }; - if let Err(r) = result { - log::error!("[ERROR]: {}", r); - return; - } - - { - const TOPICS: usize = 2; - let t1 = "test/topic1"; - let t2 = "test/topic2"; - let mut names = Vec::<&str, TOPICS>::new(); - names.push(&t1); - names.push(&t2); - client.subscribe_to_topics::(&names).await; - //client.subscribe_to_topic("test/topic").await; - }; - - { - sleep(Duration::from_secs(10)); - client.send_ping().await; - } - let mut o = 0; - loop { - if o == 2 { - break; - } - log::info!("Waiting for new message!"); - let mes = client.receive_message().await.unwrap(); - let x = String::from_utf8_lossy(mes); - log::info!("Got new message: {}", x); - o = o + 1; - } - { - client.disconnect().await; - } -} - -async fn publish(message: &str) { - let mut ip: [u8; 4] = [37, 205, 11, 180]; - let mut port: u16 = 1883; - let mut tokio_network: TokioNetwork = TokioNetwork::new(ip, port); - tokio_network.create_connection().await; - let config = ClientConfig::new(); - let mut res2 = vec![0; 260]; - let mut res3 = vec![0; 260]; - let mut client = MqttClientV5::::new( - &mut tokio_network, - &mut res2, - 260, - &mut res3, - 260, - config, - ); - - let mut result = { client.connect_to_broker().await }; - log::info!("Waiting until send!"); - sleep(Duration::from_secs(15)); - result = { - log::info!("Sending new message!"); - /*client - .send_message("test/topic", message) - .await*/ - client.send_ping().await - }; - if let Err(e) = result { - log::error!("Chyba!"); - } - - /*result = { - log::info!("Sending new message!"); - client - .send_message("test/topic", "Dalsi zprava :)") - .await - }; - if let Err(err) = result { - log::error!("Chyba!"); - }*/ - - { - client.disconnect().await; - } -} - -#[tokio::main] -async fn main() { - env_logger::builder() - .filter_level(log::LevelFilter::Info) - .format_timestamp_nanos() - .init(); - - /*let recv = task::spawn(async move { - receive().await; - }); - - let publ = task::spawn(async move { - publish("hello world 123 !").await; - }); - - join!(recv, publ);*/ - receive().await; - - //publish("Ahoj 123").await; - log::info!("Done"); -} diff --git a/src/network/network_trait.rs b/src/network/network_trait.rs deleted file mode 100644 index d3b3d56..0000000 --- a/src/network/network_trait.rs +++ /dev/null @@ -1,40 +0,0 @@ -use core::future::Future; - -use crate::packet::v5::reason_codes::ReasonCode; - -#[derive(Debug)] -pub enum NetworkError { - Connection, - Unknown, - QoSAck, - IDNotMatchedOnAck, - NoMatchingSubs, -} - -pub trait Network { - type ConnectionFuture<'m>: Future> - where - Self: 'm; - - type WriteFuture<'m>: Future> - where - Self: 'm; - - type ReadFuture<'m>: Future> - where - Self: 'm; - - type TimerFuture<'m>: Future - where - Self: 'm; - - fn new(ip: [u8; 4], port: u16) -> Self; - - fn create_connection(&'m mut self) -> Self::ConnectionFuture<'m>; - - fn send(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m>; - - fn receive(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m>; - - fn count_down(&'m mut self, time_in_secs: u64) -> Self::TimerFuture<'m>; -} diff --git a/src/tokio_network.rs b/src/tokio_network.rs deleted file mode 100644 index 3791479..0000000 --- a/src/tokio_network.rs +++ /dev/null @@ -1,100 +0,0 @@ -use alloc::format; -use alloc::string::String; -use core::future::Future; -use core::time::Duration; - -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::net::TcpStream; -use tokio::time::sleep; - -use crate::network::network_trait::Network; -use crate::packet::v5::reason_codes::ReasonCode; - -pub struct TokioNetwork { - ip: [u8; 4], - port: u16, - socket: Option, -} - -impl TokioNetwork { - fn convert_ip(&mut self) -> String { - String::from(format!( - "{}.{}.{}.{}:{}", - self.ip[0], self.ip[1], self.ip[2], self.ip[3], self.port - )) - } -} - -impl TokioNetwork {} - -impl Network for TokioNetwork { - type ConnectionFuture<'m> - where - Self: 'm, - = impl Future> + 'm; - type WriteFuture<'m> - where - Self: 'm, - = impl Future> + 'm; - - type ReadFuture<'m> - where - Self: 'm, - = impl Future> + 'm; - - type TimerFuture<'m> - where - Self: 'm, - = impl Future; - - fn new(ip: [u8; 4], port: u16) -> Self { - return Self { - ip, - port, - socket: Option::None, - }; - } - - fn create_connection<'m>(&'m mut self) -> Self::ConnectionFuture<'m> { - async move { - TcpStream::connect(self.convert_ip()) - .await - .map(|socket| self.socket = Some(socket)) - .map(|_| ()) - .map_err(|_| ReasonCode::NetworkError) - } - } - - fn send<'m>(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m> { - async move { - return if let Some(ref mut stream) = self.socket { - stream - .write_all(&buffer[0..len]) - .await - .map_err(|_| ReasonCode::NetworkError) - } else { - Err(ReasonCode::NetworkError) - }; - } - } - - fn receive<'m>(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m> { - async move { - return if let Some(ref mut stream) = self.socket { - stream - .read(buffer) - .await - .map_err(|_| ReasonCode::NetworkError) - } else { - Err(ReasonCode::NetworkError) - }; - } - } - - fn count_down(&'m mut self, time_in_secs: u64) -> Self::TimerFuture<'m> { - async move { - return sleep(Duration::from_secs(time_in_secs)) - .await - } - } -}