From f36d0f0f9dfe64927b7aa0c9ad2a8d9298d63a63 Mon Sep 17 00:00:00 2001 From: conectado Date: Tue, 16 Nov 2021 11:36:30 -0300 Subject: [PATCH] feat(rust): adss smoltcp support and abstract tcp transport to tcp_core * All necessary changes to support using smoltcp as transport protocol in crate `ockam_transport_smoltcp`. * Includes async interface. * Ability to manually poll. * Necessary implementation of interfaces to run in std using tun/tap interface. * Extract common behavior from smoltcp and std tcp into `ockam_transport_core` in a new `tcp` module. * Necessary unix socket behavior extracted into traits. * Worker and Route behavior extracted into common modules. * No support for portals and inlet yet. --- Cargo.lock | 305 +++- .../rust/ockam/ockam_core/src/compat.rs | 8 +- .../example_projects/smoltcp/Cargo.lock | 1607 +++++++++++++++++ .../example_projects/smoltcp/Cargo.toml | 46 + .../example_projects/smoltcp/README.md | 59 + .../smoltcp/examples/network_echo_client.rs | 66 + .../smoltcp/examples/network_echo_server.rs | 70 + .../example_projects/smoltcp/src/lib.rs | 1 + .../example_projects/tcp/Cargo.lock | 1384 ++++++++++++++ .../ockam/ockam_transport_core/Cargo.toml | 19 +- .../ockam/ockam_transport_core/src/error.rs | 18 +- .../ockam/ockam_transport_core/src/lib.rs | 10 + .../ockam/ockam_transport_core/src/tcp/mod.rs | 4 + .../src/tcp/router/handle.rs | 145 ++ .../src/tcp}/router/mod.rs | 158 +- .../ockam_transport_core/src/tcp/traits/io.rs | 222 +++ .../src/tcp/traits/mod.rs | 248 +++ .../src/tcp/workers/listener.rs | 107 ++ .../src/tcp/workers/mod.rs | 9 + .../src/tcp}/workers/receiver.rs | 66 +- .../src/tcp}/workers/sender.rs | 138 +- .../ockam/ockam_transport_smoltcp/Cargo.toml | 77 + .../ockam/ockam_transport_smoltcp/src/lib.rs | 21 + .../src/net/device/mod.rs | 150 ++ .../src/net/device/packet_pool.rs | 77 + .../src/net/device/tuntap.rs | 215 +++ .../ockam_transport_smoltcp/src/net/mod.rs | 17 + .../ockam_transport_smoltcp/src/net/stack.rs | 355 ++++ .../ockam_transport_smoltcp/src/net/tcp.rs | 203 +++ .../src/net/timer/mod.rs | 51 + .../src/port_provider.rs | 30 + .../ockam_transport_smoltcp/src/transport.rs | 292 +++ .../ockam/ockam_transport_tcp/src/handle.rs | 115 ++ .../rust/ockam/ockam_transport_tcp/src/lib.rs | 11 +- .../src/portal/outlet_listener.rs | 3 +- .../ockam_transport_tcp/src/router/handle.rs | 139 -- .../ockam_transport_tcp/src/transport.rs | 19 +- .../src/workers/listener.rs | 59 - .../ockam_transport_tcp/src/workers/mod.rs | 7 - .../ockam_transport_tcp/tests/send_receive.rs | 3 +- 40 files changed, 6091 insertions(+), 443 deletions(-) create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.lock create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.toml create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/README.md create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_client.rs create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_server.rs create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/smoltcp/src/lib.rs create mode 100644 implementations/rust/ockam/ockam_examples/example_projects/tcp/Cargo.lock create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/mod.rs create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/router/handle.rs rename implementations/rust/ockam/{ockam_transport_tcp/src => ockam_transport_core/src/tcp}/router/mod.rs (57%) create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/traits/io.rs create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/traits/mod.rs create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/workers/listener.rs create mode 100644 implementations/rust/ockam/ockam_transport_core/src/tcp/workers/mod.rs rename implementations/rust/ockam/{ockam_transport_tcp/src => ockam_transport_core/src/tcp}/workers/receiver.rs (51%) rename implementations/rust/ockam/{ockam_transport_tcp/src => ockam_transport_core/src/tcp}/workers/sender.rs (60%) create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/Cargo.toml create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/lib.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/mod.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/packet_pool.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/tuntap.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/mod.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/stack.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/tcp.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/net/timer/mod.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/port_provider.rs create mode 100644 implementations/rust/ockam/ockam_transport_smoltcp/src/transport.rs create mode 100644 implementations/rust/ockam/ockam_transport_tcp/src/handle.rs delete mode 100644 implementations/rust/ockam/ockam_transport_tcp/src/router/handle.rs delete mode 100644 implementations/rust/ockam/ockam_transport_tcp/src/workers/listener.rs delete mode 100644 implementations/rust/ockam/ockam_transport_tcp/src/workers/mod.rs diff --git a/Cargo.lock b/Cargo.lock index debb0f1d1c5..81c0856e1e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,7 +86,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a785a543aea40f5e4e2e93bb2655d31bc21bb391fff65697150973e383f16bb" dependencies = [ - "as-slice", + "as-slice 0.1.5", ] [[package]] @@ -128,6 +128,34 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "async-io" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + [[package]] name = "async-trait" version = "0.1.52" @@ -141,14 +169,26 @@ dependencies = [ [[package]] name = "atomic-polyfill" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6adc1648f03fbc1bc1b5cf0f2fdfb5edbc96215b711edcfe6ce2641ef9b347" +checksum = "e686d748538a32325b28d6411dd8a939e7ad5128e5d0023cc4fd3573db456042" dependencies = [ "critical-section", "riscv-target", ] +[[package]] +name = "atomic-pool" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b407ed6d721feca5f9432fcd24dec6857debbc8f5d86a75538d871ee85b8b1f" +dependencies = [ + "as-slice 0.1.5", + "as-slice 0.2.1", + "atomic-polyfill", + "stable_deref_trait", +] + [[package]] name = "atsamd-hal" version = "0.12.0" @@ -204,9 +244,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" @@ -445,6 +485,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + [[package]] name = "cast" version = "0.2.7" @@ -456,9 +502,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.73" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -498,9 +544,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.0" +version = "3.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f1fea81f183005ced9e59cdb01737ef2423956dac5a6d731b06b2ecfaa3467" +checksum = "08799f92c961c7a1cf0cc398a9073da99e21ce388b46372c37f3191f2f3eed3e" dependencies = [ "atty", "bitflags", @@ -515,9 +561,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.0" +version = "3.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd1122e63869df2cb309f449da1ad54a7c6dfeb7c7e6ccd8e0825d9eb93bb72" +checksum = "0fd2078197a22f338bd4fbf7d6387eb6f0d6a3c69e6cbc09f5c93e97321fd92a" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -569,6 +615,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + [[package]] name = "config" version = "0.11.0" @@ -723,9 +778,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd435b205a4842da59efd07628f921c096bc1cc0a156835b4fa0bcb9a19bcce" +checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110" dependencies = [ "cfg-if", "crossbeam-utils", @@ -733,9 +788,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" dependencies = [ "cfg-if", ] @@ -749,7 +804,7 @@ dependencies = [ "bitflags", "crossterm_winapi", "libc", - "mio 0.7.14", + "mio", "parking_lot 0.11.2", "signal-hook", "signal-hook-mio", @@ -938,9 +993,9 @@ dependencies = [ [[package]] name = "embedded-hal" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9" dependencies = [ "nb 0.1.3", "void", @@ -995,7 +1050,7 @@ version = "0.1.0" dependencies = [ "anyhow", "duct", - "rand 0.8.5", + "rand 0.8.4", "ron", "serde 1.0.136", ] @@ -1006,6 +1061,15 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "ff" version = "0.10.1" @@ -1119,6 +1183,21 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.21" @@ -1281,7 +1360,7 @@ checksum = "d076121838e03f862871315477528debffdb7462fb229216ecef91b1a3eb31eb" dependencies = [ "atomic-polyfill", "hash32", - "spin", + "spin 0.9.2", "stable_deref_trait", ] @@ -1306,7 +1385,7 @@ version = "0.1.0" dependencies = [ "ockam", "ockam_transport_websocket", - "rand 0.8.5", + "rand 0.8.4", "serde 1.0.136", "serde_json", ] @@ -1380,9 +1459,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.6.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "human-panic" @@ -1476,6 +1555,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lexical-core" @@ -1492,9 +1574,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.118" +version = "0.2.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" +checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" [[package]] name = "libdbus-sys" @@ -1606,19 +1688,6 @@ dependencies = [ "winapi", ] -[[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" @@ -1700,9 +1769,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.7" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ "winapi", ] @@ -1787,7 +1856,7 @@ dependencies = [ "ockam_transport_tcp", "ockam_vault", "ockam_vault_sync_core", - "rand 0.8.5", + "rand 0.8.4", "rand_xorshift", "serde 1.0.136", "serde-big-array", @@ -1823,7 +1892,7 @@ dependencies = [ "ockam_node", "ockam_vault", "ockam_vault_sync_core", - "rand 0.8.5", + "rand 0.8.4", "rand_pcg", "serde 1.0.136", "tokio", @@ -1836,7 +1905,7 @@ name = "ockam_command" version = "0.7.0" dependencies = [ "bunt", - "clap 3.1.0", + "clap 3.0.13", "comfy-table", "config", "ctrlc", @@ -1866,11 +1935,11 @@ dependencies = [ "heapless", "hex", "ockam_macros", - "rand 0.8.5", + "rand 0.8.4", "rand_pcg", "serde 1.0.136", "serde_bare", - "spin", + "spin 0.9.2", "zeroize", ] @@ -1912,7 +1981,7 @@ dependencies = [ "ockam_transport_tcp", "ockam_vault", "ockam_vault_sync_core", - "rand 0.8.5", + "rand 0.8.4", "rand_xorshift", "serde 1.0.136", "serde-big-array", @@ -2020,7 +2089,29 @@ dependencies = [ name = "ockam_transport_core" version = "0.20.0" dependencies = [ + "futures 0.3.21", + "ockam_core", + "ockam_node", + "smoltcp", + "tokio", + "tracing", +] + +[[package]] +name = "ockam_transport_smoltcp" +version = "0.1.0" +dependencies = [ + "async-io", + "atomic-pool", + "futures 0.3.21", + "lazy_static", + "libc", + "managed", "ockam_core", + "ockam_node", + "ockam_transport_core", + "rand 0.8.4", + "smoltcp", "tracing", ] @@ -2068,7 +2159,7 @@ dependencies = [ "ockam_core", "ockam_macros", "ockam_vault_test_suite", - "rand 0.8.5", + "rand 0.8.4", "rand_pcg", "sha2", "signature_bbs_plus", @@ -2089,7 +2180,7 @@ dependencies = [ "ockam_node", "ockam_vault", "ockam_vault_test_suite", - "rand 0.8.5", + "rand 0.8.4", "rand_pcg", "serde 1.0.136", "serde-big-array", @@ -2154,6 +2245,12 @@ dependencies = [ "group", ] +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + [[package]] name = "parking_lot" version = "0.11.2" @@ -2276,6 +2373,19 @@ version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + [[package]] name = "polyval" version = "0.5.3" @@ -2358,18 +2468,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc", + "rand_hc 0.2.0", ] [[package]] name = "rand" -version = "0.8.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", + "rand_hc 0.3.1", ] [[package]] @@ -2419,6 +2530,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + [[package]] name = "rand_pcg" version = "0.3.1" @@ -2657,9 +2777,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" dependencies = [ "itoa", "ryu", @@ -2728,7 +2848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" dependencies = [ "libc", - "mio 0.7.14", + "mio", "signal-hook", ] @@ -2759,7 +2879,7 @@ dependencies = [ "hmac-drbg", "managed", "pairing", - "rand 0.8.5", + "rand 0.8.4", "rand_core 0.6.3", "rand_xorshift", "serde 1.0.136", @@ -2799,7 +2919,7 @@ dependencies = [ "group", "hashbrown 0.11.2", "heapless", - "rand 0.8.5", + "rand 0.8.4", "rand_core 0.6.3", "serde 1.0.136", "serde-big-array", @@ -2820,7 +2940,7 @@ dependencies = [ "hkdf", "hmac-drbg", "pairing", - "rand 0.8.5", + "rand 0.8.4", "rand_chacha 0.3.1", "rand_core 0.6.3", "rand_xorshift", @@ -2844,6 +2964,18 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "smoltcp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2308a1657c8db1f5b4993bab4e620bdbe5623bd81f254cf60326767bb243237" +dependencies = [ + "bitflags", + "byteorder", + "managed", + "rand_core 0.6.3", +] + [[package]] name = "socket2" version = "0.4.4" @@ -2854,6 +2986,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.2" @@ -3126,20 +3264,19 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.17.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" dependencies = [ "bytes 1.1.0", "libc", "memchr", - "mio 0.8.0", + "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.11.2", "pin-project-lite", "signal-hook-registry", - "socket2", "tokio-macros", "winapi", ] @@ -3216,9 +3353,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.31" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if", "pin-project-lite", @@ -3239,12 +3376,11 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.22" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", - "valuable", ] [[package]] @@ -3260,9 +3396,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.9" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" +checksum = "5312f325fe3588e277415f5a6cca1f4ccad0f248c4cd5a4bd33032d7286abc22" dependencies = [ "ansi_term", "lazy_static", @@ -3278,9 +3414,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.56" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d60539445867cdd9680b2bfe2d0428f1814b7d5c9652f09d8d3eae9d19308db" +checksum = "099a24e67e2b4083a6d0beb5a98e274c3160edfb879d71cd2cd14da93786a93b" dependencies = [ "dissimilar", "glob", @@ -3303,7 +3439,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.8.5", + "rand 0.8.4", "sha-1", "thiserror", "url", @@ -3333,9 +3469,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" @@ -3386,12 +3522,6 @@ dependencies = [ "getrandom 0.2.4", ] -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - [[package]] name = "vcell" version = "0.1.3" @@ -3435,6 +3565,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -3447,6 +3583,15 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/implementations/rust/ockam/ockam_core/src/compat.rs b/implementations/rust/ockam/ockam_core/src/compat.rs index a92fe200971..759375a6d5e 100644 --- a/implementations/rust/ockam/ockam_core/src/compat.rs +++ b/implementations/rust/ockam/ockam_core/src/compat.rs @@ -190,22 +190,24 @@ pub mod sync { pub use spin::RwLock; /// spin::Mutex.lock() does not return Option - pub struct Mutex(spin::Mutex); + pub struct Mutex(spin::Mutex); impl Mutex { pub fn new(value: T) -> Self { Mutex(spin::Mutex::new(value)) } + } + impl Mutex { pub fn lock(&self) -> Option> { Some(self.0.lock()) } } - impl core::ops::Deref for Mutex { + impl core::ops::Deref for Mutex { type Target = spin::Mutex; fn deref(&self) -> &spin::Mutex { &self.0 } } - impl core::ops::DerefMut for Mutex { + impl core::ops::DerefMut for Mutex { fn deref_mut(&mut self) -> &mut spin::Mutex { &mut self.0 } diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.lock b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.lock new file mode 100644 index 00000000000..9ad5b275f21 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.lock @@ -0,0 +1,1607 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array 0.14.4", + "heapless", + "rand_core 0.6.3", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.4", + "stable_deref_trait", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "async-io" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "atomic-pool" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b407ed6d721feca5f9432fcd24dec6857debbc8f5d86a75538d871ee85b8b1f" +dependencies = [ + "as-slice 0.1.5", + "as-slice 0.2.1", + "atomic-polyfill", + "stable_deref_trait", +] + +[[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 = "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 = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.4", +] + +[[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 = "cache-padded" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array 0.14.4", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "core2" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cf12d2dad3ed124aa116f59561428478993d69ab81ae4d30e5349c9c5b5a5f6" +dependencies = [ + "memchr", +] + +[[package]] +name = "cortex-m" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac919ef424449ec8c08d515590ce15d9262c0ca5f0da5b0c901e971a3b783b3" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[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 = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.4", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.4", +] + +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "ed25519" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "zeroize", +] + +[[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 = "fastrand" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" +dependencies = [ + "instant", +] + +[[package]] +name = "ff" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "group" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.6", + "serde", +] + +[[package]] +name = "heapless" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1ad878e07405df82b695089e63d278244344f80e764074d0bdfe99b89460f3" +dependencies = [ + "atomic-polyfill", + "hash32", + "spin 0.9.2", + "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 = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] + +[[package]] +name = "libc" +version = "0.2.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e167738f1866a7ec625567bae89ca0d44477232a4f7c52b1c7f2adc2c98804f" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +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 = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +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 = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "ockam" +version = "0.46.0" +dependencies = [ + "arrayref", + "dyn-clone", + "hex", + "ockam_channel", + "ockam_core", + "ockam_identity", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_transport_tcp", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "serde", + "serde-big-array", + "sha2", + "tracing", +] + +[[package]] +name = "ockam_channel" +version = "0.42.0" +dependencies = [ + "ockam_core", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "rand_pcg", + "serde", + "tracing", +] + +[[package]] +name = "ockam_core" +version = "0.46.0" +dependencies = [ + "async-trait", + "cfg-if", + "core2", + "futures-util", + "hashbrown 0.11.2", + "heapless", + "hex", + "ockam_macros", + "rand 0.8.4", + "rand_pcg", + "serde", + "serde_bare", + "spin 0.9.2", + "zeroize", +] + +[[package]] +name = "ockam_executor" +version = "0.15.0" +dependencies = [ + "crossbeam-queue", + "futures", + "heapless", + "ockam_core", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "ockam_identity" +version = "0.36.0" +dependencies = [ + "cfg-if", + "group", + "heapless", + "ockam_channel", + "ockam_core", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "serde", + "serde-big-array", + "sha2", + "tracing", +] + +[[package]] +name = "ockam_key_exchange_core" +version = "0.38.0" +dependencies = [ + "ockam_core", + "zeroize", +] + +[[package]] +name = "ockam_key_exchange_xx" +version = "0.39.0" +dependencies = [ + "ockam_core", + "ockam_key_exchange_core", +] + +[[package]] +name = "ockam_macros" +version = "0.7.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ockam_node" +version = "0.45.0" +dependencies = [ + "futures", + "heapless", + "ockam_core", + "ockam_executor", + "ockam_macros", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ockam_transport_core" +version = "0.20.0" +dependencies = [ + "futures", + "ockam_core", + "ockam_node", + "smoltcp", + "tokio", + "tracing", +] + +[[package]] +name = "ockam_transport_smoltcp" +version = "0.1.0" +dependencies = [ + "async-io", + "atomic-pool", + "futures", + "lazy_static", + "libc", + "managed", + "ockam_core", + "ockam_node", + "ockam_transport_core", + "rand 0.8.4", + "smoltcp", + "tracing", +] + +[[package]] +name = "ockam_transport_tcp" +version = "0.41.0" +dependencies = [ + "hashbrown 0.9.1", + "ockam_core", + "ockam_macros", + "ockam_node", + "ockam_transport_core", + "rand 0.7.3", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "ockam_vault" +version = "0.40.0" +dependencies = [ + "aes-gcm", + "arrayref", + "cfg-if", + "curve25519-dalek", + "ed25519-dalek", + "hkdf", + "ockam_core", + "ockam_macros", + "rand 0.8.4", + "rand_pcg", + "sha2", + "tracing", + "x25519-dalek", +] + +[[package]] +name = "ockam_vault_sync_core" +version = "0.38.0" +dependencies = [ + "ockam_core", + "ockam_macros", + "ockam_node", + "ockam_vault", + "rand 0.8.4", + "rand_pcg", + "serde", + "serde-big-array", + "tracing", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "pin-project-lite" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proc-macro2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.3", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.3", +] + +[[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-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "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 = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[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 = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-big-array" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "serde_bare" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51c55386eed0f1ae957b091dc2ca8122f287b60c79c774cbe3d5f2b69fded660" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signature" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "smoltcp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2308a1657c8db1f5b4993bab4e620bdbe5623bd81f254cf60326767bb243237" +dependencies = [ + "bitflags", + "byteorder", + "libc", + "log", + "managed", + "rand_core 0.6.3", +] + +[[package]] +name = "socket2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[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 = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tcp_examples" +version = "0.0.0" +dependencies = [ + "lazy_static", + "ockam", + "ockam_node", + "ockam_transport_smoltcp", + "serde", + "smoltcp", + "tracing", +] + +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array 0.14.4", + "subtle", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[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 = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "x25519-dalek" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.toml b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.toml new file mode 100644 index 00000000000..2a5a11c85a9 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "tcp_examples" +version = "0.0.0" +authors = ["Ockam Developers"] +edition = "2018" +publish = false + +[features] +default = ["std"] + +# Feature (enabled by default): "std" enables functionality expected to +# be available on a standard platform. +std = [ + "ockam/default", + "ockam_node/default", + "ockam_transport_smoltcp/default", +] + +# Feature: "no_std" enables functionality required for platforms +# without the standard library. +no_std = [ + "ockam/no_std", + "ockam_node/no_std", + "ockam_transport_smoltcp/no_std", +] + +# Feature: "alloc" enables support for heap allocation on "no_std" +# platforms, requires nightly. +alloc = [ + "ockam/alloc", + "ockam_node/alloc", + "ockam_transport_smoltcp/alloc", +] + +[dependencies] +ockam = { path = "../../../ockam", default_features = false, features = ["software_vault"] } +ockam_node = { path = "../../../ockam_node", default_features = false } +ockam_transport_smoltcp = { path = "../../../ockam_transport_smoltcp", default_features = false } +smoltcp = "0.8" +lazy_static = "1.4" + +# TODO: this dependency here is required because rustc doesn't yet +# support re-exporting attributes from crates. Tracking issue: +# https://github.com/rust-lang/rust/issues/27812 +serde = { version = "1.0", features = ["derive"] } +tracing = { version = "0.1", default-features = false } diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/README.md b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/README.md new file mode 100644 index 00000000000..f957630cc06 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/README.md @@ -0,0 +1,59 @@ +# Example using [smoltcp](https://github.com/smoltcp-rs/smoltcp) + +## Description + +[Smoltcp](https://github.com/smoltcp-rs/smoltcp) is a library that allows to run a TCP stack without depending on the OS implementations() + +This example uses a tap interface to demonstrate how to use the smoltcp transport. + +Both the client and server examples use the same `tap0` interface so they can't be ran together, however they are designed to run along the sibling example `tcp` server and client, respectively. + +_TODO: Create a separate example that connects 2 `tap` interface_ + +_TODO: Add an example with a hardware interface_ + +## Preparation + +Create the tap interface: + +```sh +sudo ip tuntap add name tap0 mode tap user $USER +sudo ip link set tap0 up +sudo ip addr add 192.168.69.100/24 dev tap0 +sudo ip -6 addr add fe80::100/64 dev tap0 +sudo ip -6 addr add fdaa::100/64 dev tap0 +sudo ip -6 route add fe80::/64 dev tap0 +sudo ip -6 route add fdaa::/64 dev tap0 +``` + +## Run the server example + +In a terminal in this directory($PWD) run: + +```sh +cargo run --example network_echo_server +``` + +In another terminal on the tcp example directory($PWD/../tcp) run: + +```sh +cargo run --example network_echo_client 192.168.69.1:10222 +``` + +## Run the client example + +In a terminal on the tcp example directory($PWD/../tcp) run: + +```sh +cargo run --example network_echo_server 0.0.0.0:10222 +``` + +In another terminal in this directory($PWD) run: + +```sh +cargo run --example network_echo_client 192.168.69.100:10222 +``` + +## Note + +To see what's happening you want to set the logging level when running any of this example to `INFO` or `TRACE` to do that set the env variable `OCKAM_LOG` to `info` or `trace` respectively. diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_client.rs b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_client.rs new file mode 100644 index 00000000000..9625e0fa248 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_client.rs @@ -0,0 +1,66 @@ +#[macro_use] +extern crate tracing; + +use core::str::FromStr; +use lazy_static::lazy_static; +use ockam::compat::collections::BTreeMap; +use ockam::compat::sync::Mutex; +use ockam::{Context, Result, Route}; +use ockam_transport_smoltcp::{InterfaceConfiguration, SmolTcpTransport, TunTapDevice, TCP, ThreadLocalPortProvider, StdClock}; +use smoltcp::iface::Routes; +use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address}; + +fn get_peer_addr() -> (String, String) { + let mut args = std::env::args().skip(1).take(2); + + ( + args.next().unwrap_or("192.168.69.100:10222".to_string()), + args.next().unwrap_or("192.168.69.1".to_string()), + ) +} + +lazy_static! { + static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); +} + +#[ockam::node] +async fn main(mut ctx: Context) -> Result<()> { + let (peer_addr, bind_ip_addr) = get_peer_addr(); + + let default_gateway = "192.168.69.100"; + + // Configure stack + let mut configuration = InterfaceConfiguration::<_, Routes<'static>>::new( + [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + [IpCidr::new(IpAddress::from_str(&bind_ip_addr).unwrap(), 24)], + &*DEVICE, + ); + + let mut routes = Routes::new(BTreeMap::new()); + routes + .add_default_ipv4_route(Ipv4Address::from_str(&default_gateway).unwrap()) + .unwrap(); + configuration.set_routes(routes); + + // Initialize the TCP stack by opening a connection to a the remote + let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)) + .await?; + + tcp.connect(&peer_addr).await?; + + // Send a message to the remote + ctx.send( + Route::new() + .append_t(TCP, format!("{peer_addr}")) + .append("echo_service"), + String::from("Hello you over there!"), + ) + .await?; + + // Then wait for a message back! + let msg = ctx.receive::().await?; + info!("Received return message: '{msg}'"); + + ctx.stop().await?; + Ok(()) +} diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_server.rs b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_server.rs new file mode 100644 index 00000000000..abef63a6ae4 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/examples/network_echo_server.rs @@ -0,0 +1,70 @@ +//! This example is part of `network_echo` +//! +//! You need to start this binary first, before letting the +//! `network_echo_client` connect to it. + +#[macro_use] +extern crate tracing; + +use core::str::FromStr; +use lazy_static::lazy_static; +use ockam::compat::sync::Mutex; +use ockam::{Context, Result, Routed, Worker}; +use ockam_transport_smoltcp::{InterfaceConfiguration, SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; +use smoltcp::iface::Routes; +use smoltcp::wire::{IpAddress, IpCidr}; + +struct Responder; + +#[ockam::worker] +impl Worker for Responder { + type Context = Context; + type Message = String; + + async fn handle_message(&mut self, ctx: &mut Context, msg: Routed) -> Result<()> { + info!("Responder: {}", msg); + ctx.send(msg.return_route(), msg.body()).await?; + Ok(()) + } +} + +fn get_bind_addr() -> String { + std::env::args() + .skip(1) + .take(1) + .next() + .unwrap_or(format!("192.168.69.1:10222")) +} + +lazy_static! { + static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); +} + +#[ockam::node] +async fn main(ctx: Context) -> Result<()> { + // Get either the default socket address, or a user-input + let bind_addr = get_bind_addr(); + debug!("Binding to: {}", bind_addr); + + // TODO: Should the transport parse it? + let (bind_ip_addr, bind_port) = match bind_addr.split(":").collect::>()[..] { + [bind_ip_addr, bind_port, ..] => (bind_ip_addr, bind_port.parse().unwrap()), + _ => panic!("Cannot parse address"), + }; + + let configuration = InterfaceConfiguration::<_, Routes<'static>>::new( + [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], + &*DEVICE, + ); + let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)) + .await?; + + tcp.listen(bind_port).await?; + + // Create the responder worker + ctx.start_worker("echo_service", Responder).await?; + + // The server never shuts down + Ok(()) +} diff --git a/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/src/lib.rs b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/src/lib.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/smoltcp/src/lib.rs @@ -0,0 +1 @@ + diff --git a/implementations/rust/ockam/ockam_examples/example_projects/tcp/Cargo.lock b/implementations/rust/ockam/ockam_examples/example_projects/tcp/Cargo.lock new file mode 100644 index 00000000000..73b1056340e --- /dev/null +++ b/implementations/rust/ockam/ockam_examples/example_projects/tcp/Cargo.lock @@ -0,0 +1,1384 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", + "rand_core 0.6.3", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "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 = "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 = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[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 = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "core2" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cf12d2dad3ed124aa116f59561428478993d69ab81ae4d30e5349c9c5b5a5f6" +dependencies = [ + "memchr", +] + +[[package]] +name = "cortex-m" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac919ef424449ec8c08d515590ce15d9262c0ca5f0da5b0c901e971a3b783b3" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[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 = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "ed25519" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "zeroize", +] + +[[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 = "ff" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "group" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.6", + "serde", +] + +[[package]] +name = "heapless" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e476c64197665c3725621f0ac3f9e5209aa5e889e02a08b1daf5f16dc5fd952" +dependencies = [ + "atomic-polyfill", + "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 = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +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 = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +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 = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "ockam" +version = "0.46.0" +dependencies = [ + "arrayref", + "dyn-clone", + "hex", + "ockam_channel", + "ockam_core", + "ockam_identity", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_transport_tcp", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "serde", + "serde-big-array", + "sha2", + "tracing", +] + +[[package]] +name = "ockam_channel" +version = "0.42.0" +dependencies = [ + "ockam_core", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "serde", + "tracing", +] + +[[package]] +name = "ockam_core" +version = "0.46.0" +dependencies = [ + "async-trait", + "cfg-if", + "core2", + "futures-util", + "hashbrown 0.11.2", + "heapless", + "hex", + "ockam_macros", + "rand 0.8.4", + "serde", + "serde_bare", + "zeroize", +] + +[[package]] +name = "ockam_executor" +version = "0.15.0" +dependencies = [ + "crossbeam-queue", + "futures", + "heapless", + "ockam_core", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "ockam_identity" +version = "0.36.0" +dependencies = [ + "cfg-if", + "group", + "heapless", + "ockam_channel", + "ockam_core", + "ockam_key_exchange_core", + "ockam_key_exchange_xx", + "ockam_macros", + "ockam_node", + "ockam_vault", + "ockam_vault_sync_core", + "rand 0.8.4", + "serde", + "serde-big-array", + "sha2", + "tracing", +] + +[[package]] +name = "ockam_key_exchange_core" +version = "0.38.0" +dependencies = [ + "ockam_core", + "zeroize", +] + +[[package]] +name = "ockam_key_exchange_xx" +version = "0.39.0" +dependencies = [ + "ockam_core", + "ockam_key_exchange_core", +] + +[[package]] +name = "ockam_macros" +version = "0.7.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ockam_node" +version = "0.45.0" +dependencies = [ + "futures", + "ockam_core", + "ockam_executor", + "ockam_macros", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ockam_transport_core" +version = "0.20.0" +dependencies = [ + "futures", + "ockam_core", + "ockam_node", + "smoltcp", + "tokio", + "tracing", +] + +[[package]] +name = "ockam_transport_tcp" +version = "0.41.0" +dependencies = [ + "hashbrown 0.9.1", + "ockam_core", + "ockam_macros", + "ockam_node", + "ockam_transport_core", + "rand 0.7.3", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "ockam_vault" +version = "0.40.0" +dependencies = [ + "aes-gcm", + "arrayref", + "cfg-if", + "curve25519-dalek", + "ed25519-dalek", + "hkdf", + "ockam_core", + "ockam_macros", + "rand 0.8.4", + "sha2", + "tracing", + "x25519-dalek", +] + +[[package]] +name = "ockam_vault_sync_core" +version = "0.38.0" +dependencies = [ + "ockam_core", + "ockam_macros", + "ockam_node", + "ockam_vault", + "rand 0.8.4", + "serde", + "serde-big-array", + "tracing", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "pin-project-lite" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proc-macro2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.3", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + +[[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-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "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 = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[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 = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-big-array" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "serde_bare" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51c55386eed0f1ae957b091dc2ca8122f287b60c79c774cbe3d5f2b69fded660" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signature" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "smoltcp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2308a1657c8db1f5b4993bab4e620bdbe5623bd81f254cf60326767bb243237" +dependencies = [ + "bitflags", + "byteorder", + "managed", +] + +[[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 = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tcp_examples" +version = "0.0.0" +dependencies = [ + "ockam", + "ockam_node", + "ockam_transport_tcp", + "serde", + "tracing", +] + +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "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 = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[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 = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "x25519-dalek" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/implementations/rust/ockam/ockam_transport_core/Cargo.toml b/implementations/rust/ockam/ockam_transport_core/Cargo.toml index 2228698da5f..0cc6581a8af 100644 --- a/implementations/rust/ockam/ockam_transport_core/Cargo.toml +++ b/implementations/rust/ockam/ockam_transport_core/Cargo.toml @@ -14,22 +14,35 @@ Generic Transport primitives. """ publish = true rust-version = "1.56.0" +resolver = "2" [features] default = ["std"] # Feature (enabled by default): "std" enables functionality expected to # be available on a standard platform. -std = ["ockam_core/std"] +std = [ + "ockam_core/std", + "ockam_node/std", + "tokio", + "tokio/io-util", + "tokio/net", +] # Feature: "no_std" enables functionality required for platforms # without the standard library. -no_std = ["ockam_core/no_std"] +no_std = ["ockam_core/no_std", "ockam_node/no_std"] # Feature: "alloc" enables support for heap allocation on "no_std" # platforms, requires nightly. -alloc = ["ockam_core/alloc"] +alloc = ["ockam_core/alloc", "ockam_node/alloc"] [dependencies] ockam_core = { path = "../ockam_core", version = "^0.46.0", default_features = false } tracing = { version = "0.1", default-features = false } +smoltcp = { version = "0.8", default-features = false, features = [ + "proto-ipv4", +] } +futures = { version = "0.3", default-features = false } +ockam_node = { path = "../ockam_node", version = "0.45", default-features = false } +tokio = { version = "1.8", default-features = false, optional = true } diff --git a/implementations/rust/ockam/ockam_transport_core/src/error.rs b/implementations/rust/ockam/ockam_transport_core/src/error.rs index 1c939106339..b0b22101a05 100644 --- a/implementations/rust/ockam/ockam_transport_core/src/error.rs +++ b/implementations/rust/ockam/ockam_transport_core/src/error.rs @@ -21,7 +21,7 @@ pub enum TransportError { UnknownRoute, /// Failed to parse the socket address InvalidAddress, - /// Failed to read message (buffer exhausted) or failed to send it (size is too big) + /// Failed to read message (buffer exhausted), failed to send it (size is too big) Capacity, /// Failed to encode message Encoding, @@ -29,8 +29,10 @@ pub enum TransportError { Protocol, /// A generic I/O failure GenericIo, - /// PortalInvalidState + /// Portal invalid state PortalInvalidState, + /// Unexpected end of stream encountered + UnexpectedEof, } impl TransportError { @@ -53,6 +55,18 @@ impl From for TransportError { fn from(e: io::Error) -> Self { match e.kind() { io::ErrorKind::ConnectionRefused => Self::PeerNotFound, + io::ErrorKind::UnexpectedEof => Self::UnexpectedEof, + io::ErrorKind::WriteZero => Self::ConnectionDrop, + _ => Self::GenericIo, + } + } +} + +impl From for TransportError { + fn from(e: smoltcp::Error) -> Self { + match e { + smoltcp::Error::Illegal => Self::BindFailed, + smoltcp::Error::Exhausted => Self::Capacity, // TODO: update docs or change error mapping _ => Self::GenericIo, } } diff --git a/implementations/rust/ockam/ockam_transport_core/src/lib.rs b/implementations/rust/ockam/ockam_transport_core/src/lib.rs index fab79b80517..2fcaf9c5f63 100644 --- a/implementations/rust/ockam/ockam_transport_core/src/lib.rs +++ b/implementations/rust/ockam/ockam_transport_core/src/lib.rs @@ -2,6 +2,16 @@ pub use error::TransportError; +#[cfg(feature = "alloc")] +#[macro_use] +extern crate alloc; + mod error; #[cfg(test)] mod error_test; +pub mod tcp; + +/// TCP address type constant +pub const TCP: u8 = 1; + +pub(crate) const CLUSTER_NAME: &str = "_internals.transport.tcp"; diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/mod.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/mod.rs new file mode 100644 index 00000000000..0645373e041 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/mod.rs @@ -0,0 +1,4 @@ +//! TCP functionality shared across transport protocols. +pub mod router; +pub mod traits; +pub mod workers; diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/router/handle.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/router/handle.rs new file mode 100644 index 00000000000..008a02923f6 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/router/handle.rs @@ -0,0 +1,145 @@ +use crate::tcp::traits::{EndpointResolver, IntoSplit, TcpAccepter, TcpBinder, TcpStreamConnector}; +use crate::tcp::workers::{TcpListenProcessor, TcpSendWorker, WorkerPair}; +use crate::TCP; +use core::fmt::Display; +use core::marker::PhantomData; +use core::ops::Deref; +use ockam_core::{async_trait, RouterMessage}; +use ockam_core::{Address, AsyncTryClone, Result}; +use ockam_node::Context; + +// We need alloc here for `async_trait` it's very easy to prevent this by making this clone +// directly inside of `bind` but since `processors` already needs to be an async_trait and +// ockam_core still needs alloc I'll leave this here. +use ockam_core::compat::boxed::Box; + +pub struct TcpRouterHandle { + ctx: Context, + addr: Address, + _endpoint_resolver: PhantomData, +} + +#[async_trait] +impl AsyncTryClone for TcpRouterHandle +where + E: EndpointResolver + Send + Sync, + E::Hostnames: Deref, + E::Peer: Clone + Display + Send + Sync + 'static, + V: Display, +{ + async fn async_try_clone(&self) -> Result { + let child_ctx = self.ctx.new_context(Address::random(0)).await?; + Ok(Self::new(child_ctx, self.addr.clone())) + } +} + +impl TcpRouterHandle +where + E: EndpointResolver + Send + Sync + 'static, + E::Hostnames: Deref, + E::Peer: Clone + Display + Send + Sync + 'static, + V: Display, +{ + pub async fn bind(&self, bind_addr: A, binder: B) -> Result<()> + where + B: TcpBinder + Send, + B::Listener: Send + Sync + 'static, + ::Stream: IntoSplit + Send + Sync, + <::Stream as IntoSplit>::ReadHalf: Send + Unpin, + <::Stream as IntoSplit>::WriteHalf: Send + Unpin, + ::Peer: Send + Sync + Clone + Display, + A: Display, + { + TcpListenProcessor::start( + &self.ctx, + self.async_try_clone().await?, + bind_addr, + binder, + crate::CLUSTER_NAME, + ) + .await + } +} + +impl TcpRouterHandle +where + E: EndpointResolver + Send + Sync, + E::Hostnames: Deref, + E::Peer: Clone + Display + Send + Sync + 'static, + V: Display, +{ + pub(crate) fn new(ctx: Context, addr: Address) -> Self { + Self { + ctx, + addr, + _endpoint_resolver: PhantomData, + } + } + + pub fn ctx(&self) -> &Context { + &self.ctx + } + + pub fn addr(&self) -> &Address { + &self.addr + } + /// Registers the passed pair using accepting from the address format `#` where PROTOCOL is a universal constant identifying the protocol used and `peer` is either the address of hostname of the peer of the given pair. + pub(crate) async fn register( + &self, + pair: &WorkerPair, + ) -> Result<(), ockam_core::Error> + where + T: Deref, + W: Display, + U: Clone + Display, + { + // definition on how to create the used address for the pair. + // Note: not using a lambda to be able to be generic over addr. + fn get_addr(addr: impl Display) -> Address { + format!("{TCP}#{addr}").into() + } + + // define all external addresses for the pair + let tcp_address: Address = get_addr(pair.peer()); + let accepts = pair + .hostnames() + .iter() + .map(get_addr) + .chain(core::iter::once(tcp_address)) + .collect(); + + // internal address of the pair + let self_addr = pair.tx_addr(); + + // Send registration request to router address(Note: the implementation needs to ensure that this message is correctly supported) + self.ctx + .send( + self.addr.clone(), + RouterMessage::Register { accepts, self_addr }, + ) + .await + } + + pub async fn connect(&self, peer: P, stream_connector: S) -> Result<()> + where + P: AsRef, + S: TcpStreamConnector + Send + Sync + 'static, + ::ReadHalf: Send + Unpin + 'static, + ::WriteHalf: Send + Unpin + 'static, + { + let (endpoint, hostnames) = E::resolve_endpoint(peer.as_ref())?; + let pair = TcpSendWorker::start_pair::( + &self.ctx, + None, + stream_connector, + endpoint, + hostnames, + crate::CLUSTER_NAME, + ) + .await?; + + self.register(&pair).await?; + + Ok(()) + } +} diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/router/mod.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/router/mod.rs similarity index 57% rename from implementations/rust/ockam/ockam_transport_tcp/src/router/mod.rs rename to implementations/rust/ockam/ockam_transport_core/src/tcp/router/mod.rs index 71507dab624..20b717e0f08 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/router/mod.rs +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/router/mod.rs @@ -1,12 +1,21 @@ +use super::traits::EndpointResolver; +use super::traits::IntoSplit; +use super::traits::TcpStreamConnector; mod handle; -use crate::{TcpSendWorker, TCP}; +use super::workers::TcpSendWorker; +use crate::TransportError; +use crate::CLUSTER_NAME; +use crate::TCP; +use core::fmt::Display; +use core::iter::Iterator; +use core::marker::PhantomData; use core::ops::Deref; -pub(crate) use handle::*; +pub use handle::TcpRouterHandle; use ockam_core::async_trait; +use ockam_core::compat::boxed::Box; +use ockam_core::compat::collections::BTreeMap; use ockam_core::{Address, LocalMessage, Result, Routed, RouterMessage, Worker}; use ockam_node::Context; -use ockam_transport_core::TransportError; -use std::collections::BTreeMap; use tracing::{debug, trace}; /// A TCP address router and connection listener @@ -17,52 +26,76 @@ use tracing::{debug, trace}; /// /// Optionally you can also start listening for incoming connections /// if the local node is part of a server architecture. -pub(crate) struct TcpRouter { +pub struct TcpRouter { ctx: Context, addr: Address, map: BTreeMap, allow_auto_connection: bool, + stream_connector: T, + cluster_name: &'static str, + _marker: PhantomData<(A, P)>, } -impl TcpRouter { - async fn create_self_handle(&self, ctx: &Context) -> Result { +impl TcpRouter +where + T: TcpStreamConnector + Clone + Send + Sync + 'static, + T::Stream: Send, + ::ReadHalf: Send + Unpin + 'static, + ::WriteHalf: Send + Unpin + 'static, + A: Clone + Display + Sync + Send + 'static, + P: EndpointResolver + Send + Sync + 'static, + P::Hostnames: Deref + Send + Sync, + U: Display + Sync, +{ + async fn create_self_handle(&self, ctx: &Context) -> Result> { let handle_ctx = ctx.new_context(Address::random(0)).await?; let handle = TcpRouterHandle::new(handle_ctx, self.addr.clone()); Ok(handle) } - async fn handle_register(&mut self, accepts: Vec
, self_addr: Address) -> Result<()> { - if let Some(f) = accepts.first().cloned() { + async fn handle_register( + &mut self, + accepts: impl Iterator + Clone, + self_addr: Address, + ) -> Result<()> { + if let Some(f) = accepts.clone().next() { trace!("TCP registration request: {} => {}", f, self_addr); } else { // Should not happen return Err(TransportError::InvalidAddress.into()); } - for accept in &accepts { - if self.map.contains_key(accept) { + for accept in accepts.clone() { + if self.map.contains_key(&accept) { return Err(TransportError::AlreadyConnected.into()); } } for accept in accepts { - self.map.insert(accept.clone(), self_addr.clone()); + self.map.insert(accept, self_addr.clone()); } Ok(()) } - async fn connect(&mut self, peer: String) -> Result
{ - let (peer_addr, hostnames) = TcpRouterHandle::resolve_peer(peer)?; + async fn connect(&mut self, peer_str: &str) -> Result
{ + let (peer_addr, hostnames) = P::resolve_endpoint(peer_str)?; + let pair = TcpSendWorker::start_pair::( + &self.ctx, + None, + self.stream_connector.clone(), + peer_addr, + hostnames, + self.cluster_name, + ) + .await?; + + let tcp_address: Address = format!("{TCP}#{}", pair.peer()).into(); + let accepts = pair + .hostnames() + .into_iter() + .map(|h| format!("{TCP}#{}", h).into()) + .chain(core::iter::once(tcp_address)); - let pair = TcpSendWorker::start_pair(&self.ctx, None, peer_addr, hostnames).await?; - - let tcp_address: Address = format!("{}#{}", TCP, pair.peer()).into(); - let mut accepts = vec![tcp_address]; - accepts.extend( - pair.hostnames() - .iter() - .map(|x| Address::from_string(format!("{}#{}", TCP, x))), - ); let self_addr = pair.tx_addr(); self.handle_register(accepts, self_addr.clone()).await?; @@ -85,13 +118,13 @@ impl TcpRouter { // Connection already exists next = n.clone(); } else { + trace!("Route not found"); // No existing connection - let peer_str; - if let Ok(s) = String::from_utf8(onward.deref().clone()) { - peer_str = s; + let peer_str = if let Ok(s) = core::str::from_utf8(onward) { + s } else { return Err(TransportError::UnknownRoute.into()); - } + }; // TODO: Check if this is the hostname and we have existing/pending connection to this IP if self.allow_auto_connection { @@ -113,10 +146,49 @@ impl TcpRouter { Ok(()) } + + /// Create and register a new TCP router with the node context + /// + /// To also handle incoming connections, use + /// [`TcpRouterHandle::bind`](TcpRouterHandle::bind) + pub async fn register(ctx: &Context, stream_connector: T) -> Result> { + let addr = Address::random(0); + debug!("Initialising new TcpRouter with address {}", &addr); + + let child_ctx = ctx.new_context(Address::random(0)).await?; + + let router = Self { + ctx: child_ctx, + addr: addr.clone(), + map: BTreeMap::new(), + allow_auto_connection: true, + cluster_name: CLUSTER_NAME, + stream_connector, + _marker: PhantomData, + }; + + let handle = router.create_self_handle(ctx).await?; + + ctx.start_worker(addr.clone(), router).await?; + trace!("Registering TCP router for type = {}", TCP); + ctx.register(TCP, addr).await?; + + Ok(handle) + } } #[async_trait] -impl Worker for TcpRouter { +impl Worker for TcpRouter +where + T: TcpStreamConnector + Clone + Send + Sync + 'static, + ::ReadHalf: Send + Unpin + 'static, + ::WriteHalf: Send + Unpin + 'static, + T::Stream: Send, + A: Clone + Display + Sync + Send + 'static, + P: EndpointResolver + Send + Sync + 'static, + P::Hostnames: Deref + Send + Sync, + U: Display + Sync, +{ type Context = Context; type Message = RouterMessage; @@ -137,38 +209,10 @@ impl Worker for TcpRouter { self.handle_route(ctx, msg).await?; } Register { accepts, self_addr } => { - self.handle_register(accepts, self_addr).await?; + self.handle_register(accepts.into_iter(), self_addr).await?; } }; Ok(()) } } - -impl TcpRouter { - /// Create and register a new TCP router with the node context - /// - /// To also handle incoming connections, use - /// [`TcpRouter::bind`](TcpRouter::bind) - pub async fn register(ctx: &Context) -> Result { - let addr = Address::random(0); - debug!("Initialising new TcpRouter with address {}", &addr); - - let child_ctx = ctx.new_context(Address::random(0)).await?; - - let router = Self { - ctx: child_ctx, - addr: addr.clone(), - map: BTreeMap::new(), - allow_auto_connection: true, - }; - - let handle = router.create_self_handle(ctx).await?; - - ctx.start_worker(addr.clone(), router).await?; - trace!("Registering TCP router for type = {}", TCP); - ctx.register(TCP, addr).await?; - - Ok(handle) - } -} diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/io.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/io.rs new file mode 100644 index 00000000000..bd20bc38c76 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/io.rs @@ -0,0 +1,222 @@ +//! Traits based in the `futures::io` crate to support `no_std` compilation. +//! +//! The intend use of these traits is to be implemented for the transport layer to use along the [workers][crate::tcp::workers] in this crate. To see a more complex example of this take a look at the implementation in `ockam_transport_smoltcp::net::tcp` module. +//! +//! The biggest change is using [TransportError] instead of [std::io::Error] for compatibility without std. +//! This module define and implements both [AsyncRead] and [AsyncWrite] from the futures crate but it only implements `write_all` and `read_exact` from [AsyncWriteExt] and [AsyncReadExt] respectively, since those are the only method we use. +//! +//! Note: Although the implementation is based on `futures::io` the traits are auto-implemented only for `tokio::io::AsyncRead` and `tokio::io::AsyncWrite` not for the same structs in `futures::io`. +//! This is becaused to play along with the other ockam crates we needed it to be implemented for `tokio` but the implementation from futures was slightly simpler. The differences on implementation are subtle and we might change it in the future to be more similar to `tokio`. +use crate::error::TransportError; +use core::fmt::Debug; +use core::mem; +use core::pin::Pin; +use futures::{ready, Future}; +use ockam_core::compat::task::{Context, Poll}; + +/// Result from IO operations. +pub type Result = core::result::Result; + +/// Custom definition of `futures::io::AsyncRead` that returns our [Result]. +/// +/// Reads bytes asyncronously from a source. +pub trait AsyncRead { + /// Attempt to read from [AsyncRead] into `buf`. + /// + /// On success, returns `Poll::Ready(Ok(num_bytes_read))`. + /// + /// If no data is available for reading, the method return `Poll::Pending` and arranges for the current task (via `cx.waker().wake_by_ref()`) + /// to receive a notification when the object becomes readable or is closed. + fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) + -> Poll>; +} + +// Auto implementation of `AsyncRead` for any struct implementing `tokio::io::AsyncRead`. +#[cfg(feature = "std")] +impl AsyncRead for T { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let mut buf = tokio::io::ReadBuf::new(buf); + let res = tokio::io::AsyncRead::poll_read(self, cx, &mut buf); + // Tokio's AsyncRead doesn't return the number of bytes read instead this information is stored in `ReadBuf` so here we do the mapping. + res.map_ok(|()| buf.filled().len()) + .map_err(TransportError::from) + } +} + +/// Custom definition of `futures::io::AsyncWrite` that returns our [Result]. +/// +/// Write bytes asynchronously. +pub trait AsyncWrite { + /// Attempt to write bytes from `buf` into the object. + /// + /// On sucess, returns `Poll::Ready(Ok(num_bytes_written))`. + /// + /// If the object is not ready for writing, the method returns `Poll::Pending` and arranges for the current task (via `cx.waker().wake_by_ref()`) to receive a notification when the object becomes writable or is closed. + fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll>; +} + +// Auto implementation of AsyncWrite for any trait implementing `tokio::io::AsyncWrite`. +#[cfg(feature = "std")] +impl AsyncWrite for T { + fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + tokio::io::AsyncWrite::poll_write(self, cx, buf).map_err(|err| err.into()) + } +} + +/// Custom definition of `futures::io::AsyncWriteExt` compatible with our [AsyncWrite]. +/// +/// Provides extension methods to [AsyncWrite]. +pub trait AsyncWriteExt: AsyncWrite { + /// Write data into this object. + /// + /// Creates a future that will write the entire contes of the buffer `buf` into `AsyncWrite`. + /// + /// The returned future will not complete until all the data has been written. + /// + /// # Examples + /// ``` + /// use ockam_transport_core::tcp::traits::io::AsyncWriteExt; + /// use std::io::Cursor; + /// # #[tokio::main] + /// # async fn main() { + /// let mut writer = Cursor::new(vec![0u8;5]); + /// + /// writer.write_all(&[1, 2, 3, 4]).await.unwrap(); + /// + /// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); + /// # } + /// ``` + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self> { + WriteAll::new(self, buf) + } +} + +/// Custom definition of `futures::io::AsynReadExt` compatible with our [AsyncWrite]. +/// +/// Provides extension methods for `AsyncRead`. +pub trait AsyncReadExt: AsyncRead { + /// Creates a future which will read exactly enough bytes to fill `buf`, returning an error ([TransportError::UnexpectedEof]) if end of file is hit sooner. + /// + /// The returned future will resolve once the read operation is completed an will keep returning `Poll::Pending` until the the buffer is filled. + /// + /// In the case of an error the buffer and the object will be discarded, with the error yielded(This will depend on the mapping between the io error and [TransportError]). + /// + /// # Examples + /// ``` + /// use ockam_transport_core::tcp::traits::io::AsyncReadExt; + /// use std::io::Cursor; + /// # #[tokio::main] + /// # async fn main() { + /// let mut reader = Cursor::new([1,2, 3, 4]); + /// let mut output = [0u8; 4]; + /// + /// reader.read_exact(&mut output).await.unwrap(); + /// + /// assert_eq!(output, [1, 2, 3, 4]); + /// # } + /// ``` + /// + /// # Eof is hit before `buf` is filled + /// ``` + /// use ockam_transport_core::tcp::traits::io::AsyncReadExt; + /// use ockam_transport_core::TransportError; + /// use std::io::Cursor; + /// # #[tokio::main] + /// # async fn main() { + /// let mut reader = Cursor::new([1,2, 3, 4]); + /// let mut output = [0u8; 5]; + /// + /// let res = reader.read_exact(&mut output).await; + /// + /// assert_eq!(res.unwrap_err(), TransportError::UnexpectedEof); + /// # } + /// ``` + fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self> { + ReadExact::new(self, buf) + } +} + +impl AsyncWriteExt for T where T: AsyncWrite {} +impl AsyncReadExt for T where T: AsyncRead {} + +/// Future for the [`write_all`](AsyncWriteExt::write_all) method. +#[derive(Debug)] +pub struct WriteAll<'a, W: ?Sized> { + writer: &'a mut W, + buf: &'a [u8], +} + +impl Unpin for WriteAll<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized> WriteAll<'a, W> { + fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { + Self { writer, buf } + } +} + +/// Future for the [`read_exact`](AsyncReadExt::read_exact) method. +#[derive(Debug)] +pub struct ReadExact<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut [u8], +} + +impl Unpin for ReadExact<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized> ReadExact<'a, R> { + fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { + Self { reader, buf } + } +} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> Future for WriteAll<'a, W> { + type Output = Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + // Will consume the buffer contents and write them into the writer until it's empty + while !this.buf.is_empty() { + // Write into the buffer or returns Pending if it's not readdy + let n = ready!(Pin::new(&mut *this.writer).poll_write(cx, this.buf))?; + { + // Shorten the buffer according to the number of written bytes + let (_, rest) = mem::replace(&mut this.buf, &[]).split_at(n); + this.buf = rest; + } + // If `poll_write` returns 0 bytes before the buffer was emptied means the Writer was closed before all the data could be written + if n == 0 { + return Poll::Ready(Err(TransportError::ConnectionDrop)); + } + } + + Poll::Ready(Ok(())) + } +} + +impl<'a, R: AsyncRead + ?Sized + Unpin> Future for ReadExact<'a, R> { + type Output = Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + // Will shrink the slice of the buffer while filling it until the slice is empty + while !this.buf.is_empty() { + // Reads from the Reader into the slice if ready or returns Pending + let n = ready!(Pin::new(&mut *this.reader).poll_read(cx, this.buf))?; + // Shrinks the slice according to the number of bytes read. + { + let (_, rest) = mem::replace(&mut this.buf, &mut []).split_at_mut(n); + this.buf = rest; + } + + // If the slice isn't empty but the Reader return 0 it's because we reach the end of the Reader before filling the buffer + if n == 0 { + return Poll::Ready(Err(TransportError::UnexpectedEof)); + } + } + Poll::Ready(Ok(())) + } +} diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/mod.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/mod.rs new file mode 100644 index 00000000000..c84a294d5f5 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/traits/mod.rs @@ -0,0 +1,248 @@ +//! Trait definition and stub and external crates implementations needed to use the core transport functionality. +//! +//! These traits have to be implemented by a TCP(Could be generalized to other protocols) implementation in order to use the utilities, such as the [workers](crate::tcp::workers) modules, provided by this crate to implement transport protocols. +//! +//! The most important parts of this module are the [IntoSplit], [TcpAccepter] and [TcpBinder] traits, these generalize the behavior we use from a Tcp stream or socket from the standard library so that we can implement in other libraries(such as smoltcp). +//! +//! The rest of the module are no-op implementations and implementations for `tokio::net`. +use self::io::{AsyncRead, AsyncWrite}; + +use crate::TransportError; +use ockam_core::async_trait; +use ockam_core::compat::boxed::Box; + +pub mod io; + +/// A channel that implements `IntoSplit` can be split into two owned halves: one for reading and one for writing +/// +/// Both halves should be able to be used separately and moved independently. +/// +/// This trait generalizes [tokio::net::TcpStream::into_split]. +/// +/// # Example +/// ```no_run +/// use tokio::net::TcpStream; +/// use ockam_transport_core::tcp::traits::IntoSplit; +/// # #[tokio::main] +/// # async fn main() { +/// let stream = TcpStream::connect("127.0.0.1:8080").await.unwrap(); +/// let (read_half, write_half) = stream.into_split(); +/// # } +/// ``` +pub trait IntoSplit { + /// Type of the read half of the splittable channel. + type ReadHalf: AsyncRead + 'static; + + /// Type of the write half of the splittable channel. + type WriteHalf: AsyncWrite + 'static; + + /// Consumes the splittable channel and returns both halfs as a pair `(ReadHalf, WriteHalf)` + fn into_split(self) -> (Self::ReadHalf, Self::WriteHalf); +} + +// Implementation of `IntoSplit` for tokio's TcpStream, it simply forwards the method. +#[cfg(feature = "std")] +impl IntoSplit for tokio::net::TcpStream { + type ReadHalf = tokio::net::tcp::OwnedReadHalf; + type WriteHalf = tokio::net::tcp::OwnedWriteHalf; + + fn into_split(self) -> (Self::ReadHalf, Self::WriteHalf) { + tokio::net::TcpStream::into_split(self) + } +} + +/// A `TcpStreamConnector` will connect to a given endpoint and return a stream. +/// +/// This traits generalizes `tokio::net::TcpStream::connect` to use it with non-std implementations of the TCP stack. +/// +/// Note: that `connect` isn't static in this version because for smoltcp we need a `StackFacade` instance(For type security reasons) in order to connect. +/// # Example +/// ## Using tokio's socket implementation connects to 127.0.0.1:8080 send "hello" and await for 8 bytes to be returned. +/// ```no_run +/// use ockam_transport_core::tcp::traits::{TcpStreamConnector, TokioTcpConnector}; +/// use ockam_transport_core::tcp::traits::io::{AsyncReadExt, AsyncWriteExt}; +/// # #[tokio::main] +/// # async fn main() { +/// // Connect using tokio's socket +/// let connector = TokioTcpConnector; +/// let stream = connector.connect("127.0.0.1:8080").await.unwrap(); +/// +/// // Split the created stream into recv and send halves +/// let (mut rx, mut tx) = stream.into_split(); +/// +/// // Send "hello" +/// let send_buf = "hello".as_bytes(); +/// tx.write_all(&send_buf).await.unwrap(); +/// +/// // Wait to recieve a 8 bytes +/// let mut recv_buf = [0u8; 8]; +/// rx.read_exact(&mut recv_buf).await.unwrap(); +/// # } +/// ``` +#[async_trait] +pub trait TcpStreamConnector { + /// Type of the returned stream. + type Stream: IntoSplit; + + /// Creates an stream to the given endpoint. + async fn connect(&self, peer: A) -> Result; +} + +/// No-op implementor of TcpStreamConnector. +/// +/// This is currently only userd by [TcpListenProcessor](crate::tcp::workers::TcpListenProcessor) so that we can use [TcpSendWorker](crate::tcp::workers::TcpSendWorker) without having to receive a connector that won't be used since we always pass the already connected stream. +#[derive(Debug, Clone, Copy)] +pub(crate) struct NoConnector(pub core::marker::PhantomData); + +// No-op implementation. +#[async_trait] +impl TcpStreamConnector for NoConnector +where + A: Send + 'static, + B: IntoSplit + Sync, +{ + type Stream = B; + async fn connect(&self, _: A) -> Result { + unimplemented!() + } +} + +/// A `TcpBinder` will be able to bind to a specific address and yield a listener that will be ready to accept new connections. +/// +/// This generalizes `tokio::net::TcpListener::bind` to use it with non-std implementations of the TCP stack. +/// +/// Note: that `bind` isn't static in this version because for smoltcp we need a `StackFacade` instance(For type security reasons) in order to connect. +/// # Example +/// ## Using tokio's socket bind it to 127.0.0.1:8080 and await for new connections and echo 8 bytes. +/// ```no_run +/// use ockam_transport_core::tcp::traits::{TcpBinder, TokioTcpBinder}; +/// use ockam_transport_core::tcp::traits::io::{AsyncReadExt, AsyncWriteExt}; +/// # #[tokio::main] +/// # async fn main() { +/// // Bind to 127.0.0.1:8080 +/// let binder = TokioTcpBinder; +/// let listener = binder.bind("127.0.0.1:8080").await.unwrap(); +/// +/// // Await for a new connection +/// let (stream, peer) = listener.accept().await.unwrap(); +/// +/// // Split the stream +/// let (mut rx, mut tx) = stream.into_split(); +/// +/// let mut buf = [0u8;8]; +/// +/// // Read 8 bytes +/// rx.read_exact(&mut buf).await.unwrap(); +/// +/// // Write back the read 8 bytes +/// tx.write_all(&buf).await.unwrap(); +/// # } +/// ``` +#[async_trait] +pub trait TcpBinder { + /// Type of the returned listener. + type Listener: TcpAccepter; + + /// Binds to address `binding` and on sucess returns a `TcpAccepter` that can be used to accept new TCP connections. + /// Note: The user can't depend that binding to port 0 works since there is no insurance that in an non-std platform there is a way to get an available port. + async fn bind(&self, binding: A) -> Result; +} + +/// A TcpAccepter can await for new connections and return an stream that can be used as a channel with the connection +/// +/// This generalizes the behavior of `tokio::net::TcpListener::accept` to use it with non-std implementation of the TCP stack. +/// # Example +/// ## Using tokio's socket bind it to 127.0.0.1:8080 and await for new connections and echo 8 bytes. +/// ```no_run +/// use ockam_transport_core::tcp::traits::{TcpBinder, TokioTcpBinder}; +/// use ockam_transport_core::tcp::traits::io::{AsyncReadExt, AsyncWriteExt}; +/// # #[tokio::main] +/// # async fn main() { +/// // Bind to 127.0.0.1:8080 +/// let binder = TokioTcpBinder; +/// let listener = binder.bind("127.0.0.1:8080").await.unwrap(); +/// +/// // Await for a new connection +/// let (stream, peer) = listener.accept().await.unwrap(); +/// +/// // Split the stream +/// let (mut rx, mut tx) = stream.into_split(); +/// +/// let mut buf = [0u8;8]; +/// +/// // Read 8 bytes +/// rx.read_exact(&mut buf).await.unwrap(); +/// +/// // Write back the read 8 bytes +/// tx.write_all(&buf).await.unwrap(); +/// # } +/// ``` +#[async_trait] +pub trait TcpAccepter { + /// Type of the returned stream. + type Stream: IntoSplit; + + /// Type for the address of the connected peer. + type Peer; + + /// Awaits for an incoming connection and on sucess returns a tuple (stream, peer). + async fn accept(&mut self) -> Result<(Self::Stream, Self::Peer), TransportError>; +} + +pub trait EndpointResolver { + type Hostnames; + type Peer; + fn resolve_endpoint(peer: &str) -> Result<(Self::Peer, Self::Hostnames), ockam_core::Error>; +} + +// Implementation of `TcpAccepter` for tokio +#[cfg(feature = "std")] +#[async_trait] +impl TcpAccepter for tokio::net::TcpListener { + type Stream = tokio::net::TcpStream; + type Peer = std::net::SocketAddr; + async fn accept(&mut self) -> Result<(Self::Stream, Self::Peer), TransportError> { + tokio::net::TcpListener::accept(self) + .await + .map_err(TransportError::from) + } +} + +/// Type that can be instanced that implements [TcpBinder] for tokio's sockets. +#[cfg(feature = "std")] +#[derive(Debug, Clone, Copy)] +pub struct TokioTcpBinder; + +#[cfg(feature = "std")] +#[async_trait] +impl TcpBinder for TokioTcpBinder +where + A: tokio::net::ToSocketAddrs + Send + 'static, +{ + type Listener = tokio::net::TcpListener; + async fn bind(&self, addr: A) -> Result { + tokio::net::TcpListener::bind(addr) + .await + .map_err(TransportError::from) + } +} + +/// Type that can be instanced that implements [TcpStreamConnector] for tokio's sockets. +#[cfg(feature = "std")] +#[derive(Debug, Clone, Copy)] +pub struct TokioTcpConnector; + +#[cfg(feature = "std")] +#[async_trait] +impl TcpStreamConnector for TokioTcpConnector +where + A: Send + tokio::net::ToSocketAddrs + 'static, +{ + type Stream = tokio::net::TcpStream; + + async fn connect(&self, peer: A) -> Result { + tokio::net::TcpStream::connect(peer) + .await + .map_err(TransportError::from) + } +} diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/listener.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/listener.rs new file mode 100644 index 00000000000..0b26a163718 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/listener.rs @@ -0,0 +1,107 @@ +use crate::tcp::traits::{EndpointResolver, NoConnector}; +use crate::tcp::workers::TcpSendWorker; +use crate::TransportError; +use core::fmt::Display; +use core::ops::Deref; +use ockam_core::async_trait; +use ockam_core::compat::boxed::Box; +use ockam_core::{Address, Processor, Result}; +use ockam_node::Context; +use tracing::{debug, trace}; + +use crate::tcp::router::TcpRouterHandle; +use crate::tcp::traits::{IntoSplit, TcpAccepter, TcpBinder}; + +/// A TCP Processor that listen for new connections and launch a new [WorkerPair](super::sender::WorkerPair) for each one. +/// +/// The new Pair will be then registered with a `Router`. +pub struct TcpListenProcessor { + inner: T, + router_handle: TcpRouterHandle, + cluster_name: &'static str, +} + +impl TcpListenProcessor +where + T: TcpAccepter + Send + Sync + 'static, + T::Stream: IntoSplit + Send + Sync + 'static, + T::Peer: Send + Sync + Clone + Display + 'static, + ::ReadHalf: Send + Unpin, + ::WriteHalf: Send + Unpin, + E: EndpointResolver + Send + Sync + 'static, + E::Hostnames: Deref, + E::Peer: Send + Sync + Clone + Display, + V: Display, +{ + /// Creates and start a new [TcpListenProcessor]. + pub(crate) async fn start( + ctx: &Context, + router_handle: TcpRouterHandle, + addr: A, + binder: B, + cluster_name: &'static str, + ) -> Result<()> + where + B: TcpBinder, + A: Display, + { + let waddr = Address::random(0); + + debug!("Binding TcpListener to {}", addr); + let inner = binder.bind(addr).await.map_err(TransportError::from)?; + let worker = Self { + inner, + router_handle, + cluster_name, + }; + + ctx.start_processor(waddr, worker).await?; + Ok(()) + } +} + +#[async_trait] +impl Processor for TcpListenProcessor +where + T: Send + TcpAccepter + Sync + 'static, + T::Peer: Send + Display + Sync + Clone + 'static, + T::Stream: IntoSplit + Send + Sync + 'static, + ::ReadHalf: Send + Unpin, + ::WriteHalf: Send + Unpin, + E: EndpointResolver + Send + Sync + 'static, + E::Hostnames: Deref, + V: Display, + E::Peer: Send + Display + Sync + Clone + 'static, +{ + type Context = Context; + + async fn initialize(&mut self, ctx: &mut Context) -> Result<()> { + ctx.set_cluster(self.cluster_name).await + } + + async fn process(&mut self, ctx: &mut Self::Context) -> Result { + trace!("Waiting for incoming TCP connection..."); + + // Wait for an incoming connection + let (stream, peer) = self.inner.accept().await.map_err(TransportError::from)?; + + let empty: &'static [&'static str] = &[]; + // And spawn a connection worker for it + // TODO: Here stream_connector is not really needed, in fact it's never needed when stream is passed + // Reflecting that in the API will ease the use of TcpSendWorker. + let pair = TcpSendWorker::start_pair( + ctx, + Some(stream), + NoConnector(core::marker::PhantomData::), + peer, + empty, + self.cluster_name, + ) + .await?; + + // Register the connection with the local TcpRouter + self.router_handle.register(&pair).await?; + + Ok(true) + } +} diff --git a/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/mod.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/mod.rs new file mode 100644 index 00000000000..e55f7806799 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/mod.rs @@ -0,0 +1,9 @@ +//! Workers used to implement TCP transport protocols. +mod listener; +mod receiver; +mod sender; + +use receiver::TcpRecvProcessor; + +pub use listener::TcpListenProcessor; +pub use sender::{TcpSendWorker, WorkerPair}; diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/workers/receiver.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/receiver.rs similarity index 51% rename from implementations/rust/ockam/ockam_transport_tcp/src/workers/receiver.rs rename to implementations/rust/ockam/ockam_transport_core/src/tcp/workers/receiver.rs index 8d721945f0d..4650dba2d78 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/workers/receiver.rs +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/receiver.rs @@ -1,51 +1,53 @@ -use ockam_core::async_trait; -use ockam_core::{Address, Decodable, LocalMessage, Processor, Result, TransportMessage}; +use crate::TransportError; +use ockam_core::compat::{boxed::Box, vec::Vec}; +use ockam_core::{ + async_trait, Address, Decodable, LocalMessage, Processor, Result, TransportMessage, +}; use ockam_node::Context; -use ockam_transport_core::TransportError; -use tokio::{io::AsyncReadExt, net::tcp::OwnedReadHalf}; use tracing::{error, info, trace}; +use crate::tcp::traits::io::{AsyncRead, AsyncReadExt}; + /// A TCP receiving message worker /// -/// Create this worker type by calling -/// [`start_tcp_worker`](crate::start_tcp_worker)! +/// This type will be created by [TcpSendWorker::start_pair](super::sender::TcpSendWorker::start_pair) /// /// This half of the worker is created when spawning a new connection /// worker pair, and listens for incoming TCP packets, to relay into /// the node message system. -pub(crate) struct TcpRecvProcessor { - rx: OwnedReadHalf, +pub(crate) struct TcpRecvProcessor { peer_addr: Address, + tcp_stream: R, + cluster_name: &'static str, } -impl TcpRecvProcessor { - pub fn new(rx: OwnedReadHalf, peer_addr: Address) -> Self { - Self { rx, peer_addr } +impl TcpRecvProcessor { + pub fn new(tcp_stream: R, peer_addr: Address, cluster_name: &'static str) -> Self { + Self { + peer_addr, + tcp_stream, + cluster_name, + } } } #[async_trait] -impl Processor for TcpRecvProcessor { +impl Processor for TcpRecvProcessor +where + R: AsyncRead + Send + Unpin + 'static, +{ type Context = Context; async fn initialize(&mut self, ctx: &mut Context) -> Result<()> { - ctx.set_cluster(crate::CLUSTER_NAME).await + ctx.set_cluster(self.cluster_name).await } - // We are using the initialize function here to run a custom loop, - // while never listening for messages sent to our address - // - // Note: when the loop exits, we _must_ call stop_worker(..) on - // Context not to spawn a zombie task. - // - // Also: we must stop the TcpReceive loop when the worker gets - // killed by the user or node. async fn process(&mut self, ctx: &mut Context) -> Result { - // Run in a loop until TcpWorkerPair::stop() is called - // First read a message length header... - let len = match self.rx.read_u16().await { - Ok(len) => len, - Err(_e) => { + let mut len_buf = [0; 2]; // TODO Optimization: read into unitialized buffer + let len = match self.tcp_stream.read_exact(&mut len_buf[..]).await { + Ok(_) => u16::from_be_bytes(len_buf), + Err(e) => { + trace!("Got error: {e:?} while processing new tcp packets"); info!( "Connection to peer '{}' was closed; dropping stream", self.peer_addr @@ -54,16 +56,17 @@ impl Processor for TcpRecvProcessor { } }; - trace!("Received message header for {} bytes", len); + trace!("Received message header for {len} bytes"); // Allocate a buffer of that size + // TODO allocation(Very similar case as bufer allocation for sockets[in net/stack.rs]) let mut buf = vec![0; len as usize]; // Then Read into the buffer - match self.rx.read_exact(&mut buf).await { + match self.tcp_stream.read_exact(&mut buf).await { Ok(_) => {} _ => { - error!("Failed to receive message of length: {}", len); + error!("Failed to receive message of length: {len}"); return Ok(true); } } @@ -71,11 +74,6 @@ impl Processor for TcpRecvProcessor { // Deserialize the message now let mut msg = TransportMessage::decode(&buf).map_err(|_| TransportError::RecvBadMessage)?; - // Heartbeat message - if msg.onward_route.next().is_err() { - trace!("Got heartbeat message from: {}", self.peer_addr); - } - // Insert the peer address into the return route so that // reply routing can be properly resolved msg.return_route.modify().prepend(self.peer_addr.clone()); diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/workers/sender.rs b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/sender.rs similarity index 60% rename from implementations/rust/ockam/ockam_transport_tcp/src/workers/sender.rs rename to implementations/rust/ockam/ockam_transport_core/src/tcp/workers/sender.rs index 151448ed0f7..9ab10cf0c72 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/workers/sender.rs +++ b/implementations/rust/ockam/ockam_transport_core/src/tcp/workers/sender.rs @@ -1,30 +1,43 @@ -use crate::TcpRecvProcessor; +use super::TcpRecvProcessor; +use crate::tcp::traits::io::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use crate::tcp::traits::{IntoSplit, TcpStreamConnector}; +use crate::TransportError; +use core::fmt::Display; +use core::ops::Deref; use core::time::Duration; -use ockam_core::{async_trait, route, Any, Decodable, LocalMessage}; -use ockam_core::{Address, Encodable, Result, Routed, TransportMessage, Worker}; +use ockam_core::compat::boxed::Box; +use ockam_core::compat::vec::Vec; +use ockam_core::{ + async_trait, route, Address, Any, Decodable, Encodable, LocalMessage, Result, Routed, + TransportMessage, Worker, +}; use ockam_node::{Context, Heartbeat}; -use ockam_transport_core::TransportError; -use std::net::SocketAddr; -use tokio::io::AsyncWriteExt; -use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; -use tokio::net::TcpStream; use tracing::{debug, trace, warn}; /// Transmit and receive peers of a TCP connection #[derive(Debug)] -pub(crate) struct WorkerPair { - hostnames: Vec, - peer: SocketAddr, +pub struct WorkerPair { + hostnames: T, + endpoint: U, tx_addr: Address, } -impl WorkerPair { - pub fn hostnames(&self) -> &[String] { +impl WorkerPair +where + T: Deref, + U: Clone, +{ + /// Returns the hostnames of the remote peer associated with the worker pair. + pub fn hostnames(&self) -> &[V] { &self.hostnames } - pub fn peer(&self) -> SocketAddr { - self.peer + + /// Returns the socket address of the peer to the worker pair. + pub fn peer(&self) -> U { + self.endpoint.clone() } + + /// Returns the external address of the pair. pub fn tx_addr(&self) -> Address { self.tx_addr.clone() } @@ -33,27 +46,41 @@ impl WorkerPair { /// A TCP sending message worker /// /// Create this worker type by calling -/// [`start_tcp_worker`](crate::start_tcp_worker)! +/// [TcpSendWorker::start_pair] /// /// This half of the worker is created when spawning a new connection /// worker pair, and listens for messages from the node message system /// to dispatch to a remote peer. -pub(crate) struct TcpSendWorker { - rx: Option, - tx: Option, - peer: SocketAddr, +pub struct TcpSendWorker { + rx: Option, + tx: Option, + stream_connector: V, + endpoint: W, internal_addr: Address, heartbeat: Heartbeat>, heartbeat_interval: Option, + cluster_name: &'static str, } -impl TcpSendWorker { - fn new( - stream: Option, - peer: SocketAddr, +impl TcpSendWorker +where + W: Display + Clone + Send + Sync + 'static, + V: TcpStreamConnector + Send + Sync + 'static, + V::Stream: IntoSplit, + T: AsyncRead + Send + Unpin + 'static, + U: AsyncWrite + Send + Unpin + 'static, +{ + fn new( + stream: Option, + stream_connector: V, + endpoint: W, internal_addr: Address, + cluster_name: &'static str, heartbeat: Heartbeat>, - ) -> Self { + ) -> Self + where + Y: IntoSplit, + { let (rx, tx) = match stream { Some(s) => { let (rx, tx) = s.into_split(); @@ -65,37 +92,51 @@ impl TcpSendWorker { Self { rx, tx, - peer, + stream_connector, + endpoint, internal_addr, heartbeat, heartbeat_interval: Some(Duration::from_secs(5 * 60)), + cluster_name, } } - pub(crate) async fn start_pair( + /// Starts a pair of recv/send workers to process messages from `peer`. + /// + /// It returns a [WorkerPair] that holds the information of the pair of workers. + pub async fn start_pair( ctx: &Context, - stream: Option, - peer: SocketAddr, - hostnames: Vec, - ) -> Result { + stream: Option, + stream_connector: V, + endpoint: W, + hostnames: Z, + cluster_name: &'static str, + ) -> Result> + where + Y: IntoSplit, + { trace!("Creating new TCP worker pair"); let tx_addr = Address::random(0); let internal_addr = Address::random(0); let sender = TcpSendWorker::new( stream, - peer, + stream_connector, + endpoint.clone(), internal_addr.clone(), + cluster_name, Heartbeat::create(ctx, internal_addr.clone(), vec![]).await?, ); + // TODO allocation + // Here the allocation is due to AdressSet: From<[Adress; 2]> or something similar not being implemented ctx.start_worker(vec![tx_addr.clone(), internal_addr], sender) .await?; // Return a handle to the worker pair Ok(WorkerPair { hostnames, - peer, + endpoint, tx_addr, }) } @@ -132,17 +173,25 @@ fn prepare_message(msg: TransportMessage) -> Result> { } #[async_trait] -impl Worker for TcpSendWorker { +impl Worker for TcpSendWorker +where + V: TcpStreamConnector + Send + Sync + 'static, + X: IntoSplit, + T: Send + AsyncRead + Unpin + 'static, + U: Send + AsyncWrite + Unpin + 'static, + W: Clone + Send + Sync + core::fmt::Display + 'static, +{ type Context = Context; type Message = Any; async fn initialize(&mut self, ctx: &mut Self::Context) -> Result<()> { - ctx.set_cluster(crate::CLUSTER_NAME).await?; + ctx.set_cluster(self.cluster_name).await?; if self.tx.is_none() { - let (rx, tx) = TcpStream::connect(self.peer) - .await - .map_err(TransportError::from)? + let (rx, tx) = self + .stream_connector + .connect(self.endpoint.clone()) + .await? .into_split(); self.tx = Some(tx); self.rx = Some(rx); @@ -150,8 +199,11 @@ impl Worker for TcpSendWorker { if let Some(rx) = self.rx.take() { let rx_addr = Address::random(0); - let receiver = - TcpRecvProcessor::new(rx, format!("{}#{}", crate::TCP, self.peer).into()); + let receiver = TcpRecvProcessor::new( + rx, + format!("{}#{}", crate::TCP, self.endpoint).into(), + self.cluster_name, + ); ctx.start_processor(rx_addr.clone(), receiver).await?; } else { return Err(TransportError::GenericIo.into()); @@ -184,13 +236,13 @@ impl Worker for TcpSendWorker { let msg = prepare_message(msg)?; // Sending empty heartbeat if tx.write_all(&msg).await.is_err() { - warn!("Failed to send heartbeat to peer {}", self.peer); + warn!("Failed to send heartbeat to peer {}", self.endpoint); ctx.stop_worker(ctx.address()).await?; return Ok(()); } - debug!("Sent heartbeat to peer {}", self.peer); + debug!("Sent heartbeat to peer {}", self.endpoint); } else { let mut msg = LocalMessage::decode(msg.payload())?.into_transport_message(); // Remove our own address from the route so the other end @@ -200,7 +252,7 @@ impl Worker for TcpSendWorker { let msg = prepare_message(msg)?; if tx.write_all(msg.as_slice()).await.is_err() { - warn!("Failed to send message to peer {}", self.peer); + warn!("Failed to send message to peer {}", self.endpoint); ctx.stop_worker(ctx.address()).await?; return Ok(()); diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/Cargo.toml b/implementations/rust/ockam/ockam_transport_smoltcp/Cargo.toml new file mode 100644 index 00000000000..a6b6c09aedc --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/Cargo.toml @@ -0,0 +1,77 @@ +[package] +name = "ockam_transport_smoltcp" +version = "0.1.0" +authors = ["Ockam Developers"] +edition = "2018" +license = "Apache-2.0" +homepage = "https://github.com/ockam-network/ockam" +repository = "https://github.com/ockam-network/ockam/implementations/rust/ockam/ockam_transport_tcp" +readme = "README.md" +keywords = ["ockam", "crypto", "network", "networking", "tcp"] +categories = [ + "cryptography", + "asynchronous", + "authentication", + "network-programming", + "embedded", +] + +exclude = ["DEVELOP.md", "LICENSE"] +autoexamples = false + +[features] +# Pool sizes allowed for packet buffer +pool-32 = [] +pool-16 = [] +pool-8 = [] +pool-4 = [] + +default = ["std", "pool-32"] +std = [ + "smoltcp/std", + "ockam_core/std", + "ockam_node/std", + "ockam_transport_core/std", + "rand", + "async-io", + "libc", + "managed/std", + "pool-32", +] +no_std = [ + "ockam_core/no_std", + "ockam_node/no_std", + "ockam_transport_core/no_std", + "lazy_static/spin_no_std", + "pool-4", +] +alloc = [ + "smoltcp/alloc", + "ockam_core/alloc", + "ockam_node/alloc", + "ockam_transport_core/alloc", + "managed/alloc", + "pool-4", +] + +[dependencies] +smoltcp = { version = "0.8", default_features = false, features = [ + "proto-ipv4", + "proto-ipv6", + "medium-ethernet", + "socket-tcp", + "async", +] } +ockam_core = { path = "../ockam_core", version = "0.46", default_features = false } +ockam_node = { path = "../ockam_node", version = "0.45", default_features = false } +tracing = { version = "0.1", default-features = false } +ockam_transport_core = { path = "../ockam_transport_core", version = "0.20" } +futures = { version = "0.3", default-features = false } +lazy_static = { version = "1.4", default-features = false } +managed = { version = "0.8", default-features = false } +atomic-pool = { version = "0.2", default-features = false } + +# Std only dependencies +libc = { version = "0.2", optional = true } +rand = { version = "0.8", optional = true } +async-io = { version = "1.6", optional = true } diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/lib.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/lib.rs new file mode 100644 index 00000000000..088df717b43 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/lib.rs @@ -0,0 +1,21 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "alloc")] +#[macro_use] +extern crate alloc; + +mod net; +mod port_provider; +mod transport; + +// Tap devices only make sense in std +#[cfg(feature = "std")] +pub use crate::net::TunTapDevice; + +#[cfg(feature = "std")] +pub use port_provider::ThreadLocalPortProvider; + +pub use net::{Clock, Device, Instant, InterfaceConfiguration, StackFacade, StdClock}; +pub use ockam_transport_core::TCP; +pub use port_provider::PortProvider; +pub use transport::*; diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/mod.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/mod.rs new file mode 100644 index 00000000000..45bc20b751d --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/mod.rs @@ -0,0 +1,150 @@ +// This file is based on [embassy's device](https://github.com/embassy-rs/embassy/blob/3396a519389837727c17eae2ebf65d5c93f70551/embassy-net/src/device.rs) +use ockam_core::compat::task::Waker; +use smoltcp::phy::Device as SmolDevice; +use smoltcp::phy::DeviceCapabilities; +use smoltcp::time::Instant as SmolInstant; +use smoltcp::Result; + +use ockam_core::compat::sync::Mutex; + +use packet_pool::PacketBoxExt; +use packet_pool::{Packet, PacketBox, PacketBuf}; + +mod packet_pool; + +// Tap devices only make sense in std +#[cfg(feature = "std")] +mod tuntap; + +// Tap devices only make sense in std +#[cfg(feature = "std")] +pub use tuntap::TunTapDevice; + +// This Device is very similar to Smoltcp's device however it makes the need +// to handle `Waker` explicit +/// Similar to [smoltcp::phy::Device] but allows passing a `Waker` explicitly. +pub trait Device { + /// Returns whether the device is prepared to start sending packages. + fn is_transmit_ready(&mut self) -> bool; + /// Transmits a package, if the buffer is full the `waker` should be signaled once the device is available to send again. + fn transmit(&mut self, pkt: PacketBuf, waker: &Option); + /// Recieves a package, if no package is available yet the `waker` should be signaled once the package is ready. + fn receive(&mut self, waker: &Option) -> Option; + /// Returns the device's [DeviceCapabilities] + fn capabilities(&mut self) -> DeviceCapabilities; +} + +pub struct DeviceAdapter { + // Note: This Mutex is not strictly necessary since `DeviceAdapter will always sit behind a `Stack` which is hold behind a Mutex. + // However, we do need to mutate `device` which would require unsafe so to keep it simple for now we will keep the `Mutex`. + pub device: &'static Mutex<(dyn Device + Send)>, + caps: DeviceCapabilities, + waker: Option, +} + +impl DeviceAdapter { + pub(crate) fn new(device: &'static Mutex<(dyn Device + Send)>) -> Self { + let caps = device.lock().unwrap().capabilities(); + Self { + caps, + device, + waker: None, + } + } + + pub(crate) fn get_waker(&self) -> &Option { + &self.waker + } + + pub(crate) fn register_waker(&mut self, waker: &Waker) { + match self.waker { + // Optimization: If both the old and new Wakers wake the same task, we can simply + // keep the old waker, skipping the clone. (In most executor implementations, + // cloning a waker is somewhat expensive, comparable to cloning an Arc). + Some(ref w2) if (w2.will_wake(waker)) => {} + _ => { + // clone the new waker and store it + if let Some(old_waker) = core::mem::replace(&mut self.waker, Some(waker.clone())) { + // We had a waker registered for another task. Wake it, so the other task can + // reregister itself if it's still interested. + // + // If two tasks are waiting on the same thing concurrently, this will cause them + // to wake each other in a loop fighting over this WakerRegistration. This wastes + // CPU but things will still work. + // + // If the user wants to have two tasks waiting on the same thing they should use + // a more appropriate primitive that can store multiple wakers. + old_waker.wake() + } + } + } + } +} + +impl<'a> SmolDevice<'a> for DeviceAdapter { + type RxToken = RxToken; + type TxToken = TxToken<'a>; + + fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { + let tx_pkt = PacketBox::new(Packet::new())?; + let rx_pkt = Mutex::lock(self.device).unwrap().receive(&self.waker)?; + let rx_token = RxToken { pkt: rx_pkt }; + let tx_token = TxToken { + device: self.device, + pkt: tx_pkt, + waker: &self.waker, + }; + + Some((rx_token, tx_token)) + } + + /// Construct a transmit token. + fn transmit(&'a mut self) -> Option { + if !self.device.lock().unwrap().is_transmit_ready() { + return None; + } + + let tx_pkt = PacketBox::new(Packet::new())?; + Some(TxToken { + device: self.device, + pkt: tx_pkt, + waker: &self.waker, + }) + } + + /// Get a description of device capabilities. + fn capabilities(&self) -> DeviceCapabilities { + self.caps.clone() + } +} + +pub struct RxToken { + pkt: PacketBuf, +} + +impl smoltcp::phy::RxToken for RxToken { + fn consume(mut self, _timestamp: SmolInstant, f: F) -> Result + where + F: FnOnce(&mut [u8]) -> Result, + { + f(&mut self.pkt) + } +} + +pub struct TxToken<'a> { + device: &'static Mutex<(dyn Device + Send)>, + pkt: PacketBox, + waker: &'a Option, +} + +impl<'a> smoltcp::phy::TxToken for TxToken<'a> { + fn consume(self, _timestamp: SmolInstant, len: usize, f: F) -> Result + where + F: FnOnce(&mut [u8]) -> Result, + { + let mut buf = self.pkt.slice(0..len); + let r = f(&mut buf)?; + self.device.lock().unwrap().transmit(buf, self.waker); + Ok(r) + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/packet_pool.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/packet_pool.rs new file mode 100644 index 00000000000..1df856cde1b --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/packet_pool.rs @@ -0,0 +1,77 @@ +// This is copied verbatim(Some stuff we don't need removed) from [embassy](https://github.com/embassy-rs/embassy/blob/7561fa19348530ce85e2645e0be8801b9b2bbe13/embassy-net/src/packet_pool.rs) +// One advantage of using atomic_pool instead of heapless it doesn't seem to have the same kind of ABA problem. +use core::ops::{Deref, DerefMut, Range}; + +use atomic_pool::{pool, Box}; + +const MTU: usize = 1516; + +#[cfg(feature = "pool-4")] +pub(crate) const PACKET_POOL_SIZE: usize = 4; + +#[cfg(feature = "pool-8")] +pub(crate) const PACKET_POOL_SIZE: usize = 8; + +#[cfg(feature = "pool-16")] +pub(crate) const PACKET_POOL_SIZE: usize = 16; + +#[cfg(feature = "pool-32")] +pub(crate) const PACKET_POOL_SIZE: usize = 32; + +pool!(pub(crate) PacketPool: [Packet; PACKET_POOL_SIZE]); +pub(crate) type PacketBox = Box; + +#[repr(align(4))] +pub(crate) struct Packet([u8; MTU]); + +impl Packet { + pub(crate) const fn new() -> Self { + Self([0; MTU]) + } +} + +pub(crate) trait PacketBoxExt { + fn slice(self, range: Range) -> PacketBuf; +} + +impl PacketBoxExt for PacketBox { + fn slice(self, range: Range) -> PacketBuf { + PacketBuf { + packet: self, + range, + } + } +} + +impl Deref for Packet { + type Target = [u8; MTU]; + + fn deref(&self) -> &[u8; MTU] { + &self.0 + } +} + +impl DerefMut for Packet { + fn deref_mut(&mut self) -> &mut [u8; MTU] { + &mut self.0 + } +} + +pub struct PacketBuf { + packet: PacketBox, + range: Range, +} + +impl Deref for PacketBuf { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.packet[self.range.clone()] + } +} + +impl DerefMut for PacketBuf { + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.packet[self.range.clone()] + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/tuntap.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/tuntap.rs new file mode 100644 index 00000000000..02b45c65187 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/device/tuntap.rs @@ -0,0 +1,215 @@ +// Copied from: https://github.com/embassy-rs/embassy/blob/master/examples/std/src/tuntap.rs +// (Almost verbatim save from `TunTap::transmit` which implements a queue when `WouldBlock` would happen) +#![cfg(feature = "std")] + +use async_io::Async; +use std::io::{Read, Write}; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::{collections::VecDeque, io}; + +pub const SIOCGIFMTU: libc::c_ulong = 0x8921; +pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933; +pub const _ETH_P_ALL: libc::c_short = 0x0003; +pub const TUNSETIFF: libc::c_ulong = 0x400454CA; +pub const _IFF_TUN: libc::c_int = 0x0001; +pub const IFF_TAP: libc::c_int = 0x0002; +pub const IFF_NO_PI: libc::c_int = 0x1000; + +const ETHERNET_HEADER_LEN: usize = 14; + +#[repr(C)] +#[derive(Debug)] +struct ifreq { + ifr_name: [libc::c_char; libc::IF_NAMESIZE], + ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ +} + +fn ifreq_for(name: &str) -> ifreq { + let mut ifreq = ifreq { + ifr_name: [0; libc::IF_NAMESIZE], + ifr_data: 0, + }; + for (i, byte) in name.as_bytes().iter().enumerate() { + ifreq.ifr_name[i] = *byte as libc::c_char + } + ifreq +} + +fn ifreq_ioctl( + lower: libc::c_int, + ifreq: &mut ifreq, + cmd: libc::c_ulong, +) -> io::Result { + unsafe { + let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq); + if res == -1 { + return Err(io::Error::last_os_error()); + } + } + + Ok(ifreq.ifr_data) +} + +#[derive(Debug)] +pub struct TunTap { + fd: libc::c_int, + mtu: usize, +} + +impl AsRawFd for TunTap { + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +impl TunTap { + pub fn new(name: &str) -> io::Result { + unsafe { + let fd = libc::open( + "/dev/net/tun\0".as_ptr() as *const libc::c_char, + libc::O_RDWR | libc::O_NONBLOCK, + ); + if fd == -1 { + return Err(io::Error::last_os_error()); + } + + let mut ifreq = ifreq_for(name); + ifreq.ifr_data = IFF_TAP | IFF_NO_PI; + ifreq_ioctl(fd, &mut ifreq, TUNSETIFF)?; + + let socket = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); + if socket == -1 { + return Err(io::Error::last_os_error()); + } + + let ip_mtu = ifreq_ioctl(socket, &mut ifreq, SIOCGIFMTU); + libc::close(socket); + let ip_mtu = ip_mtu? as usize; + + // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) + // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. + let mtu = ip_mtu + ETHERNET_HEADER_LEN; + + Ok(TunTap { fd, mtu }) + } + } +} + +impl Drop for TunTap { + fn drop(&mut self) { + unsafe { + libc::close(self.fd); + } + } +} + +impl io::Read for TunTap { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) }; + if len == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(len as usize) + } + } +} + +impl io::Write for TunTap { + fn write(&mut self, buf: &[u8]) -> io::Result { + let len = unsafe { libc::write(self.fd, buf.as_ptr() as *mut libc::c_void, buf.len()) }; + if len == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(len as usize) + } + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +/// Similar to smoltcp's `TunTapInterface` but implements [super::Device] instead of [smoltcp::phy::Device], allowing it to work with an `async` runtime. +pub struct TunTapDevice { + device: Async, + send_queue: VecDeque, +} + +impl TunTapDevice { + pub fn new(name: &str) -> io::Result { + Ok(Self { + device: Async::new(TunTap::new(name)?)?, + send_queue: VecDeque::new(), + }) + } +} + +use crate::net::device::packet_pool::PACKET_POOL_SIZE; + +use super::{DeviceCapabilities, Packet, PacketBox, PacketBoxExt, PacketBuf}; +use core::task::Waker; +use std::task::Context; + +impl super::Device for TunTapDevice { + fn is_transmit_ready(&mut self) -> bool { + true + } + + fn transmit(&mut self, pkt: PacketBuf, waker: &Option) { + // Doesn't make much sense having a queue larger than the pool size + debug_assert!(self.send_queue.len() <= PACKET_POOL_SIZE); + if self.send_queue.len() == PACKET_POOL_SIZE { + self.send_queue.pop_front(); + } + self.send_queue.push_back(pkt); + while let Some(pkt) = self.send_queue.front_mut() { + match self.device.get_mut().write(pkt) { + Ok(_) => { + self.send_queue.pop_front(); + } + Err(e) if e.kind() == io::ErrorKind::WouldBlock => { + let ready = if let Some(ref waker) = waker { + let mut cx = Context::from_waker(waker); + self.device.poll_writable(&mut cx).is_ready() + } else { + false + }; + + if !ready { + break; + } + } + Err(e) => panic!("transmit error: {:?}", e), + } + } + } + + fn receive(&mut self, waker: &Option) -> Option { + let mut pkt = PacketBox::new(Packet::new()).unwrap(); + loop { + match self.device.get_mut().read(&mut pkt[..]) { + Ok(n) => { + return Some(pkt.slice(0..n)); + } + Err(e) if e.kind() == io::ErrorKind::WouldBlock => { + let ready = if let Some(ref waker) = waker { + let mut cx = Context::from_waker(waker); + self.device.poll_readable(&mut cx).is_ready() + } else { + false + }; + if !ready { + return None; + } + } + Err(e) => panic!("read error: {:?}", e), + } + } + } + + fn capabilities(&mut self) -> DeviceCapabilities { + let mut caps = DeviceCapabilities::default(); + caps.max_transmission_unit = self.device.get_ref().mtu; + caps + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/mod.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/mod.rs new file mode 100644 index 00000000000..5246e7a6611 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/mod.rs @@ -0,0 +1,17 @@ +mod device; +mod stack; +mod tcp; +mod timer; + +pub use device::Device; +pub(crate) use stack::*; +pub use stack::{InterfaceConfiguration, StackFacade}; +pub(crate) use tcp::*; +pub use timer::{Clock, Instant}; + +// Tap devices only make sense in std +#[cfg(feature = "std")] +pub use device::TunTapDevice; + +#[cfg(feature = "std")] +pub use timer::StdClock; diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/stack.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/stack.rs new file mode 100644 index 00000000000..913306d1aff --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/stack.rs @@ -0,0 +1,355 @@ +use core::fmt::Display; +use core::future::Future; +use futures::pin_mut; +use lazy_static::lazy_static; +use ockam_core::async_trait; +use ockam_core::compat::boxed::Box; +use ockam_core::compat::collections::BTreeMap; +use ockam_core::compat::sync::Mutex; +use ockam_core::compat::task::{Context, Poll}; +use ockam_transport_core::tcp::traits::{TcpAccepter, TcpBinder, TcpStreamConnector}; +use ockam_transport_core::TransportError; +use smoltcp::socket::{Socket, TcpSocket, TcpSocketBuffer}; +use smoltcp::time::Instant; +use smoltcp::wire::{EthernetAddress, IpCidr, IpEndpoint}; +use smoltcp::Result; +use smoltcp::{ + iface::{ + Context as SmolContext, Interface, InterfaceBuilder, NeighborCache, Routes, SocketHandle, + }, + socket::TcpState, +}; +use tracing::{error, trace}; + +use super::{ + device::{Device, DeviceAdapter}, + timer::Clock, +}; +use super::{AsyncTcpSocket, AsyncTcpStream}; + +// Tap devices only make sense in std +#[cfg(feature = "std")] +pub use super::TunTapDevice; + +lazy_static! { + // The global stack that will be used by this module + static ref STACK: Mutex> = Mutex::new(None); +} + +use managed::{ManagedMap, ManagedSlice}; + +/// Configuration for the smoltcp stack. +/// +/// All the configuration will be consumed by the stack `init` and you will not be able to change it afterwards. +#[derive(Clone)] +pub struct InterfaceConfiguration +where + T: Into>, + U: Into>, +{ + eth_addr: [u8; 6], + ip_addrs: T, + routes: Option, + device: &'static Mutex, +} + +impl InterfaceConfiguration +where + T: Into>, + U: Into>, +{ + // We don't support DHCP right now so we need to set an IpAddr + /// Create a new configuration for the smoltcp stack. + /// + /// ## Parameters: + /// - `eth_addr`: the 6 octets of the ethernet addres. + /// - `ip`: Ip address that will be used by the interface. + /// - `device`: A device that implements [Device], this will be polled for packages and it will wake our waker when they become available. + pub fn new(eth_addr: [u8; 6], ip: T, device: &'static Mutex) -> Self { + Self { + eth_addr, + ip_addrs: ip, + routes: None, + device, + } + } + + /// Sets the ip routes. + pub fn set_routes(&mut self, routes: U) { + self.routes = Some(routes); + } + + fn get_routes(&mut self) -> Routes<'static> { + match self.routes.take() { + Some(routes) => routes.into(), + None => Routes::new(ManagedMap::Borrowed(&mut [])), + } + } +} + +fn create_iface(mut config: InterfaceConfiguration) -> Interface<'static, DeviceAdapter> +where + T: Into>, + U: Into>, +{ + let eth_addr = EthernetAddress(config.eth_addr); + let device = DeviceAdapter::new(config.device); + + // TODO allocation + // These allocation should be easy to remove by asking the user to provide these resources + let neighbor_cache = NeighborCache::new(BTreeMap::new()); + // TODO: If we don't alloc here and use statically allocated storage remember to update get_tcp_socket so we don't panic + let socket_storage = vec![]; + + let iface = InterfaceBuilder::new(device, socket_storage) + .hardware_addr(eth_addr.into()) + .neighbor_cache(neighbor_cache) + .routes(config.get_routes()) + .ip_addrs(config.ip_addrs) + .finalize(); + + iface +} + +struct Stack { + iface: Interface<'static, DeviceAdapter>, +} + +/// Facade into the underlying stack. +/// +/// This facade provides type safety for the stack making sure that it has been initialized before using it. +/// +/// This is used internally but if you want to [poll](StackFacade::poll) the stack manually instead of depending on it running on the background you need to use this struct. +#[derive(Clone, Debug, Copy)] +pub struct StackFacade(()); + +#[derive(Clone, Debug)] +pub(crate) struct Endpoints { + pub remote: T, + pub local: U, +} + +impl Display for Endpoints +where + T: Display, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + // For routing purposes we only care for the remote endpoint. + self.remote.fmt(f) + } +} + +#[async_trait] +impl TcpStreamConnector> for StackFacade +where + T: Into + Send + 'static, + U: Into + Send + 'static, +{ + type Stream = AsyncTcpStream; + + async fn connect( + &self, + Endpoints { remote, local }: Endpoints, + ) -> core::result::Result { + let mut socket = self.get_async_tcp_socket(); + AsyncTcpSocket::connect(&mut socket, remote, local) + .await + .map_err(TransportError::from)?; + + Ok(socket.into_stream()) + } +} + +impl StackFacade { + pub(crate) fn init_stack(config: InterfaceConfiguration) -> Self + where + T: Into>, + U: Into>, + { + if STACK.lock().unwrap().is_none() { + Stack::init(config); + } else { + panic!("The stack should never be initialized twice"); + } + + Self(()) + } + + pub(crate) fn get_async_tcp_socket(&self) -> AsyncTcpSocket { + Self::with_stack(|stack| stack.get_async_tcp_socket(*self)) + } + + pub(crate) async fn accept>( + &self, + binding_endpoint: T, + ) -> Result<(AsyncTcpStream, IpEndpoint)> { + let mut new_socket = Self::with_stack(|stack| stack.get_async_tcp_socket(*self)); + new_socket.listen(binding_endpoint).await?; + Ok(new_socket.accept().await) + } + + pub(crate) fn with_handle( + &self, + handle: SocketHandle, + f: impl FnOnce(&mut TcpSocket, &mut SmolContext) -> R, + ) -> R { + Self::with_stack(|stack| stack.with(handle, f)) + } + + /// Polls the underlying stack. + /// + /// It uses the `context` to extract a `waker` that will be signaled (either by the [Device], by a timeout or by any action taken to a socket). + /// + /// Note that you will never have to use this function or concern yourself with the [StackFacade] if you pass a [Clock] to [SmolTcpTransport::create](crate::SmolTcpTransport::create) + pub fn poll(&self, cx: &mut Context, timestamp: impl Into) { + Self::with_stack(|stack| stack.poll_iface(cx, timestamp)); + } + + pub(crate) async fn run(&self, clock: C) + where + C: Clock + Send + Sync + 'static, + { + ockam_node::spawn(async move { + futures::future::poll_fn::<(), _>(|cx| { + let timestamp = clock.now(); + Self::with_stack(|stack| { + stack.poll_iface(cx, timestamp); + }); + Poll::Pending + }) + .await; + }); + } + + fn with_stack(f: impl FnOnce(&mut Stack) -> R) -> R { + let mut stack = STACK.lock().unwrap(); + let stack = stack + .as_mut() + .expect("There should be no way to access the stack without inititializing it first"); + f(stack) + } +} + +pub struct StackTcpAccepter { + stack: StackFacade, + local_endpoint: IpEndpoint, +} + +#[async_trait] +impl TcpBinder for StackFacade +where + A: Into + Send + 'static, +{ + type Listener = StackTcpAccepter; + async fn bind(&self, addr: A) -> core::result::Result { + Ok(StackTcpAccepter { + stack: *self, + local_endpoint: addr.into(), + }) + } +} + +#[async_trait] +impl TcpAccepter for StackTcpAccepter { + type Stream = AsyncTcpStream; + type Peer = IpEndpoint; + async fn accept(&mut self) -> core::result::Result<(Self::Stream, Self::Peer), TransportError> { + self.stack + .accept(self.local_endpoint) + .await + .map_err(TransportError::from) + } +} + +impl Stack { + fn init(config: InterfaceConfiguration) + where + T: Into>, + U: Into>, + { + let iface = create_iface(config); + let mut stack = STACK.lock().unwrap(); + *stack = Some(Self { iface }); + } + + fn with( + &mut self, + handle: SocketHandle, + f: impl FnOnce(&mut TcpSocket, &mut SmolContext) -> R, + ) -> R { + let (socket, cx) = self.iface.get_socket_and_context(handle); + let res = f(socket, cx); + if let Some(ref waker) = self.iface.device().get_waker() { + waker.wake_by_ref(); + } + + res + } + + fn get_tcp_socket(&mut self) -> SocketHandle { + // Reuse closed sockets if possible. + // Note: adding a socket already iterates through all the socket handles so this is probably not a problem + let closed_socket = self.iface.sockets().find_map(|(socket_handle, socket)| { + // Note: This is only a irrefutable pattern when the only kind of socket enabled + // is tcp. Which might not be the case in a downstream crate. + #[allow(irrefutable_let_patterns)] + if let Socket::Tcp(socket) = socket { + match socket.state() { + TcpState::Closed => Some(socket_handle), + _ => None, + } + } else { + None + } + }); + + if let Some(socket_handle) = closed_socket { + socket_handle + } else { + // TODO allocation + // Normally to prevent this allocation we would have the user pass on the buffers when creating the socket but in our case + // We need to support the `accept` method (look at the sibling tcp module) that automatically creates gets a socket after a new connection. + // So we need to have some way to allocate new buffers for each new incoming connection(sans reused sockets). We could use a pool(Like we've already done for the device's tokens) + // but maybe we could create a trait for `get_new_socket_buffer` and use that so that the user can chose whatever allocation method. + let socket_rx_buff = TcpSocketBuffer::new(vec![0; 65535]); + let socket_tx_buff = TcpSocketBuffer::new(vec![0; 65535]); + + let socket = TcpSocket::new(socket_rx_buff, socket_tx_buff); + self.iface.add_socket(socket) // TODO! This can panic if we are using statically allocated socket storage, remember to change this when we allow for that!! + } + } + + fn get_async_tcp_socket(&mut self, stack_facade: StackFacade) -> AsyncTcpSocket { + let socket_handle = self.get_tcp_socket(); + AsyncTcpSocket::new(socket_handle, stack_facade) + } + + fn poll_iface(&mut self, cx: &mut Context, timestamp: impl Into) { + trace!("Polling interface"); + // Register the waker for the interface (Used to wake each time a change ocurrs in the interface) + self.iface.device_mut().register_waker(cx.waker()); + + // Poll the interface + let timestamp = timestamp.into(); + match self.iface.poll(timestamp) { + Ok(_) => {} + Err(e) => { + error!("poll error: {}", e); + cx.waker().wake_by_ref(); + } + } + + // Get recomended delay and register waker for delay + let delay = self.iface.poll_delay(timestamp); + + if let Some(delay) = delay { + let time = ockam_node::tokio::time::sleep( + ockam_node::tokio::time::Duration::from_millis(delay.millis()), + ); + pin_mut!(time); + if time.poll(cx).is_ready() { + cx.waker().wake_by_ref(); + } + } + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/tcp.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/tcp.rs new file mode 100644 index 00000000000..a36df5c76f3 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/tcp.rs @@ -0,0 +1,203 @@ +use core::pin; +use ockam_core::async_trait; +use ockam_core::compat::task::{Context, Poll}; +use ockam_transport_core::tcp::traits::io::Result; +use ockam_transport_core::tcp::traits::io::{AsyncRead, AsyncWrite}; +use ockam_transport_core::tcp::traits::IntoSplit; +use smoltcp::iface::SocketHandle; +use smoltcp::socket::TcpState; +use smoltcp::wire::IpEndpoint; + +use super::StackFacade; + +#[derive(Debug)] +pub(crate) struct AsyncTcpSocket { + socket_handle: SocketHandle, + stack: StackFacade, +} + +impl Drop for AsyncTcpSocket { + fn drop(&mut self) { + self.close(); + } +} + +use ockam_core::compat::sync::Arc; + +#[derive(Debug, Clone)] +pub struct AsyncTcpStream { + // TODO allocation + // We need shared ownership of the AsyncTcpSocket since Dropping the `AsyncTcpSocket` should close it. + // Since ockam_core still needs `alloc` we are using `Arc`. When we go to an alloc-less version we can either: + // * AsyncTcpSocket drop doesn't remove it/close it, instead the creator must make sure that it removes it after using. + // * Use heapless's Arc + inner: Arc, +} + +#[async_trait] +impl IntoSplit for AsyncTcpStream { + type ReadHalf = AsyncTcpStream; + + type WriteHalf = AsyncTcpStream; + + fn into_split(self) -> (Self::ReadHalf, Self::WriteHalf) { + (self.clone(), self.clone()) + } +} + +impl AsyncTcpSocket { + pub(crate) fn new(socket_handle: SocketHandle, stack: StackFacade) -> Self { + Self { + socket_handle, + stack, + } + } + + pub(crate) fn remote_endpoint(&self) -> IpEndpoint { + self.stack + .with_handle(self.socket_handle, |s, _| s.remote_endpoint()) + } + + fn get_state(&self) -> TcpState { + self.stack.with_handle(self.socket_handle, |s, _| s.state()) + } + + fn register_send_waker(&self, cx: &mut Context) { + self.stack + .with_handle(self.socket_handle, |s, _| s.register_recv_waker(cx.waker())); + } + + fn register_recv_waker(&self, cx: &mut Context) { + self.stack + .with_handle(self.socket_handle, |s, _| s.register_recv_waker(cx.waker())); + } + + fn close(&self) { + self.stack.with_handle(self.socket_handle, |s, _| s.close()); + } + + pub(crate) fn get_connection_status(&mut self) -> (bool, IpEndpoint) { + self.stack.with_handle(self.socket_handle, |s, _| { + (s.is_active(), s.remote_endpoint()) + }) + } + + pub(crate) async fn connect( + &mut self, + remote_endpoint: T, + local_endpoint: U, + ) -> smoltcp::Result<()> + where + T: Into, + U: Into, + { + self.stack.with_handle(self.socket_handle, |s, cx| { + s.connect(cx, remote_endpoint, local_endpoint) + })?; + + futures::future::poll_fn(|cx| match self.get_state() { + TcpState::Closed | TcpState::TimeWait => { + Poll::Ready(Err(smoltcp::Error::Unaddressable)) + } + TcpState::Listen => Poll::Ready(Err(smoltcp::Error::Illegal)), + TcpState::SynSent | TcpState::SynReceived => { + self.register_send_waker(cx); + Poll::Pending + } + _ => Poll::Ready(Ok(())), + }) + .await + } + + pub(crate) async fn listen(&mut self, local_endpoint: T) -> smoltcp::Result<()> + where + T: Into, + { + self.stack.with_handle(self.socket_handle, |socket, _| { + socket.listen(local_endpoint) + })?; + + futures::future::poll_fn(|cx| match self.get_state() { + TcpState::Closed | TcpState::TimeWait => { + Poll::Ready(Err(smoltcp::Error::Unaddressable)) + } + TcpState::Listen => Poll::Ready(Ok(())), + TcpState::SynSent | TcpState::SynReceived => { + self.register_send_waker(cx); + Poll::Pending + } + _ => Poll::Ready(Ok(())), + }) + .await + } + + pub(super) async fn accept(mut self) -> (AsyncTcpStream, IpEndpoint) { + futures::future::poll_fn(|cx| { + if self.get_connection_status().0 { + Poll::Ready(()) + } else { + self.register_recv_waker(cx); + Poll::Pending + } + }) + .await; + + let remote_endpoint = self.remote_endpoint(); + let stream = AsyncTcpStream { + inner: Arc::new(self), + }; + (stream, remote_endpoint) + } + + pub(crate) fn into_stream(self) -> AsyncTcpStream { + AsyncTcpStream { + inner: Arc::new(self), + } + } +} + +// We could implement AsyncBufRead also but with the current protocol we always know how many bytes +// we want and we can allocate that and pass to the reader. +impl AsyncRead for AsyncTcpStream { + fn poll_read( + self: pin::Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let recv_slice = self + .inner + .stack + .with_handle(self.inner.socket_handle, |s, _| s.recv_slice(buf)); + match recv_slice { + // If the buffer is empty recv_slice will always return 0 + Ok(0) if !buf.is_empty() => { + self.inner.register_recv_waker(cx); + Poll::Pending + } + Ok(n) => Poll::Ready(Ok(n)), + Err(smoltcp::Error::Finished) => Poll::Ready(Ok(0)), + res => Poll::Ready(Ok(res?)), + } + } +} + +impl AsyncWrite for AsyncTcpStream { + fn poll_write( + self: pin::Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + let send_slice = self + .inner + .stack + .with_handle(self.inner.socket_handle, |s, _| s.send_slice(buf)); + match send_slice { + Ok(0) => { + self.inner.register_send_waker(cx); + Poll::Pending + } + Ok(n) => Poll::Ready(Ok(n)), + res => Poll::Ready(Ok(res?)), + } + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/net/timer/mod.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/timer/mod.rs new file mode 100644 index 00000000000..8c1549b3523 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/net/timer/mod.rs @@ -0,0 +1,51 @@ +use smoltcp::time::Instant as SmolInstant; + +/// Type returned by the [Clock] trait. +/// +/// The instant represent elapsed time since some arbitrary starting point and this can be converted into [SmolInstant]. +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +pub struct Instant { + /// Elapsed time measured in milliseconds. + pub millis: i64, +} + +impl From for SmolInstant { + fn from(inst: Instant) -> Self { + Self::from_millis(inst.millis) + } +} + +impl From for Instant { + fn from(inst: SmolInstant) -> Self { + Self { + millis: inst.millis(), + } + } +} + +/// Monotonic clock trait. +/// +/// Used by [SmolTcpTransport](crate::SmolTcpTransport) to provide an instant that will be passed onto the Stack for polling. +/// +/// No need to implement this trait if you plan to poll the stack manually. +/// # Example +/// ``` +/// use ockam_transport_smoltcp::{Clock, StdClock}; +/// let insntant = Clock::now(&StdClock); +/// ``` +pub trait Clock { + /// Returns the elapsed time + fn now(&self) -> Instant; +} + +#[cfg(feature = "std")] +/// `std` implementation of [Clock] using [SmolInstant]. +#[derive(Clone, Copy, Debug)] +pub struct StdClock; + +#[cfg(feature = "std")] +impl Clock for StdClock { + fn now(&self) -> Instant { + SmolInstant::now().into() + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/port_provider.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/port_provider.rs new file mode 100644 index 00000000000..d19cdcd3b87 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/port_provider.rs @@ -0,0 +1,30 @@ +/// A `PortProvider` represents an strategy to get a new port. +/// +/// # Example +/// ``` +/// use ockam_transport_smoltcp::{PortProvider, ThreadLocalPortProvider}; +/// let port = ::next_port(); +/// ``` +pub trait PortProvider { + /// Gets the next available port. + // Might want to make this method take a `&self` but for now that added too much clutter and for now it's not needed. + fn next_port() -> u16; +} + +#[cfg(feature = "std")] +use rand::Rng; + +/// [PortProvider] using [rand::thread_rng]. +/// +/// It provides a random port between [4096, 65535]. Nothing ensures that there are no collisions. +#[cfg(feature = "std")] +pub struct ThreadLocalPortProvider; + +#[cfg(feature = "std")] +impl PortProvider for ThreadLocalPortProvider { + fn next_port() -> u16 { + const MIN_PORT: u16 = 4096; + const MAX_PORT: u16 = 65535; + rand::thread_rng().gen_range(MIN_PORT..=MAX_PORT) + } +} diff --git a/implementations/rust/ockam/ockam_transport_smoltcp/src/transport.rs b/implementations/rust/ockam/ockam_transport_smoltcp/src/transport.rs new file mode 100644 index 00000000000..02e0b0eb9cc --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_smoltcp/src/transport.rs @@ -0,0 +1,292 @@ +use core::marker::PhantomData; +use core::str::FromStr; +use managed::ManagedSlice; +use ockam_core::Result; +use ockam_node::Context; +use ockam_transport_core::{ + tcp::{ + router::{TcpRouter, TcpRouterHandle}, + traits::EndpointResolver, + }, + TransportError, +}; + +use smoltcp::{ + iface::Routes, + wire::{IpCidr, IpEndpoint}, +}; + +use crate::{ + net::{Endpoints, InterfaceConfiguration, StackFacade}, + Clock, PortProvider, +}; + +/// High level management interface for TCP transports using smoltcp. +/// +/// Mostly useful in `no-std` enviroments otherwise you might want to use the ockam-transport-tcp crate. +/// +/// Be aware that only one `SmolTcpTransport` can exist per node, as it +/// registers itself as a router for the `TCP` address type. Multiple +/// calls to [`SmolTcpTransport::create`](crate::SmolTcpTransport::create) +/// will fail. +/// +/// To listen for incoming connections use +/// [`tcp.listen()`](crate::SmolTcpTransport::listen). +/// +/// To register additional connections on an already initialised +/// `TcpTransport`, use [`tcp.connect()`](crate::SmolTcpTransport::connect). +/// This step is optional because the underlying TcpRouter is capable of lazily +/// establishing a connection upon arrival of an initial message. +/// +/// # Examples +/// +/// ## Explicitly connect to an endpoint. +/// +/// ```rust +/// use ockam_transport_smoltcp::{SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; +/// use ockam_transport_smoltcp::InterfaceConfiguration; +/// # use ockam_node::Context; +/// # use ockam_core::Result; +/// # use ockam_core::compat::sync::Mutex; +/// # use ockam_core::compat::collections::BTreeMap; +/// # use smoltcp::iface::Routes; +/// # use smoltcp::wire::{IpCidr, IpAddress, Ipv4Address}; +/// # use std::str::FromStr; +/// # use lazy_static::lazy_static; +/// +/// lazy_static! { +/// static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); +/// } +/// +/// # async fn test(ctx: Context) -> Result<()> { +/// let bind_ip_addr = "192.168.69.1:10222"; +/// let default_gateway = "192.168.69.100"; +/// let mut routes = Routes::new(BTreeMap::new()); +/// routes +/// .add_default_ipv4_route(Ipv4Address::from_str(&default_gateway).unwrap()) +/// .unwrap(); +/// let mut configuration = InterfaceConfiguration::<_, Routes<'static>>::new( +/// [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], +/// [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], +/// &*DEVICE, +/// ); +/// configuration.set_routes(routes); +/// +/// let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)).await?; +/// +/// tcp.connect("192.168.69.100:10222").await?; +/// # Ok(()) } +/// ``` +/// +/// ## The same `TcpTransport` can also bind to multiple ports. +/// +/// ```rust +/// use ockam_transport_smoltcp::{SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; +/// use ockam_transport_smoltcp::InterfaceConfiguration; +/// # use ockam_node::Context; +/// # use ockam_core::Result; +/// # use ockam_core::compat::sync::Mutex; +/// # use ockam_core::compat::collections::BTreeMap; +/// # use smoltcp::iface::Routes; +/// # use smoltcp::wire::{IpCidr, IpAddress, Ipv4Address}; +/// # use std::str::FromStr; +/// # use lazy_static::lazy_static; +/// +/// lazy_static! { +/// static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); +/// } +/// +/// # async fn test(ctx: Context) -> Result<()> { +/// +/// let bind_ip_addr = "192.168.69.1:10222"; +/// let mut configuration = InterfaceConfiguration::<_, Routes<'static>>::new( +/// [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], +/// [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], +/// &*DEVICE, +/// ); +/// +/// let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)).await?; +/// +/// tcp.listen(10222).await?; +/// tcp.listen(10333).await?; +/// # Ok(()) } +/// ``` +pub struct SmolTcpTransport

{ + router_handle: TcpRouterHandle>, + stack: StackFacade, +} + +impl

SmolTcpTransport

+where + P: PortProvider + Send + Sync + 'static, +{ + /// Create a new TCP transport and router for the current node + /// + /// If you don't provide a [Clock] you will need to manually [poll](StackFacade::poll) the stack. However, if the `Clock` is provided you don't need to poll the stack(you can still do it but there's no gain in doing it). + /// + /// To get the stack to poll use [SmolTcpTransport::get_stack]. + /// ```rust + /// use ockam_transport_smoltcp::{SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; + /// use ockam_transport_smoltcp::InterfaceConfiguration; + /// # use ockam_node::Context; + /// # use ockam_core::Result; + /// # use ockam_core::compat::sync::Mutex; + /// # use smoltcp::iface::Routes; + /// # use smoltcp::wire::IpCidr; + /// # use smoltcp::wire::IpAddress; + /// # use std::str::FromStr; + /// # use lazy_static::lazy_static; + /// # async fn test(ctx: Context) -> Result<()> { + /// lazy_static! { + /// static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); + /// } + /// + /// let bind_ip_addr = "192.168.69.1:10222"; + /// let configuration = InterfaceConfiguration::<_, Routes<'static>>::new( + /// [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + /// [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], + /// &*DEVICE, + /// ); + /// + /// let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)).await?; + /// # Ok(()) } + /// ``` + pub async fn create( + ctx: &Context, + config: InterfaceConfiguration, + clock: Option, + ) -> Result + where + C: Clock + Send + Sync + 'static, + T: Into>, + U: Into>, + P: PortProvider + Send + 'static, + { + let stack = StackFacade::init_stack(config); + if let Some(clock) = clock { + stack.run(clock).await; + } + let router_handle = + TcpRouter::<_, _, SmolTcpEndpointResolver

>::register(ctx, stack).await?; + Ok(Self { + router_handle, + stack, + }) + } + + /// Start listening to incoming connections on an existing transport + /// + /// ## Parameeters + /// - `bind_port`: the port the interface will be listening at. + /// + /// # Example + /// + /// ```rust + /// use ockam_transport_smoltcp::{SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; + /// use ockam_transport_smoltcp::InterfaceConfiguration; + /// # use ockam_node::Context; + /// # use ockam_core::Result; + /// # use ockam_core::compat::sync::Mutex; + /// # use ockam_core::compat::collections::BTreeMap; + /// # use smoltcp::iface::Routes; + /// # use smoltcp::wire::{IpCidr, IpAddress, Ipv4Address}; + /// # use std::str::FromStr; + /// # use lazy_static::lazy_static; + /// + /// lazy_static! { + /// static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); + /// } + /// + /// # async fn test(ctx: Context) -> Result<()> { + /// + /// let bind_ip_addr = "192.168.69.1:10222"; + /// let mut configuration = InterfaceConfiguration::<_, Routes<'static>>::new( + /// [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + /// [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], + /// &*DEVICE, + /// ); + /// + /// let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)).await?; + /// + /// tcp.listen(10222).await?; + /// # Ok(()) } + /// ``` + pub async fn listen(&self, bind_port: u16) -> Result<()> { + self.router_handle.bind(bind_port, self.stack).await?; + Ok(()) + } + + /// Manually establish an outgoing TCP connection on an existing transport. + /// This step is optional because the underlying TcpRouter is capable of lazily establishing + /// a connection upon arrival of the initial message. + /// + /// ```rust + /// use ockam_transport_smoltcp::{SmolTcpTransport, TunTapDevice, ThreadLocalPortProvider, StdClock}; + /// use ockam_transport_smoltcp::InterfaceConfiguration; + /// # use ockam_node::Context; + /// # use ockam_core::Result; + /// # use ockam_core::compat::sync::Mutex; + /// # use ockam_core::compat::collections::BTreeMap; + /// # use smoltcp::iface::Routes; + /// # use smoltcp::wire::{IpCidr, IpAddress, Ipv4Address}; + /// # use std::str::FromStr; + /// # use lazy_static::lazy_static; + /// + /// lazy_static! { + /// static ref DEVICE: Mutex = Mutex::new(TunTapDevice::new("tap0").unwrap()); + /// } + /// + /// # async fn test(ctx: Context) -> Result<()> { + /// let bind_ip_addr = "192.168.69.1:10222"; + /// let default_gateway = "192.168.69.100"; + /// let mut routes = Routes::new(BTreeMap::new()); + /// routes + /// .add_default_ipv4_route(Ipv4Address::from_str(&default_gateway).unwrap()) + /// .unwrap(); + /// let mut configuration = InterfaceConfiguration::<_, Routes<'static>>::new( + /// [0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + /// [IpCidr::new(IpAddress::from_str(bind_ip_addr).unwrap(), 24)], + /// &*DEVICE, + /// ); + /// configuration.set_routes(routes); + /// + /// let tcp = SmolTcpTransport::::create(&ctx, configuration, Some(StdClock)).await?; + /// + /// tcp.connect("192.168.69.100:10222").await?; + /// # Ok(()) } + /// ``` + pub async fn connect>(&self, peer: S) -> Result<()> { + self.router_handle.connect(peer, self.stack).await + } + + /// Returns the `StackFacade` corresponding to the smoltcp stack. + /// + /// This is only useful if you will [poll](StackFacade::poll) it manually instead of depending on the polling mechanism in this crate. + /// + /// If you want to poll it manually make sure to *not* provide a `Clock` to [SmolTcpTransport::create] + pub fn get_stack(&self) -> StackFacade { + self.stack.clone() + } +} + +struct SmolTcpEndpointResolver(PhantomData); + +impl EndpointResolver for SmolTcpEndpointResolver +where + T: PortProvider, +{ + type Hostnames = &'static [&'static str]; + + type Peer = Endpoints; + + fn resolve_endpoint(peer: &str) -> Result<(Self::Peer, Self::Hostnames), ockam_core::Error> { + let empty: &'static [&'static str] = &[]; + Ok(( + Endpoints { + remote: IpEndpoint::from_str(peer).map_err(|_| TransportError::InvalidAddress)?, + local: T::next_port().into(), + }, + empty, + )) + } +} diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/handle.rs b/implementations/rust/ockam/ockam_transport_tcp/src/handle.rs new file mode 100644 index 00000000000..0402d89fa20 --- /dev/null +++ b/implementations/rust/ockam/ockam_transport_tcp/src/handle.rs @@ -0,0 +1,115 @@ +use crate::{parse_socket_addr, TcpInletListenProcessor, TcpPortalWorker}; +use ockam_core::compat::net::SocketAddr; +use ockam_core::{async_trait, Address, AsyncTryClone, Result, Route}; +use ockam_node::Context; +use ockam_transport_core::tcp::router::TcpRouterHandle as BaseHandler; +use ockam_transport_core::tcp::traits::{EndpointResolver, TokioTcpBinder, TokioTcpConnector}; +use ockam_transport_core::TransportError; +use std::net::ToSocketAddrs; + +pub(crate) struct TcpRouterHandle(BaseHandler); + +#[async_trait] +impl AsyncTryClone for TcpRouterHandle { + async fn async_try_clone(&self) -> Result { + Ok(Self(self.0.async_try_clone().await?)) + } +} + +impl From> for TcpRouterHandle { + fn from(base: BaseHandler) -> Self { + Self(base) + } +} + +impl From for BaseHandler { + fn from(handler: TcpRouterHandle) -> Self { + handler.0 + } +} + +pub(crate) struct PeerResolve; + +impl EndpointResolver for PeerResolve { + type Hostnames = Vec; + + type Peer = SocketAddr; + + fn resolve_endpoint(peer: &str) -> Result<(Self::Peer, Self::Hostnames), ockam_core::Error> { + let peer_str: String = peer.into(); + let peer_addr; + let hostnames; + + // Try to parse as SocketAddr + if let Ok(p) = parse_socket_addr(peer_str.clone()) { + peer_addr = p; + hostnames = vec![]; + } + // Try to resolve hostname + else if let Ok(mut iter) = peer_str.to_socket_addrs() { + // FIXME: We only take ipv4 for now + if let Some(p) = iter.find(|x| x.is_ipv4()) { + peer_addr = p; + } else { + return Err(TransportError::InvalidAddress.into()); + } + + hostnames = vec![peer_str]; + } else { + return Err(TransportError::InvalidAddress.into()); + } + + Ok((peer_addr, hostnames)) + } +} + +impl TcpRouterHandle { + pub(crate) async fn connect(&self, peer: impl AsRef) -> Result<()> { + self.0.connect(peer, TokioTcpConnector).await + } + + pub(crate) async fn bind(&self, bind_addr: SocketAddr) -> Result<()> { + self.0.bind(bind_addr, TokioTcpBinder).await + } + + pub(crate) fn ctx(&self) -> &Context { + self.0.ctx() + } + /// Bind an incoming portal inlet connection listener for this router + pub async fn bind_inlet( + &self, + outlet_listener_route: impl Into, + addr: impl Into, + ) -> Result

{ + let socket_addr = addr.into(); + let addr = + TcpInletListenProcessor::start(self.0.ctx(), outlet_listener_route.into(), socket_addr) + .await?; + + Ok(addr) + } + + pub async fn stop_inlet(&self, addr: impl Into
) -> Result<()> { + self.0.ctx().stop_processor(addr).await?; + + Ok(()) + } + + /// Establish an outgoing TCP connection for Portal Outlet + pub async fn connect_outlet( + &self, + peer: impl AsRef, + pong_route: Route, + ) -> Result
{ + let (peer_addr, _) = PeerResolve::resolve_endpoint(peer.as_ref())?; + + let address = TcpPortalWorker::new_outlet(self.0.ctx(), peer_addr, pong_route).await?; + + Ok(address) + } + + pub async fn stop_outlet(&self, addr: impl Into
) -> Result<()> { + self.0.ctx().stop_worker(addr).await?; + Ok(()) + } +} diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/lib.rs b/implementations/rust/ockam/ockam_transport_tcp/src/lib.rs index 38d5a516bf5..afb20145446 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/lib.rs +++ b/implementations/rust/ockam/ockam_transport_tcp/src/lib.rs @@ -26,26 +26,19 @@ extern crate core; extern crate alloc; mod portal; -mod router; -mod workers; pub(crate) use portal::*; -pub(crate) use router::*; -pub(crate) use workers::*; +mod handle; mod transport; +pub use ockam_transport_core::TCP; pub use transport::*; use ockam_core::compat::net::SocketAddr; use ockam_core::Result; use ockam_transport_core::TransportError; -/// TCP address type constant -pub const TCP: u8 = 1; - -pub(crate) const CLUSTER_NAME: &str = "_internals.transport.tcp"; - fn parse_socket_addr>(s: S) -> Result { Ok(s.as_ref() .parse() diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/portal/outlet_listener.rs b/implementations/rust/ockam/ockam_transport_tcp/src/portal/outlet_listener.rs index ba0c835af7a..dc2e91ee2f4 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/portal/outlet_listener.rs +++ b/implementations/rust/ockam/ockam_transport_tcp/src/portal/outlet_listener.rs @@ -1,4 +1,5 @@ -use crate::{PortalMessage, TcpRouterHandle}; +use crate::handle::TcpRouterHandle; +use crate::PortalMessage; use ockam_core::{async_trait, AsyncTryClone}; use ockam_core::{Address, Result, Routed, Worker}; use ockam_node::Context; diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/router/handle.rs b/implementations/rust/ockam/ockam_transport_tcp/src/router/handle.rs deleted file mode 100644 index 284022602b3..00000000000 --- a/implementations/rust/ockam/ockam_transport_tcp/src/router/handle.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::{ - parse_socket_addr, TcpInletListenProcessor, TcpListenProcessor, TcpPortalWorker, TcpSendWorker, - WorkerPair, TCP, -}; -use ockam_core::compat::net::{SocketAddr, ToSocketAddrs}; -use ockam_core::{async_trait, compat::boxed::Box}; -use ockam_core::{Address, AsyncTryClone, Result, Route, RouterMessage}; -use ockam_node::Context; -use ockam_transport_core::TransportError; - -/// A handle to connect to a TcpRouter -/// -/// Dropping this handle is harmless. -pub(crate) struct TcpRouterHandle { - ctx: Context, - addr: Address, -} - -impl TcpRouterHandle { - pub fn ctx(&self) -> &Context { - &self.ctx - } -} - -#[async_trait] -impl AsyncTryClone for TcpRouterHandle { - async fn async_try_clone(&self) -> Result { - let child_ctx = self.ctx.new_context(Address::random(0)).await?; - Ok(Self::new(child_ctx, self.addr.clone())) - } -} - -impl TcpRouterHandle { - pub(crate) fn new(ctx: Context, addr: Address) -> Self { - TcpRouterHandle { ctx, addr } - } -} - -impl TcpRouterHandle { - /// Register a new connection worker with this router - pub async fn register(&self, pair: &WorkerPair) -> Result<()> { - let tcp_address: Address = format!("{}#{}", TCP, pair.peer()).into(); - let mut accepts = vec![tcp_address]; - accepts.extend( - pair.hostnames() - .iter() - .map(|x| Address::from_string(format!("{}#{}", TCP, x))), - ); - let self_addr = pair.tx_addr(); - - self.ctx - .send( - self.addr.clone(), - RouterMessage::Register { accepts, self_addr }, - ) - .await - } - - /// Bind an incoming connection listener for this router - pub async fn bind(&self, addr: impl Into) -> Result<()> { - let socket_addr = addr.into(); - TcpListenProcessor::start(&self.ctx, self.async_try_clone().await?, socket_addr).await - } - - /// Bind an incoming portal inlet connection listener for this router - pub async fn bind_inlet( - &self, - outlet_listener_route: impl Into, - addr: impl Into, - ) -> Result
{ - let socket_addr = addr.into(); - let addr = - TcpInletListenProcessor::start(&self.ctx, outlet_listener_route.into(), socket_addr) - .await?; - - Ok(addr) - } - - pub async fn stop_inlet(&self, addr: impl Into
) -> Result<()> { - self.ctx.stop_processor(addr).await?; - - Ok(()) - } - - pub(crate) fn resolve_peer(peer: impl Into) -> Result<(SocketAddr, Vec)> { - let peer_str = peer.into(); - let peer_addr; - let hostnames; - - // Try to parse as SocketAddr - if let Ok(p) = parse_socket_addr(peer_str.clone()) { - peer_addr = p; - hostnames = vec![]; - } - // Try to resolve hostname - else if let Ok(mut iter) = peer_str.to_socket_addrs() { - // FIXME: We only take ipv4 for now - if let Some(p) = iter.find(|x| x.is_ipv4()) { - peer_addr = p; - } else { - return Err(TransportError::InvalidAddress.into()); - } - - hostnames = vec![peer_str]; - } else { - return Err(TransportError::InvalidAddress.into()); - } - - Ok((peer_addr, hostnames)) - } - - /// Establish an outgoing TCP connection on an existing transport - pub async fn connect>(&self, peer: S) -> Result<()> { - let (peer_addr, hostnames) = Self::resolve_peer(peer.as_ref())?; - - let pair = TcpSendWorker::start_pair(&self.ctx, None, peer_addr, hostnames).await?; - self.register(&pair).await?; - - Ok(()) - } - - /// Establish an outgoing TCP connection for Portal Outlet - pub async fn connect_outlet( - &self, - peer: impl Into, - pong_route: Route, - ) -> Result
{ - let (peer_addr, _) = Self::resolve_peer(peer)?; - - let address = TcpPortalWorker::new_outlet(&self.ctx, peer_addr, pong_route).await?; - - Ok(address) - } - - pub async fn stop_outlet(&self, addr: impl Into
) -> Result<()> { - self.ctx.stop_worker(addr).await?; - Ok(()) - } -} diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/transport.rs b/implementations/rust/ockam/ockam_transport_tcp/src/transport.rs index 82fdc906f22..53730e0904e 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/transport.rs +++ b/implementations/rust/ockam/ockam_transport_tcp/src/transport.rs @@ -1,7 +1,14 @@ -use crate::{parse_socket_addr, TcpOutletListenWorker, TcpRouter, TcpRouterHandle}; +use std::net::SocketAddr; + +use crate::handle::{PeerResolve, TcpRouterHandle}; +use crate::{parse_socket_addr, TcpOutletListenWorker}; use ockam_core::compat::boxed::Box; use ockam_core::{Address, AsyncTryClone, Result, Route}; use ockam_node::Context; +use ockam_transport_core::tcp::traits::TokioTcpConnector; + +type TcpRouter = + ockam_transport_core::tcp::router::TcpRouter; /// High level management interface for TCP transports /// @@ -58,10 +65,10 @@ impl TcpTransport { /// # Ok(()) } /// ``` pub async fn create(ctx: &Context) -> Result { - let router = TcpRouter::register(ctx).await?; + let router = TcpRouter::register(ctx, TokioTcpConnector).await?; Ok(Self { - router_handle: router, + router_handle: router.into(), }) } @@ -106,7 +113,8 @@ impl TcpTransport { /// Pair of corresponding Inlet and Outlet is called Portal. /// /// ```rust - /// use ockam_transport_tcp::{TcpTransport, TCP}; + /// use ockam_transport_tcp::TcpTransport; + /// use ockam_transport_core::TCP; /// # use ockam_node::Context; /// # use ockam_core::{Result, route}; /// # async fn test(ctx: Context) -> Result<()> { @@ -135,7 +143,8 @@ impl TcpTransport { /// Stop inlet at addr /// /// ```rust - /// use ockam_transport_tcp::{TcpTransport, TCP}; + /// use ockam_transport_tcp::TcpTransport; + /// use ockam_transport_core::TCP; /// # use ockam_node::Context; /// # use ockam_core::{Result, route}; /// # async fn test(ctx: Context) -> Result<()> { diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/workers/listener.rs b/implementations/rust/ockam/ockam_transport_tcp/src/workers/listener.rs deleted file mode 100644 index e084ac90e08..00000000000 --- a/implementations/rust/ockam/ockam_transport_tcp/src/workers/listener.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::{TcpRouterHandle, TcpSendWorker}; -use ockam_core::async_trait; -use ockam_core::{Address, Processor, Result}; -use ockam_node::Context; -use ockam_transport_core::TransportError; -use std::net::SocketAddr; -use tokio::net::TcpListener; -use tracing::{debug, trace}; - -pub(crate) struct TcpListenProcessor { - inner: TcpListener, - router_handle: TcpRouterHandle, -} - -impl TcpListenProcessor { - pub(crate) async fn start( - ctx: &Context, - router_handle: TcpRouterHandle, - addr: SocketAddr, - ) -> Result<()> { - let waddr = Address::random(0); - - debug!("Binding TcpListener to {}", addr); - let inner = TcpListener::bind(addr) - .await - .map_err(TransportError::from)?; - let worker = Self { - inner, - router_handle, - }; - - ctx.start_processor(waddr, worker).await?; - Ok(()) - } -} - -#[async_trait] -impl Processor for TcpListenProcessor { - type Context = Context; - - async fn initialize(&mut self, ctx: &mut Context) -> Result<()> { - ctx.set_cluster(crate::CLUSTER_NAME).await - } - - async fn process(&mut self, ctx: &mut Self::Context) -> Result { - trace!("Waiting for incoming TCP connection..."); - - // Wait for an incoming connection - let (stream, peer) = self.inner.accept().await.map_err(TransportError::from)?; - - // And spawn a connection worker for it - let pair = TcpSendWorker::start_pair(ctx, Some(stream), peer, vec![]).await?; - - // Register the connection with the local TcpRouter - self.router_handle.register(&pair).await?; - - Ok(true) - } -} diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/workers/mod.rs b/implementations/rust/ockam/ockam_transport_tcp/src/workers/mod.rs deleted file mode 100644 index 340c7fa97e7..00000000000 --- a/implementations/rust/ockam/ockam_transport_tcp/src/workers/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod listener; -mod receiver; -mod sender; - -pub(crate) use listener::*; -pub(crate) use receiver::*; -pub(crate) use sender::*; diff --git a/implementations/rust/ockam/ockam_transport_tcp/tests/send_receive.rs b/implementations/rust/ockam/ockam_transport_tcp/tests/send_receive.rs index 0a3446e13b1..e7284547448 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/tests/send_receive.rs +++ b/implementations/rust/ockam/ockam_transport_tcp/tests/send_receive.rs @@ -4,7 +4,8 @@ use ockam_core::{route, Address, Result, Routed, Worker}; use ockam_node::Context; use rand::Rng; -use ockam_transport_tcp::{TcpTransport, TCP}; +use ockam_transport_core::TCP; +use ockam_transport_tcp::TcpTransport; #[ockam_macros::test] async fn send_receive(ctx: &mut Context) -> Result<()> {