From 39bb92ac31c1c6fec8cd96e0d003b38bfd536e10 Mon Sep 17 00:00:00 2001 From: giangndm <45644921+giangndm@users.noreply.github.com> Date: Wed, 10 Jan 2024 01:24:23 +0700 Subject: [PATCH] feat: atm0s-sdn (#2) --- Cargo.lock | 1089 +++++++++++++++--- Cargo.toml | 1 + README.md | 113 +- crates/agent/node_local.sh | 5 + crates/agent/src/main.rs | 101 +- crates/protocol/src/cluster.rs | 39 + crates/protocol/src/lib.rs | 1 + crates/relayer/Cargo.toml | 1 + crates/relayer/run_local_node1.sh | 7 + crates/relayer/run_local_node2.sh | 8 + crates/relayer/src/agent_listener/quic.rs | 20 +- crates/relayer/src/agent_listener/tcp.rs | 28 +- crates/relayer/src/agent_worker.rs | 20 +- crates/relayer/src/main.rs | 147 ++- crates/relayer/src/proxy_listener.rs | 16 +- crates/relayer/src/proxy_listener/cluster.rs | 164 +++ crates/relayer/src/proxy_listener/http.rs | 36 +- crates/relayer/src/tunnel.rs | 130 +++ crates/relayer/src/utils.rs | 12 + rust-toolchain | 1 - 20 files changed, 1647 insertions(+), 292 deletions(-) create mode 100644 crates/agent/node_local.sh create mode 100644 crates/protocol/src/cluster.rs create mode 100644 crates/relayer/run_local_node1.sh create mode 100644 crates/relayer/run_local_node2.sh create mode 100644 crates/relayer/src/proxy_listener/cluster.rs create mode 100644 crates/relayer/src/tunnel.rs create mode 100644 crates/relayer/src/utils.rs delete mode 100644 rust-toolchain diff --git a/Cargo.lock b/Cargo.lock index d4bf820..3b15603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "agent" version = "0.1.0" @@ -35,9 +70,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -54,6 +89,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstream" version = "0.6.5" @@ -108,6 +149,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "async-attributes" version = "1.1.2" @@ -118,6 +165,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "async-bincode" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21849a990d47109757e820904d7c0b569a8013f6595bf14d911884634d58795f" +dependencies = [ + "bincode", + "byteorder", + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "serde", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -136,7 +198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener 4.0.0", + "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -152,7 +214,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "slab", ] @@ -167,7 +229,7 @@ dependencies = [ "async-io 2.2.2", "async-lock 3.2.0", "blocking", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "once_cell", "tokio", ] @@ -202,7 +264,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "parking", "polling 3.3.1", "rustix 0.38.28", @@ -226,11 +288,21 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] +[[package]] +name = "async-notify" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8356f653934a654817bceada97a857ef8d68ab8992753d23ed8e8ccd5fc8fa31" +dependencies = [ + "futures-channel", + "futures-util", +] + [[package]] name = "async-process" version = "1.8.1" @@ -296,19 +368,294 @@ dependencies = [ [[package]] name = "async-task" -version = "4.5.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", +] + +[[package]] +name = "atm0s-sdn" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b7f21569f8c8f9dd5f5844fedbe6fc66bbbd210c232cde98c215df3cc590dd" +dependencies = [ + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-key-value", + "atm0s-sdn-layers-spread-router", + "atm0s-sdn-layers-spread-router-sync", + "atm0s-sdn-manual-discovery", + "atm0s-sdn-network", + "atm0s-sdn-node-alias", + "atm0s-sdn-pub-sub", + "atm0s-sdn-router", + "atm0s-sdn-rpc", + "atm0s-sdn-transport-compose", + "atm0s-sdn-transport-tcp", + "atm0s-sdn-transport-udp", + "atm0s-sdn-utils", + "atm0s-sdn-virtual-socket", + "futures-util", + "paste", + "thiserror", +] + +[[package]] +name = "atm0s-sdn-identity" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e991909d52b8ee19ad314e6b57042970b9c5d2147ea493a60b23ae20368cda" +dependencies = [ + "multiaddr", + "rand", + "serde", +] + +[[package]] +name = "atm0s-sdn-key-value" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266942ffdb64bc5e2827b7408c8bfe66dc41b56381c1e2b86013997c2c7a51ec" +dependencies = [ + "async-std", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "log", + "mockall", + "parking_lot", + "serde", + "small-map", + "thiserror", +] + +[[package]] +name = "atm0s-sdn-layers-spread-router" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168734a4a61849cd843a4f8cd27f7248318721ed4e10d53b10b80536c260ddf" +dependencies = [ + "atm0s-sdn-identity", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "log", + "parking_lot", + "serde", +] + +[[package]] +name = "atm0s-sdn-layers-spread-router-sync" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3eaa384d32b351f673b9320433a9c66691d6f816521d690bff00bb0377998" +dependencies = [ + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-layers-spread-router", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "bincode", + "log", + "serde", + "thiserror", +] + +[[package]] +name = "atm0s-sdn-manual-discovery" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3190a1e821b7449a2b4c03f0185d8bf2a2fb527262cfb556c9c5703376c4863" +dependencies = [ + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-key-value", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "log", + "parking_lot", + "serde", + "thiserror", +] + +[[package]] +name = "atm0s-sdn-network" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2032f77c22aec4cd33cf2b600ada66190edd350a3e46fa7031be96c68dfec0" +dependencies = [ + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "bincode", + "bytes", + "convert-enum", + "futures", + "log", + "parking_lot", + "serde", + "sha1", + "thiserror", +] + +[[package]] +name = "atm0s-sdn-node-alias" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a913834bf7275d9ed6fe4f05453233dc5068c4b1dc9455195ab617310ceb6de9" +dependencies = [ + "async-std", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-pub-sub", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "bincode", + "bytes", + "log", + "parking_lot", + "serde", +] + +[[package]] +name = "atm0s-sdn-pub-sub" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82900821dd3e1a71dcfc6c833c31b2cc4237689dce03001a096929aa966d6cc0" +dependencies = [ + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-key-value", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "bytes", + "log", + "parking_lot", + "serde", +] + +[[package]] +name = "atm0s-sdn-router" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d580980e58dad9642155f3f7004174b606d6b3552d18a08ed7ad27abf6e9dbff" +dependencies = [ + "atm0s-sdn-identity", +] + +[[package]] +name = "atm0s-sdn-rpc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "971b129bb4d4e116ea93dd58b9ba55628fc2475c3a344fc22b0324d413935c59" +dependencies = [ + "async-std", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "bincode", + "log", + "parking_lot", + "serde", +] + +[[package]] +name = "atm0s-sdn-transport-compose" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ad123e94796f04b6ecec127057cafc867dc108717c05decf8e556859779999" + +[[package]] +name = "atm0s-sdn-transport-tcp" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13e53e3f432d9c73fa4de04d691dcef7ab9cb1d643d8fd9f25f5b8f36ca6b27" +dependencies = [ + "async-bincode", + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-utils", + "bincode", + "futures-util", + "local-ip-address", + "log", + "parking_lot", + "serde", + "snow", +] + +[[package]] +name = "atm0s-sdn-transport-udp" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736ce6cbd9aed3fcf9f7381228693c1a0898c46c7ddc1dda71e573dfe480d1f5" +dependencies = [ + "async-notify", + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-utils", + "bincode", + "futures-util", + "local-ip-address", + "log", + "parking_lot", + "serde", + "snow", + "socket2 0.5.5", +] + +[[package]] +name = "atm0s-sdn-utils" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e648fecc372185b13c6da558d7675e90d6326229ed5af53ac4d4ed65685b5b0" +dependencies = [ + "async-notify", + "async-std", + "async-trait", + "log", + "rand", +] + +[[package]] +name = "atm0s-sdn-virtual-socket" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2bb7aca08fa99a3c89cec606a4e5b2a327d1d5849d7aed964be0f55ea1ba6f" +dependencies = [ + "async-std", + "async-trait", + "atm0s-sdn-identity", + "atm0s-sdn-network", + "atm0s-sdn-router", + "atm0s-sdn-utils", + "futures", + "log", + "parking_lot", + "quinn", + "quinn-plaintext", ] [[package]] @@ -338,11 +685,17 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base64" -version = "0.21.5" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" [[package]] name = "base64ct" @@ -371,6 +724,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -391,17 +753,32 @@ dependencies = [ "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "piper", "tracing", ] +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -423,11 +800,46 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clap" -version = "4.4.11" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" dependencies = [ "clap_builder", "clap_derive", @@ -435,9 +847,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" dependencies = [ "anstream", "anstyle", @@ -454,7 +866,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -484,6 +896,16 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "convert-enum" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79ed4c334ab0e41c547309fd0d5e5cc84e29b65a22e88a6a8516abbbe3266de6" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -500,46 +922,48 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.16" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", ] [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -548,9 +972,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "4.1.1" @@ -576,7 +1010,33 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", +] + +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "data-encoding-macro" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +dependencies = [ + "data-encoding", + "syn 1.0.109", ] [[package]] @@ -592,9 +1052,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -607,8 +1067,15 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "ed25519" version = "2.2.3" @@ -691,9 +1158,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -706,7 +1173,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "pin-project-lite", ] @@ -746,11 +1213,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -763,9 +1236,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -773,15 +1246,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -790,9 +1263,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -811,9 +1284,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -824,32 +1297,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -875,15 +1348,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.28.1" @@ -941,6 +1424,9 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "allocator-api2", +] [[package]] name = "headers" @@ -984,6 +1470,24 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.11" @@ -1020,9 +1524,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1035,13 +1539,23 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.5", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1062,6 +1576,15 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -1082,6 +1605,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -1114,9 +1646,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libp2p-identity" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0" +dependencies = [ + "bs58", + "hkdf", + "multihash", + "quick-protobuf", + "sha2", + "thiserror", + "tracing", +] [[package]] name = "linux-raw-sys" @@ -1130,6 +1677,18 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "local-ip-address" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66357e687a569abca487dc399a9c9ac19beb3f13991ed49f00c144e02cbd42ab" +dependencies = [ + "libc", + "neli", + "thiserror", + "windows-sys 0.48.0", +] + [[package]] name = "lock_api" version = "0.4.11" @@ -1151,9 +1710,9 @@ dependencies = [ [[package]] name = "mach2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -1169,18 +1728,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "metrics" @@ -1212,13 +1762,13 @@ dependencies = [ [[package]] name = "metrics-macros" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" +checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -1298,6 +1848,98 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "multiaddr" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b852bc02a2da5feed68cd14fa50d0774b92790a5bdbfa932a813926c8472070" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity", + "multibase", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +dependencies = [ + "core2", + "unsigned-varint", +] + +[[package]] +name = "neli" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4" +dependencies = [ + "either", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -1405,9 +2047,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -1418,6 +2060,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl-probe" version = "0.1.5" @@ -1468,6 +2116,12 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "pem" version = "3.0.3" @@ -1548,7 +2202,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -1586,9 +2240,9 @@ dependencies = [ [[package]] name = "platforms" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "poem" @@ -1634,7 +2288,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -1667,6 +2321,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.6.0" @@ -1685,6 +2362,33 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "predicates" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dfc28575c2e3f19cb3c73b93af36460ae898d426eba6fc15b9bd2a5220758a0" +dependencies = [ + "anstyle", + "itertools", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "proc-macro-crate" version = "2.0.1" @@ -1697,9 +2401,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -1751,6 +2455,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + [[package]] name = "quinn" version = "0.10.2" @@ -1771,6 +2484,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "quinn-plaintext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb0e784540a62e207fafa749f17a80ea1c67a59b9d5b30c9083a97bcc42d6eea" +dependencies = [ + "bytes", + "quinn-proto", + "seahash", + "tracing", +] + [[package]] name = "quinn-proto" version = "0.10.6" @@ -1804,9 +2529,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1951,6 +2676,7 @@ version = "0.1.0" dependencies = [ "async-std", "async-trait", + "atm0s-sdn", "clap", "futures", "httparse", @@ -2007,9 +2733,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.1.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810294a8a4a0853d4118e3b94bb079905f2107c7fe979d8f0faae98765eb6378" +checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -2018,22 +2744,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.1.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc144a1273124a67b8c1d7cd19f5695d1878b31569c0512f6086f0f4676604e" +checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.41", + "syn 2.0.48", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.1.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ccd4875431253d6bb54b804bcff4369cbde9bae33defde25fdf6c2ef91d40" +checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" dependencies = [ "sha2", "walkdir", @@ -2161,11 +2887,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2184,6 +2910,12 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sealed" version = "0.5.0" @@ -2193,7 +2925,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -2221,35 +2953,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -2338,12 +3070,39 @@ dependencies = [ "autocfg", ] +[[package]] +name = "small-map" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6bc8704b966e50b4fc057788d91533d3296594d4f68701da95f2c2289c808e" +dependencies = [ + "ahash", + "hashbrown 0.14.3", + "rustc-hash", +] + [[package]] name = "smallvec" version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +[[package]] +name = "snow" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58021967fd0a5eeeb23b08df6cc244a4d4a5b4aec1d27c9e02fad1a58b4cd74e" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek", + "rand_core", + "rustc_version", + "sha2", + "subtle", +] + [[package]] name = "socket2" version = "0.4.10" @@ -2417,9 +3176,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -2441,24 +3200,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -2473,9 +3238,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "powerfmt", @@ -2520,9 +3285,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -2543,7 +3308,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -2603,7 +3368,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -2675,12 +3440,43 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-bidi" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" + [[package]] name = "untrusted" version = "0.7.1" @@ -2693,6 +3489,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf8parse" version = "0.2.1" @@ -2707,9 +3514,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "7cdbaf5e132e593e9fc1de6a15bbec912395b11fb9719e061cf64f804524c503" [[package]] name = "version_check" @@ -2769,7 +3576,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -2803,7 +3610,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2826,9 +3633,9 @@ dependencies = [ [[package]] name = "wildmatch" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" +checksum = "495ec47bf3c1345005f40724f0269362c8556cbc43aed0526ed44cae1d35fceb" [[package]] name = "winapi" @@ -2995,9 +3802,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.28" +version = "0.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" dependencies = [ "memchr", ] @@ -3029,22 +3836,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8713621..8c8b20b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "crates/*", diff --git a/README.md b/README.md index c1b2408..da27479 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# Decentralized HomeAssistant Proxy +# Decentralized reverse proxy for HomeAssistant, IoT and more -This project aims to create an innovative decentralized relay server for HomeAssistant. The server allows contributions from anyone and provides a fast and optimized path between clients. +This project aims to create an innovative decentralized reverse proxy server for HomeAssistant, IoT and more. The server allows contributions from anyone and provides a fast and optimized path between clients. + +If you find it interesting or believe it could be helpful, we welcome your contributions to the codebase or consider starring the repository to show your support and motivate our team! ## Features -- **Decentralized:** The server is designed to be decentralized, allowing anyone to contribute and participate in the network. +- **Decentralized:** The server is designed to be decentralized, allowing anyone to contribute and participate in the network. More details: [atm0s-sdn](https://github.com/8xff/atm0s-sdn) - **Fast Relay:** The relay server ensures fast and efficient communication between clients, optimizing the path for data transmission using the atm0s-sdn overlay network. @@ -12,6 +14,63 @@ This project aims to create an innovative decentralized relay server for HomeAss - **Written in Rust:** The project is implemented in Rust, a modern and efficient programming language known for its performance and memory safety. +- **No account required:** Each client will be identified by a public-private key, just connect and it works. + +## Check list + +- [x] Decentralized Routing, Relay between nodes +- [x] TLS(SNI) tunneling +- [x] HTTP tunneling +- [x] Stats Dashboard +- [x] Anonymous client +- [ ] Anonymous server contribution (WIP) + +## Performance + +Bellow is benchmarking results with Mac M1, and all nodes is running localy, it it very early version so it can be improve after finish all features: + +- Direct http + +```bash +wrk http://localhost:3000 +Running 10s test @ http://localhost:3000 + 2 threads and 10 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 113.58us 32.97us 3.68ms 77.81% + Req/Sec 41.60k 1.27k 43.00k 89.60% + 836084 requests in 10.10s, 143.52MB read +Requests/sec: 82780.91 +Transfer/sec: 14.21MB +``` + +- Single node + +```bash +wrk http://localhost:3000 +Running 10s test @ http://localhost:3000 + 2 threads and 10 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 407.38us 489.34us 16.67ms 98.87% + Req/Sec 13.18k 1.67k 17.61k 77.72% + 264801 requests in 10.10s, 45.46MB read +Requests/sec: 26218.89 +Transfer/sec: 4.50MB +``` + +- Two nodes + +```bash +wrk http://localhost:3000 +Running 10s test @ http://localhost:3000 + 2 threads and 10 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 678.58us 681.76us 19.83ms 98.50% + Req/Sec 8.06k 1.19k 9.60k 64.85% + 162101 requests in 10.10s, 27.83MB read +Requests/sec: 16049.83 +Transfer/sec: 2.76MB +``` + ## Getting Started To get started with the Decentralized HomeAssistant Proxy, follow these steps: @@ -19,22 +78,60 @@ To get started with the Decentralized HomeAssistant Proxy, follow these steps: 1. Clone the repository: ```shell - git clone https://github.com/your-username/decentralized-homeassistant-proxy.git + git clone https://github.com/8xFF/atm0s-reverse-proxy.git ``` 2. Build the project: ```shell - cd decentralized-homeassistant-proxy - cargo build + cd atm0s-reverse-proxy + cargo build --release ``` -3. Run the server: +3. Run the server node1: ```shell - cargo run --release + ./target/release/relayer \ + --api-port 10001 \ + --http-port 11001 \ + --https-port 12001 \ + --connector-port 0.0.0.0:13001 \ + --root-domain local.ha.8xff.io \ + --sdn-node-id 1 ``` +3. Run the server node2: + + ```shell + ./target/release/relayer \ + --api-port 10002 \ + --http-port 11002 \ + --https-port 12002 \ + --connector-port 0.0.0.0:13002 \ + --root-domain local.ha.8xff.io \ + --sdn-node-id 2 \ + --sdn-seeds '1@/ip4/192.168.1.39/udp/50001' + ``` + +4. Run the client: + + ```shell + ./target/release/agent \ + --connector-protocol tcp \ + --connector-addr 127.0.0.1:13001 \ + --http-dest 127.0.0.1:8080 \ + --https-dest 127.0.0.1:8443 + ``` + Client will print out assigned domain like: `a5fae3d220cb062c5aed9bd57d82f226.local.ha.8xff.io`, now we can access to local 8080 service with address: + + - Proxy over single node1: + http://a5fae3d220cb062c5aed9bd57d82f226.local.ha.8xff.io:11001 + + - Proxy with relay over node2 -> node1: + http://a5fae3d220cb062c5aed9bd57d82f226.local.ha.8xff.io:11002 + + Note that above url only can access in same machine. + ## Contributing Contributions are welcome! If you'd like to contribute to the project, please follow the guidelines outlined in [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/crates/agent/node_local.sh b/crates/agent/node_local.sh new file mode 100644 index 0000000..3133b67 --- /dev/null +++ b/crates/agent/node_local.sh @@ -0,0 +1,5 @@ +cargo run --release -- \ + --connector-protocol tcp \ + --connector-addr 127.0.0.1:13001 \ + --http-dest 127.0.0.1:8080 \ + --https-dest 127.0.0.1:8443 \ No newline at end of file diff --git a/crates/agent/src/main.rs b/crates/agent/src/main.rs index de972b0..9656623 100644 --- a/crates/agent/src/main.rs +++ b/crates/agent/src/main.rs @@ -6,10 +6,10 @@ static A: System = System; use std::net::SocketAddr; use async_std::io::WriteExt; -use clap::Parser; +use clap::{Parser, ValueEnum}; -use connection::quic::QuicSubConnection; -use futures::{select, FutureExt}; +use connection::tcp::TcpConnection; +use futures::{select, AsyncRead, AsyncReadExt, AsyncWrite, FutureExt}; use local_tunnel::tcp::LocalTcpTunnel; use protocol::key::LocalKey; use tracing_subscriber::{fmt, layer::*, util::SubscriberInitExt, EnvFilter}; @@ -22,13 +22,23 @@ use crate::{ mod connection; mod local_tunnel; +#[derive(ValueEnum, Debug, Clone)] +enum Protocol { + Tcp, + Quic, +} + /// A HTTP and SNI HTTPs proxy for expose your local service to the internet. #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// Address of relay server - #[arg(env, long, long, default_value = "127.0.0.1:33333")] - quic_connector_addr: SocketAddr, + #[arg(env, long)] + connector_addr: SocketAddr, + + /// Protocol of relay server + #[arg(env, long)] + connector_protocol: Protocol, /// Http proxy dest #[arg(env, long, default_value = "127.0.0.1:8080")] @@ -87,43 +97,72 @@ async fn main() { }; loop { - log::info!("Connecting to connector... {}", args.quic_connector_addr); - if let Ok(mut connection) = QuicConnection::new(args.quic_connector_addr, &local_key).await - { - log::info!("Connection to connector is established"); - loop { - match connection.recv().await { - Ok(sub_connection) => { - log::info!("recv sub_connection"); - async_std::task::spawn_local(run_connection( - sub_connection, - args.http_dest, - args.https_dest, - )); - } - Err(e) => { - log::error!("recv sub_connection error: {}", e); - break; - } + log::info!( + "Connecting to connector... {:?} addr: {:?}", + args.connector_protocol, + args.connector_addr + ); + match args.connector_protocol { + Protocol::Tcp => match TcpConnection::new(args.connector_addr, &local_key).await { + Ok(conn) => { + log::info!("Connected to connector via tcp"); + run_loop(conn, args.http_dest, args.https_dest).await; } - } - log::warn!("Connection to connector is closed, try to reconnect..."); + Err(e) => { + log::error!("Connect to connector via tcp error: {}", e); + } + }, + Protocol::Quic => match QuicConnection::new(args.connector_addr, &local_key).await { + Ok(conn) => { + log::info!("Connected to connector via quic"); + run_loop(conn, args.http_dest, args.https_dest).await; + } + Err(e) => { + log::error!("Connect to connector via quic error: {}", e); + } + }, } //TODO exponential backoff async_std::task::sleep(std::time::Duration::from_secs(1)).await; } } -async fn run_connection( - sub_connection: QuicSubConnection, +async fn run_loop( + mut connection: impl Connection, http_dest: SocketAddr, https_dest: SocketAddr, -) { +) where + S: SubConnection + 'static, + R: AsyncRead + Send + Unpin + 'static, + W: AsyncWrite + Send + Unpin + 'static, +{ + log::info!("Connection to connector is established"); + loop { + match connection.recv().await { + Ok(sub_connection) => { + log::info!("recv sub_connection"); + async_std::task::spawn_local(run_connection(sub_connection, http_dest, https_dest)); + } + Err(e) => { + log::error!("recv sub_connection error: {}", e); + break; + } + } + } + log::warn!("Connection to connector is closed, try to reconnect..."); +} + +async fn run_connection(sub_connection: S, http_dest: SocketAddr, https_dest: SocketAddr) +where + S: SubConnection + 'static, + R: AsyncRead + Send + Unpin, + W: AsyncWrite + Send + Unpin, +{ log::info!("sub_connection pipe to local_tunnel start"); let (mut reader1, mut writer1) = sub_connection.split(); let mut first_pkt = [0u8; 4096]; let (local_tunnel, first_pkt_len) = match reader1.read(&mut first_pkt).await { - Ok(Some(first_pkt_len)) => { + Ok(first_pkt_len) => { log::info!("first pkt size: {}", first_pkt_len); if first_pkt_len == 0 { log::error!("first pkt size is 0 => close"); @@ -137,10 +176,6 @@ async fn run_connection( (LocalTcpTunnel::new(http_dest).await, first_pkt_len) } } - Ok(None) => { - log::error!("read first pkt error: eof"); - return; - } Err(e) => { log::error!("read first pkt error: {}", e); return; diff --git a/crates/protocol/src/cluster.rs b/crates/protocol/src/cluster.rs new file mode 100644 index 0000000..60ca069 --- /dev/null +++ b/crates/protocol/src/cluster.rs @@ -0,0 +1,39 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct ClusterTunnelRequest { + pub domain: String, +} + +impl From<&ClusterTunnelRequest> for Vec { + fn from(resp: &ClusterTunnelRequest) -> Self { + bincode::serialize(resp).expect("Should ok") + } +} + +impl TryFrom<&[u8]> for ClusterTunnelRequest { + type Error = bincode::Error; + + fn try_from(buf: &[u8]) -> Result { + bincode::deserialize(buf) + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ClusterTunnelResponse { + pub success: bool, +} + +impl From<&ClusterTunnelResponse> for Vec { + fn from(resp: &ClusterTunnelResponse) -> Self { + bincode::serialize(resp).expect("Should ok") + } +} + +impl TryFrom<&[u8]> for ClusterTunnelResponse { + type Error = bincode::Error; + + fn try_from(buf: &[u8]) -> Result { + bincode::deserialize(buf) + } +} diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index b781615..f3643e7 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,2 +1,3 @@ +pub mod cluster; pub mod key; pub mod rpc; diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 7ad5b93..f6327c8 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -20,6 +20,7 @@ metrics = { version = "0.21.1" } quinn = { version = "0.10.2", default-features = false, features = ["native-certs", "tls-rustls", "log", "runtime-async-std", "futures-io", "ring"] } rustls = { version = "0.21.0", default-features = false, features = ["quic", "dangerous_configuration"] } rcgen = "0.12.0" +atm0s-sdn = { version = "0.1.7", features = ["all"]} [features] default = [] diff --git a/crates/relayer/run_local_node1.sh b/crates/relayer/run_local_node1.sh new file mode 100644 index 0000000..db46b0b --- /dev/null +++ b/crates/relayer/run_local_node1.sh @@ -0,0 +1,7 @@ +cargo run --release -- \ + --api-port 10001 \ + --http-port 11001 \ + --https-port 12001 \ + --connector-port 0.0.0.0:13001 \ + --root-domain local.ha.8xff.io \ + --sdn-node-id 1 \ No newline at end of file diff --git a/crates/relayer/run_local_node2.sh b/crates/relayer/run_local_node2.sh new file mode 100644 index 0000000..a874f31 --- /dev/null +++ b/crates/relayer/run_local_node2.sh @@ -0,0 +1,8 @@ +cargo run --release -- \ + --api-port 10002 \ + --http-port 11002 \ + --https-port 12002 \ + --connector-port 0.0.0.0:13002 \ + --root-domain local.ha.8xff.io \ + --sdn-node-id 2 \ + --sdn-seeds '1@/ip4/192.168.1.39/udp/50001' \ No newline at end of file diff --git a/crates/relayer/src/agent_listener/quic.rs b/crates/relayer/src/agent_listener/quic.rs index 96f2b9a..de9245d 100644 --- a/crates/relayer/src/agent_listener/quic.rs +++ b/crates/relayer/src/agent_listener/quic.rs @@ -10,27 +10,31 @@ use super::{AgentConnection, AgentListener, AgentSubConnection}; pub struct AgentQuicListener { endpoint: Endpoint, - server_cert: Vec, root_domain: String, } impl AgentQuicListener { pub async fn new(addr: SocketAddr, root_domain: String) -> Self { log::info!("AgentQuicListener::new {}", addr); - let (endpoint, server_cert) = + let (endpoint, _server_cert) = make_server_endpoint(addr).expect("Should make server endpoint"); Self { endpoint, - server_cert, root_domain, } } - async fn process_incoming_conn(&self, conn: quinn::Connection) -> Result> { + async fn process_incoming_conn( + &self, + conn: quinn::Connection, + ) -> Result> { let (mut send, mut recv) = conn.accept_bi().await?; let mut buf = [0u8; 4096]; - let buf_len = recv.read(&mut buf).await?.ok_or::>("No incomming data".into())?; + let buf_len = recv + .read(&mut buf) + .await? + .ok_or::>("No incomming data".into())?; match RegisterRequest::try_from(&buf[..buf_len]) { Ok(request) => { @@ -63,7 +67,11 @@ impl AgentListener Result> { loop { - let incoming_conn = self.endpoint.accept().await.ok_or::>("Cannot accept".into())?; + let incoming_conn = self + .endpoint + .accept() + .await + .ok_or::>("Cannot accept".into())?; let conn: quinn::Connection = incoming_conn.await?; log::info!( "[AgentQuicListener] new conn from {}", diff --git a/crates/relayer/src/agent_listener/tcp.rs b/crates/relayer/src/agent_listener/tcp.rs index 9eeb3cf..8a062d2 100644 --- a/crates/relayer/src/agent_listener/tcp.rs +++ b/crates/relayer/src/agent_listener/tcp.rs @@ -1,7 +1,8 @@ use std::{ - net::{Ipv4Addr, SocketAddr}, + error::Error, + net::SocketAddr, pin::Pin, - task::{Context, Poll}, error::Error, + task::{Context, Poll}, }; use async_std::net::{TcpListener, TcpStream}; @@ -22,17 +23,18 @@ pub struct AgentTcpListener { } impl AgentTcpListener { - pub async fn new(port: u16, root_domain: String) -> Option { - log::info!("AgentTcpListener::new {}", port); - Some(Self { - tcp_listener: TcpListener::bind(SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), port)) - .await - .ok()?, + pub async fn new(addr: SocketAddr, root_domain: String) -> Self { + log::info!("AgentTcpListener::new {}", addr); + Self { + tcp_listener: TcpListener::bind(addr).await.expect("Should open"), root_domain, - }) + } } - async fn process_incoming_stream(&self, mut stream: TcpStream) -> Result> { + async fn process_incoming_stream( + &self, + mut stream: TcpStream, + ) -> Result> { let mut buf = [0u8; 4096]; let buf_len = stream.read(&mut buf).await?; @@ -173,9 +175,11 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.get_mut(); match this.connection.poll_next_inbound(cx) { - Poll::Ready(Some(Ok(stream))) => return Poll::Ready(Ok(())), + Poll::Ready(Some(Ok(_stream))) => return Poll::Ready(Ok(())), Poll::Ready(Some(Err(e))) => return Poll::Ready(Err(e.into())), - Poll::Ready(None) => return Poll::Ready(Err("yamux server poll next inbound return None".into())), + Poll::Ready(None) => { + return Poll::Ready(Err("yamux server poll next inbound return None".into())) + } Poll::Pending => Poll::Pending, } } diff --git a/crates/relayer/src/agent_worker.rs b/crates/relayer/src/agent_worker.rs index db6a0e5..2b6c729 100644 --- a/crates/relayer/src/agent_worker.rs +++ b/crates/relayer/src/agent_worker.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, error::Error}; +use std::{error::Error, marker::PhantomData}; use futures::{select, AsyncRead, AsyncWrite, FutureExt}; use metrics::increment_gauge; @@ -8,32 +8,26 @@ use crate::{ proxy_listener::ProxyTunnel, }; -pub struct AgentWorker +pub struct AgentWorker where AG: AgentConnection, S: AgentSubConnection, R: AsyncRead + Unpin, W: AsyncWrite + Unpin, - PT: ProxyTunnel, - PR: AsyncRead + Unpin, - PW: AsyncWrite + Unpin, { - _tmp: PhantomData<(S, R, W, PR, PW)>, + _tmp: PhantomData<(S, R, W)>, connection: AG, - rx: async_std::channel::Receiver, + rx: async_std::channel::Receiver>, } -impl AgentWorker +impl AgentWorker where AG: AgentConnection, S: AgentSubConnection + 'static, R: AsyncRead + Send + Unpin, W: AsyncWrite + Send + Unpin, - PT: ProxyTunnel + 'static, - PR: AsyncRead + Send + Unpin, - PW: AsyncWrite + Send + Unpin, { - pub fn new(connection: AG) -> (Self, async_std::channel::Sender) { + pub fn new(connection: AG) -> (Self, async_std::channel::Sender>) { let (tx, rx) = async_std::channel::bounded(3); ( Self { @@ -46,7 +40,7 @@ where } pub async fn run(&mut self) -> Result<(), Box> { - let incoming = select! { + let mut incoming = select! { incoming = self.rx.recv().fuse() => incoming?, e = self.connection.recv().fuse() => { e?; diff --git a/crates/relayer/src/main.rs b/crates/relayer/src/main.rs index 95d016d..ec7d7af 100644 --- a/crates/relayer/src/main.rs +++ b/crates/relayer/src/main.rs @@ -1,3 +1,4 @@ +use atm0s_sdn::{NodeAddr, NodeAliasSdk, NodeId}; use clap::Parser; #[cfg(feature = "expose-metrics")] use metrics_dashboard::build_dashboard_route; @@ -5,9 +6,10 @@ use metrics_dashboard::build_dashboard_route; use poem::{listener::TcpListener, middleware::Tracing, EndpointExt as _, Route, Server}; use std::{collections::HashMap, net::SocketAddr, process::exit, sync::Arc}; -use agent_listener::quic::AgentQuicListener; +use agent_listener::tcp::AgentTcpListener; +use agent_listener::{quic::AgentQuicListener, AgentSubConnection}; use async_std::sync::RwLock; -use futures::{select, FutureExt}; +use futures::{select, AsyncRead, AsyncWrite, FutureExt}; use metrics::{ decrement_gauge, describe_counter, describe_gauge, increment_counter, increment_gauge, }; @@ -17,16 +19,22 @@ use tracing_subscriber::{fmt, layer::SubscriberExt as _, util::SubscriberInitExt const METRICS_AGENT_COUNT: &str = "agent.count"; const METRICS_AGENT_LIVE: &str = "agent.live"; const METRICS_PROXY_COUNT: &str = "proxy.count"; +const METRICS_CLUSTER_LIVE: &str = "cluster.live"; +const METRICS_CLUSTER_COUNT: &str = "cluster.count"; pub(crate) const METRICS_PROXY_LIVE: &str = "proxy.live"; +use crate::utils::domain_hash; use crate::{ agent_listener::{AgentConnection, AgentListener}, proxy_listener::{ProxyListener, ProxyTunnel}, + tunnel::TunnelContext, }; mod agent_listener; mod agent_worker; mod proxy_listener; +mod tunnel; +mod utils; /// A HTTP and SNI HTTPs proxy for expose your local service to the internet. #[derive(Parser, Debug)] @@ -46,11 +54,23 @@ struct Args { /// Number of times to greet #[arg(env, long, default_value = "0.0.0.0:33333")] - quic_connector_port: SocketAddr, + connector_port: SocketAddr, /// Root domain #[arg(env, long, default_value = "localtunnel.me")] root_domain: String, + + /// atm0s-sdn node-id + #[arg(env, long)] + sdn_node_id: NodeId, + + /// atm0s-sdn secret key + #[arg(env, long, default_value = "insecure")] + sdn_secret_key: String, + + /// atm0s-sdn seed address + #[arg(env, long)] + sdn_seeds: Vec, } #[async_std::main] @@ -65,8 +85,9 @@ async fn main() { .with(fmt::layer()) .with(EnvFilter::from_default_env()) .init(); - let mut agent_listener = - AgentQuicListener::new(args.quic_connector_port, args.root_domain).await; + let mut quic_agent_listener = + AgentQuicListener::new(args.connector_port, args.root_domain.clone()).await; + let mut tcp_agent_listener = AgentTcpListener::new(args.connector_port, args.root_domain).await; let mut proxy_http_listener = ProxyHttpListener::new(args.http_port, false) .await .expect("Should listen http port"); @@ -88,37 +109,29 @@ async fn main() { #[cfg(feature = "expose-metrics")] async_std::task::spawn(async move { let _ = Server::new(TcpListener::bind("0.0.0.0:33334")) - .name("hello-world") + .name("relay-metrics") .run(app) .await; }); + let (mut cluster_endpoint, node_alias_sdk, virtual_net) = + proxy_listener::cluster::run_sdn(args.sdn_node_id, args.sdn_secret_key, args.sdn_seeds) + .await; + loop { select! { - e = agent_listener.recv().fuse() => match e { + e = quic_agent_listener.recv().fuse() => match e { + Ok(agent_connection) => { + run_agent_connection(agent_connection, agents.clone(), node_alias_sdk.clone()).await; + } + Err(e) => { + log::error!("agent_listener error {}", e); + exit(1); + } + }, + e = tcp_agent_listener.recv().fuse() => match e { Ok(agent_connection) => { - increment_counter!(METRICS_AGENT_COUNT); - log::info!("agent_connection.domain(): {}", agent_connection.domain()); - let domain = agent_connection.domain().to_string(); - let (mut agent_worker, proxy_tunnel_tx) = agent_worker::AgentWorker::new(agent_connection); - agents.write().await.insert(domain.clone(), proxy_tunnel_tx); - let agents = agents.clone(); - async_std::task::spawn(async move { - increment_gauge!(METRICS_AGENT_LIVE, 1.0); - log::info!("agent_worker run for domain: {}", domain); - loop { - match agent_worker.run().await { - Ok(()) => {} - Err(e) => { - log::error!("agent_worker error: {}", e); - break; - } - } - } - agents.write().await.remove(&domain); - log::info!("agent_worker exit for domain: {}", domain); - decrement_gauge!(METRICS_AGENT_LIVE, 1.0); - }); + run_agent_connection(agent_connection, agents.clone(), node_alias_sdk.clone()).await; } Err(e) => { log::error!("agent_listener error {}", e); @@ -126,21 +139,8 @@ async fn main() { } }, e = proxy_http_listener.recv().fuse() => match e { - Some(mut proxy_tunnel) => { - let agents = agents.clone(); - async_std::task::spawn(async move { - if proxy_tunnel.wait().await.is_none() { - return; - } - increment_counter!(METRICS_PROXY_COUNT); - log::info!("proxy_tunnel.domain(): {}", proxy_tunnel.domain()); - let domain = proxy_tunnel.domain().to_string(); - if let Some(agent_tx) = agents.read().await.get(&domain) { - agent_tx.send(proxy_tunnel).await.ok(); - } else { - log::warn!("agent not found for domain: {}", domain); - } - }); + Some(proxy_tunnel) => { + async_std::task::spawn(tunnel::tunnel_task(proxy_tunnel, agents.clone(), TunnelContext::Local(node_alias_sdk.clone(), virtual_net.clone()))); } None => { log::error!("proxy_http_listener.recv()"); @@ -148,23 +148,60 @@ async fn main() { } }, e = proxy_tls_listener.recv().fuse() => match e { - Some(mut proxy_tunnel) => { - if proxy_tunnel.wait().await.is_none() { - continue; - } - log::info!("proxy_tunnel.domain(): {}", proxy_tunnel.domain()); - let domain = proxy_tunnel.domain().to_string(); - if let Some(agent_tx) = agents.read().await.get(&domain) { - agent_tx.send(proxy_tunnel).await.ok(); - } else { - log::warn!("agent not found for domain: {}", domain); - } + Some(proxy_tunnel) => { + async_std::task::spawn(tunnel::tunnel_task(proxy_tunnel, agents.clone(), TunnelContext::Local(node_alias_sdk.clone(), virtual_net.clone()))); } None => { log::error!("proxy_http_listener.recv()"); exit(2); } }, + e = cluster_endpoint.recv().fuse() => match e { + Some(proxy_tunnel) => { + async_std::task::spawn(tunnel::tunnel_task(proxy_tunnel, agents.clone(), TunnelContext::Cluster)); + } + None => { + log::error!("cluster_endpoint.accept()"); + exit(3); + } + } } } } + +async fn run_agent_connection( + agent_connection: AG, + agents: Arc>>>>, + node_alias_sdk: NodeAliasSdk, +) where + AG: AgentConnection + 'static, + S: AgentSubConnection + 'static, + R: AsyncRead + Send + Unpin + 'static, + W: AsyncWrite + Send + Unpin + 'static, +{ + increment_counter!(METRICS_AGENT_COUNT); + log::info!("agent_connection.domain(): {}", agent_connection.domain()); + let domain = agent_connection.domain().to_string(); + let (mut agent_worker, proxy_tunnel_tx) = + agent_worker::AgentWorker::::new(agent_connection); + agents.write().await.insert(domain.clone(), proxy_tunnel_tx); + node_alias_sdk.register(domain_hash(&domain)); + let agents = agents.clone(); + async_std::task::spawn(async move { + increment_gauge!(METRICS_AGENT_LIVE, 1.0); + log::info!("agent_worker run for domain: {}", domain); + loop { + match agent_worker.run().await { + Ok(()) => {} + Err(e) => { + log::error!("agent_worker error: {}", e); + break; + } + } + } + agents.write().await.remove(&domain); + node_alias_sdk.unregister(domain_hash(&domain)); + log::info!("agent_worker exit for domain: {}", domain); + decrement_gauge!(METRICS_AGENT_LIVE, 1.0); + }); +} diff --git a/crates/relayer/src/proxy_listener.rs b/crates/relayer/src/proxy_listener.rs index ba64a9c..ab5471d 100644 --- a/crates/relayer/src/proxy_listener.rs +++ b/crates/relayer/src/proxy_listener.rs @@ -2,18 +2,22 @@ use futures::{AsyncRead, AsyncWrite}; +pub mod cluster; pub mod http; #[async_trait::async_trait] -pub trait ProxyTunnel: Send + Sync { +pub trait ProxyTunnel: Send + Sync { async fn wait(&mut self) -> Option<()>; fn domain(&self) -> &str; - fn split(self) -> (R, W); + fn split( + &mut self, + ) -> ( + Box, + Box, + ); } #[async_trait::async_trait] -pub trait ProxyListener, R: AsyncRead + Unpin, W: AsyncWrite + Unpin>: - Send + Sync -{ - async fn recv(&mut self) -> Option; +pub trait ProxyListener: Send + Sync { + async fn recv(&mut self) -> Option>; } diff --git a/crates/relayer/src/proxy_listener/cluster.rs b/crates/relayer/src/proxy_listener/cluster.rs new file mode 100644 index 0000000..c8fc77c --- /dev/null +++ b/crates/relayer/src/proxy_listener/cluster.rs @@ -0,0 +1,164 @@ +use std::sync::Arc; + +use atm0s_sdn::virtual_socket::{create_vnet, make_insecure_quinn_server, VirtualNet}; +use atm0s_sdn::{ + convert_enum, KeyValueBehavior, KeyValueBehaviorEvent, KeyValueHandlerEvent, KeyValueSdk, + KeyValueSdkEvent, LayersSpreadRouterSyncBehavior, LayersSpreadRouterSyncBehaviorEvent, + LayersSpreadRouterSyncHandlerEvent, ManualBehavior, ManualBehaviorConf, ManualBehaviorEvent, + ManualHandlerEvent, NetworkPlane, NetworkPlaneConfig, NodeAddrBuilder, NodeAliasBehavior, + NodeAliasSdk, PubsubServiceBehaviour, PubsubServiceBehaviourEvent, PubsubServiceHandlerEvent, + SharedRouter, SystemTimer, UdpTransport, +}; +use atm0s_sdn::{NodeAddr, NodeId}; +use futures::{AsyncRead, AsyncWrite}; +use protocol::cluster::{ClusterTunnelRequest, ClusterTunnelResponse}; +use quinn::{Connecting, Endpoint}; + +use super::{ProxyListener, ProxyTunnel}; + +#[derive(convert_enum::From, convert_enum::TryInto)] +enum NodeBehaviorEvent { + Manual(ManualBehaviorEvent), + LayersSpreadRouterSync(LayersSpreadRouterSyncBehaviorEvent), + KeyValue(KeyValueBehaviorEvent), + Pubsub(PubsubServiceBehaviourEvent), +} + +#[derive(convert_enum::From, convert_enum::TryInto)] +enum NodeHandleEvent { + Manual(ManualHandlerEvent), + LayersSpreadRouterSync(LayersSpreadRouterSyncHandlerEvent), + KeyValue(KeyValueHandlerEvent), + Pubsub(PubsubServiceHandlerEvent), +} + +#[derive(convert_enum::From, convert_enum::TryInto)] +enum NodeSdkEvent { + KeyValue(KeyValueSdkEvent), +} + +pub async fn run_sdn( + node_id: NodeId, + secret_key: String, + seeds: Vec, +) -> (ProxyClusterListener, NodeAliasSdk, VirtualNet) { + let secure = Arc::new(atm0s_sdn::StaticKeySecure::new(&secret_key)); + let mut node_addr_builder = NodeAddrBuilder::new(node_id); + let udp_socket = UdpTransport::prepare(50000 + node_id as u16, &mut node_addr_builder).await; + let transport = UdpTransport::new(node_addr_builder.addr(), udp_socket, secure.clone()); + + let node_addr = node_addr_builder.addr(); + log::info!("atm0s-sdn listen on addr {}", node_addr); + + let timer = Arc::new(SystemTimer()); + let router = SharedRouter::new(node_id); + + let manual = ManualBehavior::new(ManualBehaviorConf { + node_id, + node_addr, + seeds, + local_tags: vec!["relayer".to_string()], + connect_tags: vec!["relayer".to_string()], + }); + + let spreads_layer_router = LayersSpreadRouterSyncBehavior::new(router.clone()); + let router = Arc::new(router); + + let kv_sdk = KeyValueSdk::new(); + let kv_behaviour = KeyValueBehavior::new(node_id, 1000, Some(Box::new(kv_sdk))); + let (pubsub_behavior, pubsub_sdk) = PubsubServiceBehaviour::new(node_id, timer.clone()); + let (node_alias_behavior, node_alias_sdk) = NodeAliasBehavior::new(node_id, pubsub_sdk); + let (virtual_socket, virtual_socket_sdk) = create_vnet(node_id, router.clone()); + + let plan_cfg = NetworkPlaneConfig { + router, + node_id, + tick_ms: 1000, + behaviors: vec![ + Box::new(manual), + Box::new(spreads_layer_router), + Box::new(kv_behaviour), + Box::new(virtual_socket), + Box::new(pubsub_behavior), + Box::new(node_alias_behavior), + ], + transport: Box::new(transport), + timer, + }; + + let mut plane = NetworkPlane::::new(plan_cfg); + + async_std::task::spawn(async move { + plane.started(); + while let Ok(_) = plane.recv().await {} + plane.stopped(); + }); + + ( + ProxyClusterListener::new(&virtual_socket_sdk), + node_alias_sdk, + virtual_socket_sdk, + ) +} + +pub struct ProxyClusterListener { + server: Endpoint, +} + +impl ProxyClusterListener { + pub fn new(sdk: &VirtualNet) -> Self { + let server = + make_insecure_quinn_server(sdk.create_udp_socket(80, 1000).expect("")).expect(""); + + Self { server } + } +} + +#[async_trait::async_trait] +impl ProxyListener for ProxyClusterListener { + async fn recv(&mut self) -> Option> { + Some(Box::new(ProxyClusterTunnel { + domain: "".to_string(), + connecting: Some(self.server.accept().await?), + streams: None, + })) + } +} + +pub struct ProxyClusterTunnel { + domain: String, + connecting: Option, + streams: Option<( + Box, + Box, + )>, +} + +#[async_trait::async_trait] +impl ProxyTunnel for ProxyClusterTunnel { + async fn wait(&mut self) -> Option<()> { + let connection = self.connecting.take()?.await.ok()?; + let (mut send, mut recv) = connection.accept_bi().await.ok()?; + let mut req_buf = [0; 1500]; + let req_size = recv.read(&mut req_buf).await.ok()??; + let req = ClusterTunnelRequest::try_from(&req_buf[..req_size]).ok()?; + let res_buf: Vec = (&ClusterTunnelResponse { success: true }).into(); + send.write_all(&res_buf).await.ok()?; + log::info!("ProxyClusterTunnel domain: {}", req.domain); + + self.domain = req.domain; + self.streams = Some((Box::new(recv), Box::new(send))); + Some(()) + } + fn domain(&self) -> &str { + &self.domain + } + fn split( + &mut self, + ) -> ( + Box, + Box, + ) { + self.streams.take().expect("Should has send and recv") + } +} diff --git a/crates/relayer/src/proxy_listener/http.rs b/crates/relayer/src/proxy_listener/http.rs index 03f4104..9a73a41 100644 --- a/crates/relayer/src/proxy_listener/http.rs +++ b/crates/relayer/src/proxy_listener/http.rs @@ -1,10 +1,7 @@ use std::net::{Ipv4Addr, SocketAddr}; use async_std::net::{TcpListener, TcpStream}; -use futures::{ - io::{ReadHalf, WriteHalf}, - AsyncReadExt, -}; +use futures::{AsyncRead, AsyncReadExt, AsyncWrite}; use tls_parser::{parse_tls_extensions, parse_tls_plaintext}; use super::{ProxyListener, ProxyTunnel}; @@ -27,32 +24,31 @@ impl ProxyHttpListener { } #[async_trait::async_trait] -impl ProxyListener, WriteHalf> - for ProxyHttpListener -{ - async fn recv(&mut self) -> Option { +impl ProxyListener for ProxyHttpListener { + async fn recv(&mut self) -> Option> { let (stream, remote) = self.tcp_listener.accept().await.ok()?; log::info!("[ProxyHttpListener] new conn from {}", remote); - Some(ProxyHttpTunnel { - domain: "demo".to_string(), - stream, + Some(Box::new(ProxyHttpTunnel { + domain: "".to_string(), + stream: Some(stream), tls: self.tls, - }) + })) } } pub struct ProxyHttpTunnel { domain: String, - stream: TcpStream, + stream: Option, tls: bool, } #[async_trait::async_trait] -impl ProxyTunnel, WriteHalf> for ProxyHttpTunnel { +impl ProxyTunnel for ProxyHttpTunnel { async fn wait(&mut self) -> Option<()> { log::info!("[ProxyHttpTunnel] wait first data for checking url..."); let mut first_pkt = [0u8; 4096]; - let first_pkt_size = self.stream.peek(&mut first_pkt).await.ok()?; + let stream = self.stream.as_mut()?; + let first_pkt_size = stream.peek(&mut first_pkt).await.ok()?; log::info!( "[ProxyHttpTunnel] read {} bytes for determine url", first_pkt_size @@ -75,8 +71,14 @@ impl ProxyTunnel, WriteHalf> for ProxyHttpTunnel fn domain(&self) -> &str { &self.domain } - fn split(self) -> (ReadHalf, WriteHalf) { - AsyncReadExt::split(self.stream) + fn split( + &mut self, + ) -> ( + Box, + Box, + ) { + let (read, write) = AsyncReadExt::split(self.stream.take().expect("Should has stream")); + (Box::new(read), Box::new(write)) } } diff --git a/crates/relayer/src/tunnel.rs b/crates/relayer/src/tunnel.rs new file mode 100644 index 0000000..2442649 --- /dev/null +++ b/crates/relayer/src/tunnel.rs @@ -0,0 +1,130 @@ +use std::{collections::HashMap, error::Error, sync::Arc, time::Duration}; + +use crate::{ + proxy_listener::ProxyTunnel, utils::domain_hash, METRICS_CLUSTER_COUNT, METRICS_CLUSTER_LIVE, + METRICS_PROXY_COUNT, +}; +use async_std::{prelude::FutureExt, sync::RwLock}; +use atm0s_sdn::{ + virtual_socket::{make_insecure_quinn_client, vnet_addr, VirtualNet}, + NodeAliasResult, NodeAliasSdk, +}; +use futures::{select, FutureExt as _}; +use metrics::{decrement_gauge, increment_counter, increment_gauge}; +use protocol::cluster::{ClusterTunnelRequest, ClusterTunnelResponse}; + +pub enum TunnelContext { + Cluster, + Local(NodeAliasSdk, VirtualNet), +} + +pub async fn tunnel_task( + mut proxy_tunnel: Box, + agents: Arc>>>>, + context: TunnelContext, +) { + match proxy_tunnel.wait().timeout(Duration::from_secs(5)).await { + Err(_) => { + log::error!("proxy_tunnel.wait() for checking url timeout"); + return; + } + Ok(None) => { + log::error!("proxy_tunnel.wait() for checking url invalid"); + return; + } + _ => {} + } + increment_counter!(METRICS_PROXY_COUNT); + log::info!("proxy_tunnel.domain(): {}", proxy_tunnel.domain()); + let domain = proxy_tunnel.domain().to_string(); + if let Some(agent_tx) = agents.read().await.get(&domain) { + agent_tx.send(proxy_tunnel).await.ok(); + } else if let TunnelContext::Local(node_alias_sdk, virtual_net) = context { + if let Err(e) = tunnel_over_cluster(domain, proxy_tunnel, node_alias_sdk, virtual_net).await + { + log::error!("tunnel_over_cluster error: {}", e); + } + } +} + +async fn tunnel_over_cluster( + domain: String, + mut proxy_tunnel: Box, + node_alias_sdk: NodeAliasSdk, + virtual_net: VirtualNet, +) -> Result<(), Box> { + log::warn!( + "agent not found for domain: {} in local => finding in cluster", + domain + ); + let node_alias_id = domain_hash(&domain); + let (tx, rx) = async_std::channel::bounded(1); + node_alias_sdk.find_alias( + node_alias_id, + Box::new(move |res| { + tx.try_send(res).expect("Should send result"); + }), + ); + + let dest = match rx.recv().await? { + Ok(NodeAliasResult::FromLocal) => { + log::warn!( + "something wrong, found alias {} in local but mapper not found", + domain + ); + return Err("INTERNAL_ERROR".into()); + } + Ok(NodeAliasResult::FromHint(dest)) => dest, + Ok(NodeAliasResult::FromScan(dest)) => dest, + Err(_e) => return Err("NODE_ALIAS_NOT_FOUND".into()), + }; + + let socket = virtual_net + .create_udp_socket(0, 20) + .map_err(|e| format!("{:?}", e))?; + let client = make_insecure_quinn_client(socket)?; + let connecting = client.connect(vnet_addr(dest, 80), "localhost")?; + let connection = connecting.await?; + let (mut send, mut recv) = connection.open_bi().await?; + + let req_buf: Vec = (&ClusterTunnelRequest { + domain: domain.clone(), + }) + .into(); + send.write_all(&req_buf).await?; + let mut res_buf = [0; 1500]; + let res_size = recv + .read(&mut res_buf) + .await? + .ok_or("ClusterTunnelResponse not received".to_string())?; + let res = ClusterTunnelResponse::try_from(&res_buf[..res_size])?; + if !res.success { + log::error!("ClusterTunnelResponse not success"); + return Err("ClusterTunnelResponse not success".into()); + } + + log::info!("start cluster proxy tunnel for domain {}", domain); + increment_counter!(METRICS_CLUSTER_COUNT); + increment_gauge!(METRICS_CLUSTER_LIVE, 1.0); + + let (mut reader1, mut writer1) = proxy_tunnel.split(); + let job1 = futures::io::copy(&mut reader1, &mut send); + let job2 = futures::io::copy(&mut recv, &mut writer1); + + select! { + e = job1.fuse() => { + if let Err(e) = e { + log::info!("agent => proxy error: {}", e); + } + } + e = job2.fuse() => { + if let Err(e) = e { + log::info!("proxy => agent error: {}", e); + } + } + } + + log::info!("end cluster proxy tunnel for domain {}", domain); + decrement_gauge!(METRICS_CLUSTER_LIVE, 1.0); + Ok(()) +} diff --git a/crates/relayer/src/utils.rs b/crates/relayer/src/utils.rs new file mode 100644 index 0000000..d81b3fb --- /dev/null +++ b/crates/relayer/src/utils.rs @@ -0,0 +1,12 @@ +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, +}; + +use atm0s_sdn::NodeAliasId; + +pub fn domain_hash(domain: &str) -> NodeAliasId { + let mut hasher = DefaultHasher::default(); + domain.hash(&mut hasher); + hasher.finish().into() +} diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 07ade69..0000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly \ No newline at end of file