From e8f39b8c21a21b33bfb38295f33e0af9409c403e Mon Sep 17 00:00:00 2001 From: dgarus Date: Thu, 28 Nov 2024 11:43:43 +0300 Subject: [PATCH 01/16] Wtransport usage --- Cargo.lock | 1781 ++++++++++------- Cargo.toml | 1 + transports/tls/Cargo.toml | 1 + transports/tls/src/certificate.rs | 54 +- transports/tls/src/lib.rs | 26 + transports/webtransport/Cargo.toml | 33 + transports/webtransport/src/certificate.rs | 169 ++ transports/webtransport/src/config.rs | 77 + transports/webtransport/src/connection.rs | 83 + .../webtransport/src/connection/connecting.rs | 98 + .../webtransport/src/connection/stream.rs | 72 + transports/webtransport/src/lib.rs | 40 + transports/webtransport/src/provider.rs | 68 + .../webtransport/src/provider/async_std.rs | 70 + transports/webtransport/src/provider/tokio.rs | 70 + transports/webtransport/src/transport.rs | 394 ++++ 16 files changed, 2276 insertions(+), 761 deletions(-) create mode 100644 transports/webtransport/Cargo.toml create mode 100644 transports/webtransport/src/certificate.rs create mode 100644 transports/webtransport/src/config.rs create mode 100644 transports/webtransport/src/connection.rs create mode 100644 transports/webtransport/src/connection/connecting.rs create mode 100644 transports/webtransport/src/connection/stream.rs create mode 100644 transports/webtransport/src/lib.rs create mode 100644 transports/webtransport/src/provider.rs create mode 100644 transports/webtransport/src/provider/async_std.rs create mode 100644 transports/webtransport/src/provider/tokio.rs create mode 100644 transports/webtransport/src/transport.rs diff --git a/Cargo.lock b/Cargo.lock index 3d77ed104dc..9bc77a3962b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -52,32 +52,20 @@ dependencies = [ "subtle", ] -[[package]] -name = "ahash" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anes" @@ -87,81 +75,82 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.7" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arbitrary" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "asn1-rs" @@ -181,11 +170,11 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ - "asn1-rs-derive 0.5.0", + "asn1-rs-derive 0.5.1", "asn1-rs-impl 0.2.0", "displaydoc", "nom", @@ -209,13 +198,13 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", "synstructure 0.13.1", ] @@ -238,7 +227,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -268,17 +257,28 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-executor" -version = "1.5.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ - "async-lock 2.7.0", "async-task", "concurrent-queue", - "fastrand 1.9.0", - "futures-lite 1.13.0", + "fastrand 2.1.1", + "futures-lite 2.3.0", "slab", ] @@ -288,7 +288,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock 2.7.0", + "async-lock 2.8.0", "autocfg", "blocking", "futures-lite 1.13.0", @@ -296,16 +296,16 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel", + "async-channel 2.3.1", "async-executor", - "async-io 1.13.0", - "async-lock 2.7.0", + "async-io 2.3.4", + "async-lock 3.4.0", "blocking", - "futures-lite 1.13.0", + "futures-lite 2.3.0", "once_cell", ] @@ -315,7 +315,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock 2.7.0", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", @@ -323,99 +323,134 @@ dependencies = [ "log", "parking", "polling 2.8.0", - "rustix 0.37.25", + "rustix 0.37.27", "slab", - "socket2 0.4.9", + "socket2 0.4.10", "waker-fn", ] [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.1.0", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.3.0", "parking", - "polling 3.3.0", - "rustix 0.38.31", + "polling 3.7.3", + "rustix 0.38.37", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ "event-listener 2.5.3", ] [[package]] name = "async-lock" -version = "3.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 3.1.0", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-net" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" +checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" dependencies = [ "async-io 1.13.0", - "autocfg", "blocking", "futures-lite 1.13.0", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ "async-io 1.13.0", - "async-lock 2.7.0", - "autocfg", + "async-lock 2.8.0", + "async-signal", "blocking", "cfg-if", - "event-listener 2.5.3", + "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.37.25", - "signal-hook", + "rustix 0.38.37", "windows-sys 0.48.0", ] +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel 2.3.1", + "async-io 2.3.4", + "async-lock 3.4.0", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.3.1", + "futures-lite 2.3.0", + "rustix 0.38.37", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io 2.3.4", + "async-lock 3.4.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.37", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", - "async-channel", + "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.7.0", - "async-process", + "async-io 2.3.4", + "async-lock 3.4.0", + "async-process 2.3.0", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", - "gloo-timers", + "futures-lite 2.3.0", + "gloo-timers 0.3.0", "kv-log-macro", "log", "memchr", @@ -428,9 +463,9 @@ dependencies = [ [[package]] name = "async-std-resolver" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0ed2b6671c13d2c28756c5a64e04759c1e0b5d3d7ac031f521c3561e21fbcb" +checksum = "bc3b454643291f9a4a3bbdb35fa62efa4ba7be5ea13fe243e3be4352182ff4b8" dependencies = [ "async-std", "async-trait", @@ -443,9 +478,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -454,30 +489,30 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "async-task" -version = "4.4.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -495,9 +530,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "attohttpc" @@ -505,16 +540,16 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" dependencies = [ - "http 0.2.9", + "http 0.2.12", "log", "url", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "autonat-example" @@ -547,9 +582,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -571,9 +606,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.0", + "sync_wrapper 1.0.1", "tokio", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -581,9 +616,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -594,7 +629,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -602,17 +637,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -674,9 +709,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake2" @@ -716,17 +751,15 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel", - "async-lock 2.7.0", + "async-channel 2.3.1", "async-task", - "atomic-waker", - "fastrand 1.9.0", - "futures-lite 1.13.0", - "log", + "futures-io", + "futures-lite 2.3.0", + "piper", ] [[package]] @@ -745,7 +778,7 @@ dependencies = [ "rust-embed", "tokio", "tokio-util", - "tower", + "tower 0.4.13", "tower-http", "tracing", "tracing-subscriber", @@ -766,9 +799,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "serde", @@ -776,9 +809,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -788,9 +821,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -812,20 +845,20 @@ dependencies = [ [[package]] name = "cbor4ii" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b4c883b9cc4757b061600d39001d4d0232bece4a3174696cf8f58a14db107d" +checksum = "472931dd4dfcc785075b09be910147f9c6258883fc4591d0dac6116392b2daa6" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -884,9 +917,9 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -895,15 +928,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -922,9 +955,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.6" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -932,9 +965,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.6" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -944,33 +977,33 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -982,9 +1015,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1001,15 +1034,15 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1017,9 +1050,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1032,27 +1065,27 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "criterion" @@ -1067,7 +1100,7 @@ dependencies = [ "criterion-plot", "futures", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -1089,7 +1122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -1103,26 +1136,21 @@ dependencies = [ [[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.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", ] [[package]] @@ -1139,9 +1167,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1208,13 +1236,13 @@ dependencies = [ [[package]] name = "curve25519-dalek-derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -1225,9 +1253,9 @@ checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.13" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1235,9 +1263,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1259,9 +1287,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1288,7 +1316,7 @@ version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" dependencies = [ - "asn1-rs 0.6.1", + "asn1-rs 0.6.2", "displaydoc", "nom", "num-bigint", @@ -1328,33 +1356,34 @@ dependencies = [ [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -1377,9 +1406,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -1391,9 +1420,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "signature", @@ -1416,9 +1445,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1443,23 +1472,23 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] [[package]] name = "enum-as-inner" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -1493,9 +1522,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1518,13 +1547,24 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener-strategy" -version = "0.3.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 3.1.0", + "event-listener 5.3.1", "pin-project-lite", ] @@ -1539,9 +1579,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1555,9 +1595,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.1" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "file-sharing-example" @@ -1579,6 +1619,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1605,9 +1651,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1630,9 +1676,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1640,15 +1686,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1658,9 +1704,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1679,23 +1725,26 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.0.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ + "fastrand 2.1.1", "futures-core", + "futures-io", + "parking", "pin-project-lite", ] [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -1705,21 +1754,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.11", + "rustls 0.23.14", "rustls-pki-types", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-ticker" @@ -1738,15 +1787,15 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ - "gloo-timers", + "gloo-timers 0.2.6", "send_wrapper 0.4.0", ] [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1809,9 +1858,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -1819,9 +1868,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1831,15 +1880,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -1854,6 +1903,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -1867,17 +1928,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http 1.1.0", - "indexmap 2.2.1", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1886,9 +1947,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hashbrown" @@ -1898,31 +1963,32 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "heck" -version = "0.5.0" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -2054,11 +2120,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "httlib-huffman" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877" + [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -2078,9 +2150,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -2088,9 +2160,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", @@ -2101,21 +2173,21 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce4ef31cda248bbdb6e6820603b82dfcd9e833db65a43e997a0ccec777d11fe" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -2146,19 +2218,20 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", "hyper", "hyper-util", - "rustls 0.22.4", + "rustls 0.23.14", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", + "webpki-roots 0.26.6", ] [[package]] @@ -2256,7 +2329,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "core-foundation", "fnv", "futures", @@ -2265,7 +2338,7 @@ dependencies = [ "log", "rtnetlink", "smol", - "system-configuration", + "system-configuration 0.5.1", "tokio", "windows 0.51.1", ] @@ -2303,12 +2376,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", ] [[package]] @@ -2347,7 +2420,7 @@ dependencies = [ "log", "rand 0.8.5", "rtcp", - "rtp", + "rtp 0.9.0", "thiserror", "tokio", "waitgroup", @@ -2395,7 +2468,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -2409,7 +2482,7 @@ dependencies = [ "socket2 0.5.7", "widestring", "windows-sys 0.48.0", - "winreg 0.50.0", + "winreg", ] [[package]] @@ -2442,21 +2515,27 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", - "rustix 0.38.31", - "windows-sys 0.48.0", + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -2466,26 +2545,35 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2514,15 +2602,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libp2p" @@ -2868,7 +2956,7 @@ dependencies = [ name = "libp2p-mdns" version = "0.46.0" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-std", "data-encoding", "futures", @@ -3099,7 +3187,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.14", "socket2 0.5.7", "thiserror", "tokio", @@ -3270,10 +3358,10 @@ dependencies = [ name = "libp2p-swarm-derive" version = "0.35.0" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -3297,7 +3385,7 @@ dependencies = [ name = "libp2p-tcp" version = "0.42.0" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-std", "futures", "futures-timer", @@ -3323,11 +3411,12 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "libp2p-yamux", - "rcgen", + "rcgen 0.11.3", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.14", "rustls-webpki 0.101.7", "thiserror", + "time", "tokio", "x509-parser 0.16.0", "yasna", @@ -3376,7 +3465,7 @@ dependencies = [ "multihash", "quickcheck", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "serde", "stun 0.6.0", "thiserror", @@ -3444,13 +3533,13 @@ dependencies = [ "libp2p-tcp", "parking_lot", "pin-project-lite", - "rcgen", + "rcgen 0.11.3", "rw-stream-sink", "soketto", "thiserror", "tracing", "url", - "webpki-roots 0.25.2", + "webpki-roots 0.25.4", ] [[package]] @@ -3472,6 +3561,28 @@ dependencies = [ "web-sys", ] +[[package]] +name = "libp2p-webtransport" +version = "0.1.0" +dependencies = [ + "async-std", + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "libp2p-tls", + "quinn", + "rustls 0.23.14", + "sha2 0.10.8", + "thiserror", + "time", + "tokio", + "tracing", + "wtransport", +] + [[package]] name = "libp2p-webtransport-websys" version = "0.4.0" @@ -3507,6 +3618,16 @@ dependencies = [ "yamux 0.13.3", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -3569,15 +3690,15 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -3585,20 +3706,20 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "value-bag", ] [[package]] name = "lru" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.15.0", ] [[package]] @@ -3627,24 +3748,25 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67827e6ea8ee8a7c4a72227ef4fc08957040acffdb5f122733b24fa12daff41b" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "md-5" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -3655,23 +3777,14 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "memory-stats" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f79cf9964c5c9545493acda1263f1912f8d2c56c8a2ffee2606cb960acaacc" +checksum = "c73f5c649995a115e1a0220b35e4df0a1294500477f97a91d0660fb5abeb574a" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -3699,9 +3812,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3725,11 +3838,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -3745,9 +3858,9 @@ dependencies = [ [[package]] name = "multiaddr" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b852bc02a2da5feed68cd14fa50d0774b92790a5bdbfa932a813926c8472070" +checksum = "fe6351f60b488e04c1d21bc69e56b89cb3f5e8f5d22557d6e8031bdfd79b6961" dependencies = [ "arrayref", "byteorder", @@ -3758,7 +3871,7 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint 0.7.2", + "unsigned-varint 0.8.0", "url", ] @@ -3807,11 +3920,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -3878,9 +3990,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" dependencies = [ "async-io 1.13.0", "bytes", @@ -3910,7 +4022,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.7.1", + "memoffset", "pin-utils", ] @@ -3951,11 +4063,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -3968,11 +4079,10 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] @@ -3991,19 +4101,25 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.31.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] +[[package]] +name = "octets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109983a091271ee8916076731ba5fdc9ee22fea871bc7c6ceab9bfd423eb1d99" + [[package]] name = "oid-registry" version = "0.6.1" @@ -4015,30 +4131,30 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" dependencies = [ - "asn1-rs 0.6.1", + "asn1-rs 0.6.2", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" @@ -4046,7 +4162,7 @@ version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -4063,7 +4179,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -4092,7 +4208,7 @@ checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ "futures-core", "futures-sink", - "indexmap 2.2.1", + "indexmap 2.6.0", "js-sys", "once_cell", "pin-project-lite", @@ -4183,7 +4299,7 @@ dependencies = [ "glob", "once_cell", "opentelemetry 0.21.0", - "ordered-float 4.2.0", + "ordered-float 4.3.0", "percent-encoding", "rand 0.8.5", "thiserror", @@ -4212,6 +4328,12 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "2.10.1" @@ -4223,9 +4345,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +checksum = "44d501f1a72f71d3c063a6bbc8f7271fa73aa09fe5d6283b6571e2ed176a2537" dependencies = [ "num-traits", ] @@ -4262,9 +4384,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -4278,30 +4400,30 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "serde", ] @@ -4322,22 +4444,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -4363,6 +4485,17 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand 2.1.1", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -4375,15 +4508,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -4394,15 +4527,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -4425,16 +4558,17 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.0" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.37", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4450,9 +4584,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -4462,9 +4596,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -4474,33 +4608,36 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "primeorder" -version = "0.13.2" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", @@ -4516,7 +4653,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -4536,10 +4673,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -4592,19 +4729,20 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-std", "bytes", "futures-io", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 1.1.0", - "rustls 0.23.11", + "rustc-hash", + "rustls 0.23.14", + "socket2 0.5.7", "thiserror", "tokio", "tracing", @@ -4619,8 +4757,8 @@ dependencies = [ "bytes", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.0.0", - "rustls 0.23.11", + "rustc-hash", + "rustls 0.23.14", "slab", "thiserror", "tinyvec", @@ -4629,22 +4767,22 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7ad7bc932e4968523fa7d9c320ee135ff779de720e9350fee8728838551764" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ "libc", "once_cell", "socket2 0.5.7", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -4753,6 +4891,19 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" +dependencies = [ + "pem", + "ring 0.17.8", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redis" version = "0.24.0" @@ -4774,43 +4925,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -4824,13 +4966,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -4841,9 +4983,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "relay-server-example" @@ -4870,9 +5012,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -4895,14 +5037,15 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", + "quinn", + "rustls 0.23.14", "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", "tokio-rustls", @@ -4911,8 +5054,8 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.1", - "winreg 0.52.0", + "webpki-roots 0.26.6", + "windows-registry", ] [[package]] @@ -4998,9 +5141,9 @@ dependencies = [ [[package]] name = "rtcp" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3677908cadfbecb4cc1da9a56a32524fae4ebdfa7c2ea93886e1b1e846488cb9" +checksum = "33648a781874466a62d89e265fee9f17e32bc7d05a256e6cca41bf97eadcd8aa" dependencies = [ "bytes", "thiserror", @@ -5036,11 +5179,24 @@ dependencies = [ "webrtc-util 0.8.1", ] +[[package]] +name = "rtp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47fca9bd66ae0b1f3f649b8f5003d6176433d7293b78b0fce7e1031816bdd99d" +dependencies = [ + "bytes", + "rand 0.8.5", + "serde", + "thiserror", + "webrtc-util 0.8.1", +] + [[package]] name = "rust-embed" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -5049,23 +5205,23 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.66", + "syn 2.0.79", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ "globset", "sha2 0.10.8", @@ -5074,15 +5230,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -5092,9 +5242,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -5110,9 +5260,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.25" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -5124,22 +5274,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.12", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -5149,47 +5299,45 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ - "log", + "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] -name = "rustls" -version = "0.23.11" +name = "rustls-native-certs" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ - "once_cell", - "ring 0.17.8", + "openssl-probe", + "rustls-pemfile", "rustls-pki-types", - "rustls-webpki 0.102.5", - "subtle", - "zeroize", + "schannel", + "security-framework", ] [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -5203,9 +5351,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -5214,9 +5362,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rw-stream-sink" @@ -5230,9 +5378,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "salsa20" @@ -5254,11 +5402,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -5275,19 +5423,19 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] name = "sdp" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4653054c30ebce63658762eb0d64e27673868a95564474811ae6c220cf767640" +checksum = "13254db766b17451aced321e7397ebf0a446ef0c8d2942b6e67a95815421093f" dependencies = [ "rand 0.8.5", "substring", @@ -5311,11 +5459,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -5324,9 +5472,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -5334,9 +5482,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "send_wrapper" @@ -5370,26 +5518,27 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.6.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -5403,14 +5552,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -5429,9 +5578,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -5474,9 +5623,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -5491,29 +5640,25 @@ dependencies = [ ] [[package]] -name = "signal-hook" -version = "0.3.17" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -5521,9 +5666,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -5540,22 +5685,22 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-fs", "async-io 1.13.0", - "async-lock 2.7.0", + "async-lock 2.8.0", "async-net", - "async-process", + "async-process 1.8.1", "blocking", "futures-lite 1.13.0", ] [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -5579,9 +5724,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -5626,9 +5771,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -5665,30 +5810,30 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -5740,9 +5885,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -5757,9 +5902,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -5774,9 +5919,12 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384595c11a4e2969895cad5a8c4029115f5ab956a9e5ef4de79d11a426e5f20c" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -5798,14 +5946,14 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "sysinfo" -version = "0.30.12" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" dependencies = [ "cfg-if", "core-foundation-sys", @@ -5824,7 +5972,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -5837,23 +5996,34 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" -version = "3.10.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "rustix 0.38.31", - "windows-sys 0.52.0", + "fastrand 2.1.1", + "once_cell", + "rustix 0.38.37", + "windows-sys 0.59.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -5868,7 +6038,7 @@ dependencies = [ "base64 0.22.1", "futures", "http 1.1.0", - "indexmap 2.2.1", + "indexmap 2.6.0", "parking_lot", "paste", "reqwest", @@ -5892,34 +6062,34 @@ checksum = "b72d056365e368fc57a56d0cec9e41b02fb4a3474a61c8735262b1cfebe67425" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -5990,9 +6160,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -6005,9 +6175,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" dependencies = [ "backtrace", "bytes", @@ -6030,7 +6200,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -6045,11 +6215,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.22.4", + "rustls 0.23.14", "rustls-pki-types", "tokio", ] @@ -6067,9 +6237,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -6081,9 +6251,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -6093,20 +6263,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -6137,7 +6307,7 @@ dependencies = [ "socket2 0.5.7", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -6163,13 +6333,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-http" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "bytes", "futures-util", "http 1.1.0", @@ -6190,15 +6376,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -6220,7 +6406,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -6311,15 +6497,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.96" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a5f13f11071020bb12de7a16b925d2d58636175c20c11dc5f96cb64bb6c9b3" +checksum = "8923cde76a6329058a86f04d033f0945a2c6df8b94093512e4ab188b3e3a8950" dependencies = [ "glob", "serde", @@ -6331,9 +6517,9 @@ dependencies = [ [[package]] name = "turn" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f4fcb97da0426e8146fe0e9b78cc13120161087256198701d12d9df77f7701" +checksum = "ffb2ac4f331064513ad510b7a36edc0df555bd61672986607f7c9ff46f98f415" dependencies = [ "async-trait", "base64 0.21.7", @@ -6341,18 +6527,19 @@ dependencies = [ "log", "md-5", "rand 0.8.5", - "ring 0.16.20", + "ring 0.17.8", "stun 0.5.1", "thiserror", "tokio", + "tokio-util", "webrtc-util 0.8.1", ] [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -6368,39 +6555,39 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -6469,15 +6656,15 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.4.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom 0.2.15", ] @@ -6490,9 +6677,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "vcpkg" @@ -6502,9 +6689,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -6523,15 +6710,15 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -6560,9 +6747,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -6571,24 +6758,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -6598,9 +6785,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6608,28 +6795,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-bindgen-test" -version = "0.3.43" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9" +checksum = "d381749acb0943d357dcbd8f0b100640679883fcdeeef04def49daf8d33a5426" dependencies = [ "console_error_panic_hook", "js-sys", @@ -6642,13 +6829,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.43" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" +checksum = "c97b2ef2c8d627381e51c071c2ab328eac606d3f69dd82bcbca20a9e389d95f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -6664,9 +6851,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -6694,15 +6881,15 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -6723,12 +6910,12 @@ dependencies = [ "log", "pem", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "regex", "ring 0.16.20", "rtcp", - "rtp", - "rustls 0.21.11", + "rtp 0.9.0", + "rustls 0.21.12", "sdp", "serde", "serde_json", @@ -6753,9 +6940,9 @@ dependencies = [ [[package]] name = "webrtc-data" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45d2461d0e0bf93f181e30eb0b40df32b8bf3efb89c53cebb1990e603e2067d" +checksum = "e8c08e648e10572b9edbe741074e0f4d3cb221aa7cdf9a814ee71606de312f33" dependencies = [ "bytes", "log", @@ -6787,9 +6974,9 @@ dependencies = [ "pem", "rand 0.8.5", "rand_core 0.6.4", - "rcgen", + "rcgen 0.11.3", "ring 0.16.20", - "rustls 0.21.11", + "rustls 0.21.12", "sec1", "serde", "sha1", @@ -6804,9 +6991,9 @@ dependencies = [ [[package]] name = "webrtc-ice" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66eb4b85646f1c52225779db3e1e7e873dede6db68cc9be080b648f1713083a3" +checksum = "a1bbd6b3dea22cc6e961e22b012e843d8869e2ac8e76b96e54d4a25e311857ad" dependencies = [ "arc-swap", "async-trait", @@ -6828,9 +7015,9 @@ dependencies = [ [[package]] name = "webrtc-mdns" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bebbd40e7f8b630a0f1a74783dbfff1edfc0ccaae891c4689891156a8c4d8c" +checksum = "ce981f93104a8debb3563bb0cedfe4aa2f351fdf6b53f346ab50009424125c08" dependencies = [ "log", "socket2 0.5.7", @@ -6841,22 +7028,22 @@ dependencies = [ [[package]] name = "webrtc-media" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfde3c7b9450b67d466bb2f02c6d9ff9514d33535eb9994942afd1f828839d1" +checksum = "280017b6b9625ef7329146332518b339c3cceff231cc6f6a9e0e6acab25ca4af" dependencies = [ "byteorder", "bytes", "rand 0.8.5", - "rtp", + "rtp 0.10.0", "thiserror", ] [[package]] name = "webrtc-sctp" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1af6116b7f9703560c3ad0b32f67220b171bb1b59633b03563db8404d0e482ea" +checksum = "df75ec042002fe995194712cbeb2029107a60a7eab646f1b789eb1be94d0e367" dependencies = [ "arc-swap", "async-trait", @@ -6884,7 +7071,7 @@ dependencies = [ "hmac 0.12.1", "log", "rtcp", - "rtp", + "rtp 0.9.0", "sha1", "subtle", "thiserror", @@ -6953,9 +7140,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -6975,11 +7162,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -7005,7 +7192,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -7023,7 +7210,37 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -7041,7 +7258,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -7061,17 +7287,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -7082,9 +7309,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -7094,9 +7321,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -7106,9 +7333,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -7118,9 +7351,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -7130,9 +7363,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -7142,9 +7375,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -7154,15 +7387,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -7178,13 +7411,40 @@ dependencies = [ ] [[package]] -name = "winreg" -version = "0.52.0" +name = "wtransport" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "6db854cf8d3a1089a8a4e283dace6afc3746d4e570e82392779a53c943cf7aa4" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "bytes", + "pem", + "quinn", + "rcgen 0.13.1", + "rustls 0.23.14", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "sha2 0.10.8", + "socket2 0.5.7", + "thiserror", + "time", + "tokio", + "tracing", + "url", + "wtransport-proto", + "x509-parser 0.16.0", +] + +[[package]] +name = "wtransport-proto" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28b252f224a6467fb0dfc38be040bc1dde17ba5bae43120c536225ff6f4f60b" +dependencies = [ + "httlib-huffman", + "octets", + "thiserror", + "url", ] [[package]] @@ -7223,12 +7483,12 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" dependencies = [ - "asn1-rs 0.6.1", + "asn1-rs 0.6.2", "data-encoding", "der-parser 9.0.0", "lazy_static", "nom", - "oid-registry 0.7.0", + "oid-registry 0.7.1", "rusticata-macros", "thiserror", "time", @@ -7236,9 +7496,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.17" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eee6bf5926be7cf998d7381a9a23d833fd493f6a8034658a9505a4dc4b20444" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "xmltree" @@ -7291,22 +7551,23 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] [[package]] @@ -7326,5 +7587,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index 9e18af5f706..5a58676849e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ members = [ "transports/websocket-websys", "transports/websocket", "transports/webtransport-websys", + "transports/webtransport", "wasm-tests/webtransport-tests", ] resolver = "2" diff --git a/transports/tls/Cargo.toml b/transports/tls/Cargo.toml index c27e14bb537..12d95fb8a61 100644 --- a/transports/tls/Cargo.toml +++ b/transports/tls/Cargo.toml @@ -19,6 +19,7 @@ thiserror = "1.0.61" webpki = { version = "0.101.4", package = "rustls-webpki", features = ["std"] } x509-parser = "0.16.0" yasna = "0.5.2" +time = "0.3" # Exposed dependencies. Breaking changes to these are breaking changes to us. [dependencies.rustls] diff --git a/transports/tls/src/certificate.rs b/transports/tls/src/certificate.rs index 65b373bcf9b..1af747c86ca 100644 --- a/transports/tls/src/certificate.rs +++ b/transports/tls/src/certificate.rs @@ -27,6 +27,7 @@ use libp2p_identity::PeerId; use x509_parser::{prelude::*, signature_algorithm::SignatureAlgorithm}; use std::sync::Arc; +use ::time::OffsetDateTime; /// The libp2p Public Key Extension is a X.509 extension /// with the Object Identifier 1.3.6.1.4.1.53594.1.1, @@ -121,6 +122,47 @@ pub fn generate( Ok((rustls_certificate, rustls_key)) } +pub fn generate_with_validity_period( + identity_keypair: &identity::Keypair, + not_before: OffsetDateTime, + not_after: OffsetDateTime, +) -> Result< + ( + rustls::pki_types::CertificateDer<'static>, + rustls::pki_types::PrivateKeyDer<'static>, + ), + GenError, +> { + // Keypair used to sign the certificate. + // SHOULD NOT be related to the host's key. + // Endpoints MAY generate a new key and certificate + // for every connection attempt, or they MAY reuse the same key + // and certificate for multiple connections. + let certificate_keypair = rcgen::KeyPair::generate(P2P_SIGNATURE_ALGORITHM)?; + let rustls_key = rustls::pki_types::PrivateKeyDer::from( + rustls::pki_types::PrivatePkcs8KeyDer::from(certificate_keypair.serialize_der()), + ); + + let certificate = { + let mut params = rcgen::CertificateParams::new(vec![]); + params.distinguished_name = rcgen::DistinguishedName::new(); + params.custom_extensions.push(make_libp2p_extension( + identity_keypair, + &certificate_keypair, + )?); + params.alg = P2P_SIGNATURE_ALGORITHM; + params.key_pair = Some(certificate_keypair); + params.not_before = not_before; + params.not_after = not_after; + rcgen::Certificate::from_params(params)? + }; + + let rustls_certificate = rustls::pki_types::CertificateDer::from(certificate.serialize_der()?); + + Ok((rustls_certificate, rustls_key)) +} + + /// Attempts to parse the provided bytes as a [`P2pCertificate`]. /// /// For this to succeed, the certificate must contain the specified extension and the signature must @@ -128,7 +170,17 @@ pub fn generate( pub fn parse<'a>( certificate: &'a rustls::pki_types::CertificateDer<'a>, ) -> Result, ParseError> { - let certificate = parse_unverified(certificate.as_ref())?; + parse_binary(certificate.as_ref()) +} + +/// Attempts to parse the provided bytes as a [`P2pCertificate`]. +/// +/// For this to succeed, the certificate must contain the specified extension and the signature must +/// match the embedded public key. +pub fn parse_binary( + der_input: &[u8], +) -> Result { + let certificate = parse_unverified(der_input)?; certificate.verify()?; diff --git a/transports/tls/src/lib.rs b/transports/tls/src/lib.rs index 3aa66db12b3..28fc12e76e9 100644 --- a/transports/tls/src/lib.rs +++ b/transports/tls/src/lib.rs @@ -34,6 +34,8 @@ use libp2p_identity::Keypair; use libp2p_identity::PeerId; use std::sync::Arc; +use rustls::pki_types::{CertificateDer, PrivateKeyDer}; + pub use futures_rustls::TlsStream; pub use upgrade::Config; pub use upgrade::UpgradeError; @@ -91,3 +93,27 @@ pub fn make_server_config( Ok(crypto) } + +/// Create a TLS server configuration for libp2p. +pub fn make_webtransport_server_config( + certificate: &CertificateDer<'static>, + private_key: &PrivateKeyDer, + protocols: Vec>, +) -> Result { + let mut provider = rustls::crypto::ring::default_provider(); + provider.cipher_suites = verifier::CIPHERSUITES.to_vec(); + + let cert_resolver = Arc::new( + AlwaysResolvesCert::new(certificate.clone(), private_key) + .expect("Server cert key DER is valid; qed"), + ); + + let mut crypto = rustls::ServerConfig::builder_with_provider(provider.into()) + .with_protocol_versions(verifier::PROTOCOL_VERSIONS) + .expect("Cipher suites and kx groups are configured; qed") + .with_client_cert_verifier(Arc::new(verifier::Libp2pCertificateVerifier::new())) + .with_cert_resolver(cert_resolver); + crypto.alpn_protocols = protocols.to_vec(); + + Ok(crypto) +} \ No newline at end of file diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml new file mode 100644 index 00000000000..fd0d22ffcde --- /dev/null +++ b/transports/webtransport/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "libp2p-webtransport" +version = "0.1.0" +edition = "2021" +rust-version.workspace = true +description = "TLS based QUIC transport implementation for libp2p" +repository = "https://github.com/libp2p/rust-libp2p" +license = "MIT" + +[dependencies] +libp2p-core = { workspace = true } +libp2p-tls = { workspace = true } +libp2p-identity = { workspace = true } +libp2p-noise = { workspace = true } +async-std = { version = "1.12.0", optional = true } +tokio = { workspace = true, default-features = false, features = ["net", "rt", "time"], optional = true } +futures = { workspace = true } +tracing = { workspace = true } +if-watch = "3.2.0" +futures-timer = "3.0.3" +rustls = { version = "0.23.9", default-features = false } +thiserror = "1.0.61" +time = "0.3.36" +sha2 = "0.10.8" +quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } +wtransport = "0.4.0" + +[features] +tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] +async-std = ["dep:async-std", "if-watch/smol", "quinn/runtime-async-std"] + +[lints] +workspace = true diff --git a/transports/webtransport/src/certificate.rs b/transports/webtransport/src/certificate.rs new file mode 100644 index 00000000000..4a2baa0e80f --- /dev/null +++ b/transports/webtransport/src/certificate.rs @@ -0,0 +1,169 @@ +use std::io; +use std::io::{Cursor, Read, Write}; + +use rustls::pki_types::{CertificateDer, PrivateKeyDer}; +use sha2::Digest; +use time::{Duration, OffsetDateTime}; + +use libp2p_core::multihash::Multihash; +use libp2p_tls::certificate; + +const MULTIHASH_SHA256_CODE: u64 = 0x12; +const CERT_VALID_PERIOD: Duration = Duration::days(14); + +pub type CertHash = Multihash<64>; + +/* +I would like to avoid interacting with the file system as much as possible. +My suggestion would be: +- libp2p::webtransport::Transport::new takes a list of certificates (of type libp2p::webtransport::Certificate) +- libp2p::webtransport::Certificate::generate allows users generate a new certificate with certain parameters (validity date etc) +- libp2p::webtransport::Certificate::{parse,to_bytes} allow users to serialize and deserialize certificates +*/ +#[derive(Debug, PartialEq, Eq)] +pub struct Certificate { + pub cert: CertificateDer<'static>, + pub private_key: PrivateKeyDer<'static>, + pub not_before: OffsetDateTime, + pub not_after: OffsetDateTime, +} + +#[derive(Debug)] +pub enum Error { + GenError(certificate::GenError), + IoError(io::Error), +} + +impl From for Error { + fn from(value: certificate::GenError) -> Self { + Self::GenError(value) + } +} + +impl From for Error { + fn from(value: io::Error) -> Self { + Self::IoError(value) + } +} + +impl Clone for Certificate { + fn clone(&self) -> Self { + Self { + cert: self.cert.clone(), + private_key: self.private_key.clone_key(), + not_before: self.not_before.clone(), + not_after: self.not_after.clone(), + } + } +} + +impl Certificate { + pub fn generate( + identity_keypair: &libp2p_identity::Keypair, + not_before: OffsetDateTime, + ) -> Result { + let not_after = not_before + .clone() + .checked_add(CERT_VALID_PERIOD) + .expect("Addition does not overflow"); + let (cert, private_key) = certificate::generate_with_validity_period( + identity_keypair, + not_before.clone(), + not_after.clone(), + )?; + + Ok(Self { + cert, + private_key, + not_before, + not_after, + }) + } + + pub(crate) fn cert_hash(&self) -> Multihash<64> { + Multihash::wrap( + MULTIHASH_SHA256_CODE, + sha2::Sha256::digest(&self.cert.as_ref().as_ref()).as_ref(), + ) + .expect("fingerprint's len to be 32 bytes") + } + + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + + Self::write_data(&mut bytes, self.cert.as_ref()).expect("Write cert data"); + Self::write_data(&mut bytes, self.private_key.secret_der()) + .expect("Write private_key data"); + + let nb_buff = self.not_before.unix_timestamp().to_be_bytes(); + std::io::Write::write(&mut bytes, &nb_buff).expect("Write not_before"); + + let na_buff = self.not_after.unix_timestamp().to_be_bytes(); + std::io::Write::write(&mut bytes, &na_buff).expect("Write not_after"); + + bytes + } + + pub fn parse(data: &[u8]) -> Result { + let mut cursor = Cursor::new(data); + let cert_data = Self::read_data(&mut cursor)?; + let private_key_data = Self::read_data(&mut cursor)?; + let nb = Self::read_i64(&mut cursor).unwrap(); + let na = Self::read_i64(&mut cursor).unwrap(); + + let cert = CertificateDer::from(cert_data); + let private_key = PrivateKeyDer::try_from(private_key_data).unwrap(); + let not_before = OffsetDateTime::from_unix_timestamp(nb).unwrap(); + let not_after = OffsetDateTime::from_unix_timestamp(na).unwrap(); + + Ok(Self { + cert, + private_key, + not_before, + not_after, + }) + } + + fn write_data(w: &mut W, data: &[u8]) -> Result<(), io::Error> { + let size = data.len() as u64; + let mut size_buf = size.to_be_bytes(); + + w.write_all(&mut size_buf)?; + w.write_all(data)?; + + Ok(()) + } + + fn read_data(r: &mut R) -> Result, io::Error> { + let size = Self::read_i64(r)? as usize; + let mut res = vec![0u8; size]; + + r.read(res.as_mut_slice())?; + + Ok(res) + } + + fn read_i64(r: &mut R) -> Result { + let mut buffer = [0u8; 8]; + r.read(&mut buffer)?; + + Ok(i64::from_be_bytes(buffer)) + } +} + +#[cfg(test)] +mod tests { + use time::macros::datetime; + + #[test] + fn test_certificate_parsing() { + let keypair = libp2p_identity::Keypair::generate_ed25519(); + let not_before = datetime!(2025-08-08 0:00 UTC); + let cert = super::Certificate::generate(&keypair, not_before).unwrap(); + + let binary_data = cert.to_bytes(); + let actual = super::Certificate::parse(binary_data.as_slice()).unwrap(); + + assert_eq!(actual, cert); + } +} \ No newline at end of file diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs new file mode 100644 index 00000000000..03a3e28b37b --- /dev/null +++ b/transports/webtransport/src/config.rs @@ -0,0 +1,77 @@ +use std::time::Duration; + +use wtransport::config::TlsServerConfig; + +use crate::certificate::{CertHash, Certificate}; + +#[derive(Clone)] +pub struct Config { + /// Timeout for the initial handshake when establishing a connection. + /// The actual timeout is the minimum of this and the [`Config::max_idle_timeout`]. + pub handshake_timeout: Duration, + + /// Maximum duration of inactivity in ms to accept before timing out the connection. + pub max_idle_timeout: u32, + + /// Maximum number of incoming bidirectional streams that may be open + /// concurrently by the remote peer. + pub max_concurrent_stream_limit: u32, + + /// Max unacknowledged data in bytes that may be sent on a single stream. + pub max_stream_data: u32, + + /// Max unacknowledged data in bytes that may be sent in total on all streams + /// of a connection. + pub max_connection_data: u32, + + /// Period of inactivity before sending a keep-alive packet. + /// Must be set lower than the idle_timeout of both + /// peers to be effective. + /// + /// See [`quinn::TransportConfig::keep_alive_interval`] for more + /// info. + pub keep_alive_interval: Duration, + + pub server_tls_config: TlsServerConfig, + /// Libp2p identity of the node. + pub keypair: libp2p_identity::Keypair, + + cert_hash: CertHash, +} + +impl Config { + pub fn new(keypair: &libp2p_identity::Keypair, cert: Certificate) -> Self { + let server_config: rustls::ServerConfig = libp2p_tls::make_webtransport_server_config( + &cert.cert, &cert.private_key, alpn_protocols(), + ).expect("A server config"); + + Self { + server_tls_config: server_config, + handshake_timeout: Duration::from_secs(5), + max_idle_timeout: 10 * 1000, + max_concurrent_stream_limit: 256, + keep_alive_interval: Duration::from_secs(5), + max_connection_data: 15_000_000, + // Ensure that one stream is not consuming the whole connection. + max_stream_data: 10_000_000, + keypair: keypair.clone(), + cert_hash: cert.cert_hash(), + } + } + + pub fn cert_hashes(&self) -> Vec { + vec![self.cert_hash.clone()] + } +} + + +fn alpn_protocols() -> Vec> { + vec![ + b"libp2p".to_vec(), + b"h3".to_vec(), + b"h3-32".to_vec(), + b"h3-31".to_vec(), + b"h3-30".to_vec(), + b"h3-29".to_vec(), + ] +} \ No newline at end of file diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs new file mode 100644 index 00000000000..66a9be68ab4 --- /dev/null +++ b/transports/webtransport/src/connection.rs @@ -0,0 +1,83 @@ +use std::pin::Pin; +use std::task::{Context, Poll}; + +use futures::future::BoxFuture; +use futures::FutureExt; +use wtransport::{error::ConnectionError, RecvStream, SendStream}; + +pub use connecting::Connecting; +use libp2p_core::muxing::StreamMuxerEvent; +use libp2p_core::StreamMuxer; +use libp2p_identity::PeerId; + +pub(crate) use crate::connection::stream::Stream; +use crate::Error; + +mod connecting; +mod stream; + +pub struct Connection { + /// Underlying connection. + connection: wtransport::Connection, + /// Future for accepting a new incoming bidirectional stream. + incoming: Option>>, + /// Future to wait for the connection to be closed. + closing: Option>, +} + +impl Connection { + fn new(connection: wtransport::Connection) -> Self { + Self { + connection, + incoming: None, + closing: None, + } + } + + + /// Returns the address of the node we're connected to. + /// Panics if the connection is still handshaking. + fn remote_peer_id(&self) -> PeerId { + let cert = self.connection + .peer_identity() + .expect("connection got identity because it passed TLS handshake; qed") + .as_slice().first().expect("there should be exactly one certificate; qed"); + + let p2p_cert = libp2p_tls::certificate::parse_binary(cert.der()) + .expect("the certificate was validated during TLS handshake; qed"); + + p2p_cert.peer_id() + } +} + +impl StreamMuxer for Connection { + type Substream = Stream; + type Error = Error; + + fn poll_inbound(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.get_mut(); + + let incoming = this.incoming.get_or_insert_with(|| { + let connection = this.connection.clone(); + async move { connection.accept_bi().await }.boxed() + }); + + let (send, recv) = futures::ready!(incoming.poll_unpin(cx))?; + // .map_err(ConnectionError)?; + this.incoming.take(); + let stream = Stream::new(send, recv); + Poll::Ready(Ok(stream)) + } + + fn poll_outbound(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } +} \ No newline at end of file diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs new file mode 100644 index 00000000000..5be4863e86b --- /dev/null +++ b/transports/webtransport/src/connection/connecting.rs @@ -0,0 +1,98 @@ +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::time::Duration; + +use futures::future::{BoxFuture, Either, Select, select}; +use futures::FutureExt; +use futures_timer::Delay; +use wtransport::endpoint::IncomingSession; + +use libp2p_core::StreamMuxer; +use libp2p_core::upgrade::InboundConnectionUpgrade; +use libp2p_identity::PeerId; + +use crate::{Connection, Error}; + +pub(crate) const WEBTRANSPORT_PATH: &str = "/.well-known/libp2p-webtransport?type=noise"; + +/// A Webtransport connection currently being negotiated. +pub struct Connecting { + noise_config: libp2p_noise::Config, + // certhashes: Vec, + connecting: Select>, Delay>, +} + +impl Connecting { + pub fn new(incoming_session: IncomingSession, + noise_config: libp2p_noise::Config, + timeout: Duration, + // certhashes: Vec, + ) -> Self { + Connecting { + noise_config, + // certhashes, + connecting: select( + Self::handshake(incoming_session).boxed(), + Delay::new(timeout), + ), + } + } + + async fn handshake(incoming_session: IncomingSession) -> Result<(PeerId, Connection), Error> { + match incoming_session.await { + Ok(session_request) => { + let path = session_request.path(); + if path != WEBTRANSPORT_PATH { + return Err( + Error::UnexpectedPath(String::from(path)) + ); + } + + match session_request.accept().await { + Ok(wtransport_connection) => { + let connection = Connection::new(wtransport_connection); + Ok((connection.remote_peer_id(), connection)) + } + Err(connection_error) => { + Err(Error::Connection(connection_error)) + } + } + } + Err(connection_error) => { + Err(Error::Connection(connection_error)) + } + } + } +} + +impl Future for Connecting { + type Output = Result<(PeerId, Connection), Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let (peer_id, connection) = match futures::ready!(self.connecting.poll_unpin(cx)) { + Either::Right(_) => return Poll::Ready(Err(Error::HandshakeTimedOut)), + Either::Left((res, _)) => res?, + }; + + /*let session = WebTransportSession::accept(request, stream, h3_conn).await?; + let arc_session = Arc::new(session); + let webtr_stream = + webtransport::accept_webtransport_stream(&arc_session).await?; + + let certs = certhashes.iter().cloned().collect::>(); + let t_noise = noise_config.with_webtransport_certhashes(certs); + t_noise.upgrade_inbound(webtr_stream, "").await?; + + let muxer = webtransport::Connection::new(arc_session, connection); + + return Ok((peer_id, StreamMuxerBox::new(muxer)));*/ + + // futures::ready!(incoming.poll_unpin(cx)) + // t_noise.upgrade_inbound().await?; + + // todo здесь же нужно будет делать нойз хэндшейк + + Poll::Ready(Ok((peer_id, connection))) + } +} \ No newline at end of file diff --git a/transports/webtransport/src/connection/stream.rs b/transports/webtransport/src/connection/stream.rs new file mode 100644 index 00000000000..85fed6cac18 --- /dev/null +++ b/transports/webtransport/src/connection/stream.rs @@ -0,0 +1,72 @@ +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; +use futures::{AsyncRead, AsyncWrite}; +use wtransport::{SendStream, RecvStream}; + +/// A single stream on a connection +pub(crate) struct Stream { + /// A send part of the stream + send: SendStream, + /// A reception part of the stream + recv: RecvStream, + /// Whether the stream is closed or not + close_result: Option>, +} + +impl Stream { + pub(super) fn new(send: SendStream, recv: RecvStream) -> Self { + Self { + send, + recv, + close_result: None, + } + } +} + +impl AsyncRead for Stream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + if let Some(close_result) = self.close_result { + if close_result.is_err() { + return Poll::Ready(Ok(0)); + } + } + let mut read_buf = tokio::io::ReadBuf::new(buf); + let res = tokio::io::AsyncRead::poll_read(Pin::new(&mut self.recv), cx, &mut read_buf); + match res { + Poll::Ready(Ok(_)) => { + Poll::Ready(Ok(read_buf.filled().len())) + } + Poll::Ready(Err(e)) => { + Poll::Ready(Err(e)) + } + Poll::Pending => { + Poll::Pending + } + } + } +} + +impl AsyncWrite for Stream { + fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + tokio::io::AsyncWrite::poll_write(Pin::new(&mut self.send), cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(Pin::new(&mut self.send), cx) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if let Some(close_result) = self.close_result { + // For some reason poll_close needs to be 'fuse'able + return Poll::Ready(close_result.map_err(Into::into)); + } + let close_result = futures::ready!(tokio::io::AsyncWrite::poll_shutdown(Pin::new(&mut self.send), cx)); + self.close_result = Some(close_result.as_ref().map_err(|e| e.kind()).copied()); + Poll::Ready(close_result) + } +} \ No newline at end of file diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs new file mode 100644 index 00000000000..6e023c79505 --- /dev/null +++ b/transports/webtransport/src/lib.rs @@ -0,0 +1,40 @@ +mod provider; +mod transport; +mod connection; +mod config; +mod certificate; + +use wtransport::error::ConnectionError; + +pub use provider::Provider; +pub use transport::GenTransport; +pub use connection::{Connecting, Connection}; +pub use certificate::CertHash; +use libp2p_core::transport::TransportError; +// pub(crate) use connection::Stream; + +/// Errors that may happen on the [`GenTransport`] or a single [`Connection`]. +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Error after the remote has been reached. + #[error(transparent)] + Connection(#[from] ConnectionError), + + /// I/O Error on a socket. + #[error(transparent)] + Io(#[from] std::io::Error), + + /// The [`Connecting`] future timed out. + #[error("Unexpected HTTP endpoint of a libp2p WebTransport server {0}")] + UnexpectedPath(String), + + /// The [`Connecting`] future timed out. + #[error("Handshake with the remote timed out.")] + HandshakeTimedOut, +} + +impl From for TransportError { + fn from(value: Error) -> Self { + TransportError::Other(value) + } +} \ No newline at end of file diff --git a/transports/webtransport/src/provider.rs b/transports/webtransport/src/provider.rs new file mode 100644 index 00000000000..6f1122ee55f --- /dev/null +++ b/transports/webtransport/src/provider.rs @@ -0,0 +1,68 @@ +// Copyright 2022 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use futures::future::BoxFuture; +use if_watch::IfEvent; +use std::{ + io, + net::{SocketAddr, UdpSocket}, + task::{Context, Poll}, + time::Duration, +}; + +#[cfg(feature = "async-std")] +pub mod async_std; +#[cfg(feature = "tokio")] +pub mod tokio; + +pub enum Runtime { + #[cfg(feature = "tokio")] + Tokio, + #[cfg(feature = "async-std")] + AsyncStd, + Dummy, +} + +/// Provider for a corresponding quinn runtime and spawning tasks. +pub trait Provider: Unpin + Send + Sized + 'static { + type IfWatcher: Unpin + Send; + + /// Run the corresponding runtime + fn runtime() -> Runtime; + + /// Create a new [`if_watch`] watcher that reports [`IfEvent`]s for network interface changes. + fn new_if_watcher() -> io::Result; + + /// Poll for an address change event. + fn poll_if_event( + watcher: &mut Self::IfWatcher, + cx: &mut Context<'_>, + ) -> Poll>; + + /// Sleep for specified amount of time. + fn sleep(duration: Duration) -> BoxFuture<'static, ()>; + + /// Sends data on the socket to the given address. On success, returns the number of bytes written. + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: SocketAddr, + ) -> BoxFuture<'a, io::Result>; +} diff --git a/transports/webtransport/src/provider/async_std.rs b/transports/webtransport/src/provider/async_std.rs new file mode 100644 index 00000000000..a110058108c --- /dev/null +++ b/transports/webtransport/src/provider/async_std.rs @@ -0,0 +1,70 @@ +// Copyright 2022 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use futures::{future::BoxFuture, FutureExt}; +use std::{ + io, + net::UdpSocket, + task::{Context, Poll}, + time::Duration, +}; + +use crate::GenTransport; + +/// Transport with [`async-std`] runtime. +pub type Transport = GenTransport; + +/// Provider for quinn runtime and spawning tasks using [`async-std`]. +pub struct Provider; + +impl super::Provider for Provider { + type IfWatcher = if_watch::smol::IfWatcher; + + fn runtime() -> super::Runtime { + super::Runtime::AsyncStd + } + + fn new_if_watcher() -> io::Result { + if_watch::smol::IfWatcher::new() + } + + fn poll_if_event( + watcher: &mut Self::IfWatcher, + cx: &mut Context<'_>, + ) -> Poll> { + watcher.poll_if_event(cx) + } + + fn sleep(duration: Duration) -> BoxFuture<'static, ()> { + async_std::task::sleep(duration).boxed() + } + + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: std::net::SocketAddr, + ) -> BoxFuture<'a, io::Result> { + Box::pin(async move { + async_std::net::UdpSocket::from(udp_socket.try_clone()?) + .send_to(buf, target) + .await + }) + } +} diff --git a/transports/webtransport/src/provider/tokio.rs b/transports/webtransport/src/provider/tokio.rs new file mode 100644 index 00000000000..9cb148d6ef2 --- /dev/null +++ b/transports/webtransport/src/provider/tokio.rs @@ -0,0 +1,70 @@ +// Copyright 2022 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use futures::{future::BoxFuture, FutureExt}; +use std::{ + io, + net::{SocketAddr, UdpSocket}, + task::{Context, Poll}, + time::Duration, +}; + +use crate::GenTransport; + +/// Transport with [`tokio`] runtime. +pub type Transport = GenTransport; + +/// Provider for quinn runtime and spawning tasks using [`tokio`]. +pub struct Provider; + +impl super::Provider for Provider { + type IfWatcher = if_watch::tokio::IfWatcher; + + fn runtime() -> super::Runtime { + super::Runtime::Tokio + } + + fn new_if_watcher() -> io::Result { + if_watch::tokio::IfWatcher::new() + } + + fn poll_if_event( + watcher: &mut Self::IfWatcher, + cx: &mut Context<'_>, + ) -> Poll> { + watcher.poll_if_event(cx) + } + + fn sleep(duration: Duration) -> BoxFuture<'static, ()> { + tokio::time::sleep(duration).boxed() + } + + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: SocketAddr, + ) -> BoxFuture<'a, io::Result> { + Box::pin(async move { + tokio::net::UdpSocket::from_std(udp_socket.try_clone()?)? + .send_to(buf, target) + .await + }) + } +} diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs new file mode 100644 index 00000000000..06e63f425dc --- /dev/null +++ b/transports/webtransport/src/transport.rs @@ -0,0 +1,394 @@ +use std::collections::HashSet; +use std::future::Pending; +use std::net::{IpAddr, SocketAddr}; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll, Waker}; +use std::time::Duration; + +use futures::{prelude::*, stream::SelectAll}; +use futures::future::BoxFuture; +use if_watch::IfEvent; +use wtransport::config::TlsServerConfig; +use wtransport::endpoint::{endpoint_side, IncomingSession}; +use wtransport::error::ConnectionError; +use wtransport::ServerConfig; + +use libp2p_core::{Multiaddr, Transport}; +use libp2p_core::multiaddr::Protocol; +use libp2p_core::multihash::Multihash; +use libp2p_core::muxing::StreamMuxerBox; +use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; +use libp2p_identity::{Keypair, PeerId}; + +use crate::{Connecting, Provider}; +use crate::certificate::CertHash; +use crate::config::Config; +use crate::connection::Connection; +use crate::Error; + +pub struct GenTransport { + server_tls_config: TlsServerConfig, + keypair: Keypair, + cert_hashes: Vec, + + /// Timeout for the [`Connecting`] future. + handshake_timeout: Duration, + + listeners: SelectAll>, + /// Waker to poll the transport again when a new listener is added. + waker: Option, +} + +impl GenTransport

{ + pub fn new(config: Config) -> Self { + let handshake_timeout = config.handshake_timeout; + let keypair = config.keypair.clone(); + let cert_hashes = config.cert_hashes(); + let server_tls_config = config.server_tls_config; + + GenTransport { + server_tls_config, + keypair, + cert_hashes, + handshake_timeout, + listeners: SelectAll::new(), + waker: None, + } + } + + /// Extract the addr, quic version and peer id from the given [`Multiaddr`]. + fn remote_multiaddr_to_socketaddr( + &self, + addr: Multiaddr, + check_unspecified_addr: bool, + ) -> Result< + (SocketAddr, Option), + TransportError<::Error>, + > { + let (socket_addr, peer_id) = multiaddr_to_socketaddr(&addr) + .ok_or_else(|| TransportError::MultiaddrNotSupported(addr.clone()))?; + if check_unspecified_addr && (socket_addr.port() == 0 || socket_addr.ip().is_unspecified()) + { + return Err(TransportError::MultiaddrNotSupported(addr)); + } + Ok((socket_addr, peer_id)) + } +} + +impl Transport for GenTransport

{ + type Output = (PeerId, Connection); + type Error = Error; + type ListenerUpgrade = Connecting; + type Dial = Pending>; + + fn listen_on(&mut self, id: ListenerId, addr: Multiaddr) -> Result<(), TransportError> { + let (socket_addr, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; + let config = ServerConfig::builder() + .with_bind_address(socket_addr.clone()) + .with_custom_tls(self.server_tls_config.clone()) + .build(); + + let endpoint = wtransport::Endpoint::server(config) + .map_err(|e| { TransportError::Other(e.into()) })?; + let keypair = &self.keypair; + let cert_hashes = &self.cert_hashes; + let handshake_timeout = self.handshake_timeout.clone(); + + let listener = Listener::new( + id, socket_addr, Arc::new(endpoint), keypair, cert_hashes, handshake_timeout, + )?; + self.listeners.push(listener); + + if let Some(waker) = self.waker.take() { + waker.wake(); + } + + Ok(()) + } + + fn remove_listener(&mut self, id: ListenerId) -> bool { + todo!() + } + + fn dial(&mut self, _addr: Multiaddr, _opts: DialOpts) -> Result> { + panic!("Dial operation is not supported!") + } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } +} + +/// Listener for incoming connections. +struct Listener { + /// Id of the listener. + listener_id: ListenerId, + /// Endpoint + endpoint: Arc>, + /// A future to poll new incoming connections. + accept: BoxFuture<'static, IncomingSession>, + /// Timeout for connection establishment on inbound connections. + handshake_timeout: Duration, + /// Watcher for network interface changes. + /// + /// None if we are only listening on a single interface. + if_watcher: Option, + /// Whether the listener was closed and the stream should terminate. + is_closed: bool, + /// Pending event to reported. + pending_event: Option<::Item>, + /// The stream must be to awaken after it has been closed to deliver the last event. + close_listener_waker: Option, + + listening_addresses: HashSet, + + keypair: Keypair, + cert_hashes: Vec, +} + +impl Listener

{ + fn new( + listener_id: ListenerId, + socket_addr: SocketAddr, + endpoint: Arc>, + keypair: &Keypair, + cert_hashes: &Vec, + handshake_timeout: Duration, ) -> Result { + let if_watcher; + let pending_event; + let mut listening_addresses = HashSet::new(); + if socket_addr.ip().is_unspecified() { + if_watcher = Some(P::new_if_watcher()?); + pending_event = None; + } else { + if_watcher = None; + listening_addresses.insert(socket_addr.ip()); + let ma = socketaddr_to_multiaddr(&socket_addr, cert_hashes); + pending_event = Some(TransportEvent::NewAddress { + listener_id, + listen_addr: ma, + }) + } + + + let endpoint_c = Arc::clone(&endpoint); + let accept = async move { endpoint_c.accept().await }.boxed(); + + Ok( + Listener { + listener_id, + endpoint, + accept, + handshake_timeout, + if_watcher, + is_closed: false, + pending_event, + close_listener_waker: None, + listening_addresses, + keypair: keypair.clone(), + cert_hashes: cert_hashes.clone(), + } + ) + } + + fn socket_addr(&self) -> SocketAddr { + self.endpoint + .local_addr() + .expect("Cannot fail because the socket is bound") + } + + fn noise_config(&self) -> libp2p_noise::Config { + let mut res = libp2p_noise::Config::new(&self.keypair).expect("Getting a noise config"); + // let mut set = HashSet::with_capacity(self.cert_hashes.len()); + let set = self.cert_hashes.iter().cloned().collect::>(); + let res = res.with_webtransport_certhashes(set); + + res + } + + + /* todo poll_if_addr + /// Poll for a next If Event. + fn poll_if_addr(&mut self, cx: &mut Context<'_>) -> Poll<::Item> { + let endpoint_addr = self.socket_addr(); + let Some(if_watcher) = self.if_watcher.as_mut() else { + return Poll::Pending; + }; + loop { + match ready!(P::poll_if_event(if_watcher, cx)) { + Ok(IfEvent::Up(inet)) => { + if let Some(listen_addr) = + ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) + { + tracing::debug!( + address=%listen_addr, + "New listen address" + ); + self.listening_addresses.insert(inet.addr()); + return Poll::Ready(TransportEvent::NewAddress { + listener_id: self.listener_id, + listen_addr, + }); + } + } + Ok(IfEvent::Down(inet)) => { + if let Some(listen_addr) = + ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) + { + tracing::debug!( + address=%listen_addr, + "Expired listen address" + ); + self.listening_addresses.remove(&inet.addr()); + return Poll::Ready(TransportEvent::AddressExpired { + listener_id: self.listener_id, + listen_addr, + }); + } + } + Err(err) => { + return Poll::Ready(TransportEvent::ListenerError { + listener_id: self.listener_id, + error: err.into(), + }) + } + } + } + }*/ +} + +impl Stream for Listener

{ + type Item = TransportEvent< as Transport>::ListenerUpgrade, Error>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + loop { + if let Some(event) = self.pending_event.take() { + return Poll::Ready(Some(event)); + } + if self.is_closed { + return Poll::Ready(None); + } + /* todo poll_if_addr + if let Poll::Ready(event) = self.poll_if_addr(cx) { + return Poll::Ready(Some(event)); + }*/ + + match self.accept.poll_unpin(cx) { + Poll::Ready(incoming_session) => { + let endpoint = self.endpoint.clone(); + self.accept = async move { endpoint.accept().await }.boxed(); + + /*let connecting = match session_request.accept() { + Ok(connecting) => connecting, + Err(error) => { + return Poll::Ready(Some(TransportEvent::ListenerError { + listener_id: self.listener_id, + error: Error::Connection(crate::ConnectionError(error)), + })) + } + };*/ + + let local_addr = socketaddr_to_multiaddr(&self.socket_addr(), &self.cert_hashes); + let remote_addr = incoming_session.remote_address(); + //todo нафига к удаленному адресу добавлять хэши сертификатов? + let send_back_addr = socketaddr_to_multiaddr(&remote_addr, &self.cert_hashes); + let noise = self.noise_config(); + + let event = TransportEvent::Incoming { + upgrade: Connecting::new(incoming_session, noise, self.handshake_timeout), + local_addr, + send_back_addr, + listener_id: self.listener_id, + }; + return Poll::Ready(Some(event)); + } + Poll::Pending => {} + }; + + self.close_listener_waker = Some(cx.waker().clone()); + + return Poll::Pending; + } + } +} + +/// Turns an IP address and port into the corresponding WebTransport multiaddr. +fn socketaddr_to_multiaddr(socket_addr: &SocketAddr, hashes: &Vec>) -> Multiaddr { + let mut vec = hashes.clone(); + let mut res = Multiaddr::empty() + .with(socket_addr.ip().into()) + .with(Protocol::Udp(socket_addr.port())) + .with(Protocol::QuicV1) + .with(Protocol::WebTransport) + .with(Protocol::Certhash( + vec.pop().expect("Gets the last element"), + )); + if !vec.is_empty() { + res = res.with(Protocol::Certhash( + vec.pop().expect("Gets the last element"), + )); + }; + + res +} + +/// Tries to turn a Webtransport multiaddress into a UDP [`SocketAddr`]. Returns None if the format +/// of the multiaddr is wrong. +fn multiaddr_to_socketaddr( + addr: &Multiaddr, +) -> Option<(SocketAddr, Option)> { + let mut iter = addr.iter(); + let proto1 = iter.next()?; + let proto2 = iter.next()?; + let proto3 = iter.next()?; + + if proto3 != Protocol::QuicV1 { + tracing::error!("Cannot listen on a non QUIC address {addr}"); + return None; + } + + let mut peer_id = None; + let mut is_webtransport = false; + for proto in iter { + match proto { + Protocol::P2p(id) => { + peer_id = Some(id); + } + Protocol::WebTransport => { + is_webtransport = true; + } + Protocol::Certhash(_) => { + tracing::error!("Cannot listen on a specific certhash for WebTransport address {addr}"); + return None; + } + _ => return None, + } + } + + if !is_webtransport { + tracing::error!("Listening address {addr} should be followed by `/webtransport`"); + return None; + } + + match (proto1, proto2) { + (Protocol::Ip4(ip), Protocol::Udp(port)) => Some(( + SocketAddr::new(ip.into(), port), + peer_id, + )), + (Protocol::Ip6(ip), Protocol::Udp(port)) => Some(( + SocketAddr::new(ip.into(), port), + peer_id, + )), + _ => None, + } +} + +#[cfg(test)] +// #[cfg(any(feature = "async-std", feature = "tokio"))] +mod test { + #[test] + fn test() { + println!("hi!") + } +} \ No newline at end of file From 7a0a2fb07c246cfa96b01edbbedbe72b60a9f008 Mon Sep 17 00:00:00 2001 From: dgarus Date: Mon, 9 Dec 2024 13:08:39 +0300 Subject: [PATCH 02/16] removed the Provider trait --- transports/webtransport/Cargo.toml | 10 +-- transports/webtransport/src/connection.rs | 7 +- .../webtransport/src/connection/connecting.rs | 2 +- .../webtransport/src/connection/stream.rs | 11 +-- transports/webtransport/src/lib.rs | 2 - transports/webtransport/src/provider.rs | 68 ------------------ .../webtransport/src/provider/async_std.rs | 70 ------------------- transports/webtransport/src/provider/tokio.rs | 70 ------------------- transports/webtransport/src/transport.rs | 23 +++--- 9 files changed, 28 insertions(+), 235 deletions(-) delete mode 100644 transports/webtransport/src/provider.rs delete mode 100644 transports/webtransport/src/provider/async_std.rs delete mode 100644 transports/webtransport/src/provider/tokio.rs diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml index fd0d22ffcde..93d661437b9 100644 --- a/transports/webtransport/Cargo.toml +++ b/transports/webtransport/Cargo.toml @@ -10,13 +10,13 @@ license = "MIT" [dependencies] libp2p-core = { workspace = true } libp2p-tls = { workspace = true } -libp2p-identity = { workspace = true } +libp2p-identity = { workspace = true, features = ["ed25519", "rand"] } libp2p-noise = { workspace = true } async-std = { version = "1.12.0", optional = true } tokio = { workspace = true, default-features = false, features = ["net", "rt", "time"], optional = true } futures = { workspace = true } tracing = { workspace = true } -if-watch = "3.2.0" +if-watch = { version = "3.2.0", features = ["tokio"] } futures-timer = "3.0.3" rustls = { version = "0.23.9", default-features = false } thiserror = "1.0.61" @@ -25,9 +25,9 @@ sha2 = "0.10.8" quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } wtransport = "0.4.0" -[features] -tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] -async-std = ["dep:async-std", "if-watch/smol", "quinn/runtime-async-std"] +#[features] +#tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] +#async-std = ["dep:async-std", "if-watch/smol", "quinn/runtime-async-std"] [lints] workspace = true diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs index 66a9be68ab4..4ced2b1fe00 100644 --- a/transports/webtransport/src/connection.rs +++ b/transports/webtransport/src/connection.rs @@ -38,10 +38,11 @@ impl Connection { /// Returns the address of the node we're connected to. /// Panics if the connection is still handshaking. fn remote_peer_id(&self) -> PeerId { - let cert = self.connection + let cert_chain = self.connection .peer_identity() - .expect("connection got identity because it passed TLS handshake; qed") - .as_slice().first().expect("there should be exactly one certificate; qed"); + .expect("connection got identity because it passed TLS handshake; qed"); + let cert = cert_chain.as_slice() + .first().expect("there should be exactly one certificate; qed"); let p2p_cert = libp2p_tls::certificate::parse_binary(cert.der()) .expect("the certificate was validated during TLS handshake; qed"); diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs index 5be4863e86b..87dae1c78e1 100644 --- a/transports/webtransport/src/connection/connecting.rs +++ b/transports/webtransport/src/connection/connecting.rs @@ -69,7 +69,7 @@ impl Connecting { impl Future for Connecting { type Output = Result<(PeerId, Connection), Error>; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let (peer_id, connection) = match futures::ready!(self.connecting.poll_unpin(cx)) { Either::Right(_) => return Poll::Ready(Err(Error::HandshakeTimedOut)), Either::Left((res, _)) => res?, diff --git a/transports/webtransport/src/connection/stream.rs b/transports/webtransport/src/connection/stream.rs index 85fed6cac18..07400bfa285 100644 --- a/transports/webtransport/src/connection/stream.rs +++ b/transports/webtransport/src/connection/stream.rs @@ -3,9 +3,10 @@ use std::pin::Pin; use std::task::{Context, Poll}; use futures::{AsyncRead, AsyncWrite}; use wtransport::{SendStream, RecvStream}; +use tokio; /// A single stream on a connection -pub(crate) struct Stream { +pub struct Stream { /// A send part of the stream send: SendStream, /// A reception part of the stream @@ -26,7 +27,7 @@ impl Stream { impl AsyncRead for Stream { fn poll_read( - self: Pin<&mut Self>, + mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { @@ -52,15 +53,15 @@ impl AsyncRead for Stream { } impl AsyncWrite for Stream { - fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { tokio::io::AsyncWrite::poll_write(Pin::new(&mut self.send), cx, buf) } - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { tokio::io::AsyncWrite::poll_flush(Pin::new(&mut self.send), cx) } - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { if let Some(close_result) = self.close_result { // For some reason poll_close needs to be 'fuse'able return Poll::Ready(close_result.map_err(Into::into)); diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs index 6e023c79505..ee13f03b202 100644 --- a/transports/webtransport/src/lib.rs +++ b/transports/webtransport/src/lib.rs @@ -1,4 +1,3 @@ -mod provider; mod transport; mod connection; mod config; @@ -6,7 +5,6 @@ mod certificate; use wtransport::error::ConnectionError; -pub use provider::Provider; pub use transport::GenTransport; pub use connection::{Connecting, Connection}; pub use certificate::CertHash; diff --git a/transports/webtransport/src/provider.rs b/transports/webtransport/src/provider.rs deleted file mode 100644 index 6f1122ee55f..00000000000 --- a/transports/webtransport/src/provider.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use futures::future::BoxFuture; -use if_watch::IfEvent; -use std::{ - io, - net::{SocketAddr, UdpSocket}, - task::{Context, Poll}, - time::Duration, -}; - -#[cfg(feature = "async-std")] -pub mod async_std; -#[cfg(feature = "tokio")] -pub mod tokio; - -pub enum Runtime { - #[cfg(feature = "tokio")] - Tokio, - #[cfg(feature = "async-std")] - AsyncStd, - Dummy, -} - -/// Provider for a corresponding quinn runtime and spawning tasks. -pub trait Provider: Unpin + Send + Sized + 'static { - type IfWatcher: Unpin + Send; - - /// Run the corresponding runtime - fn runtime() -> Runtime; - - /// Create a new [`if_watch`] watcher that reports [`IfEvent`]s for network interface changes. - fn new_if_watcher() -> io::Result; - - /// Poll for an address change event. - fn poll_if_event( - watcher: &mut Self::IfWatcher, - cx: &mut Context<'_>, - ) -> Poll>; - - /// Sleep for specified amount of time. - fn sleep(duration: Duration) -> BoxFuture<'static, ()>; - - /// Sends data on the socket to the given address. On success, returns the number of bytes written. - fn send_to<'a>( - udp_socket: &'a UdpSocket, - buf: &'a [u8], - target: SocketAddr, - ) -> BoxFuture<'a, io::Result>; -} diff --git a/transports/webtransport/src/provider/async_std.rs b/transports/webtransport/src/provider/async_std.rs deleted file mode 100644 index a110058108c..00000000000 --- a/transports/webtransport/src/provider/async_std.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2022 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use futures::{future::BoxFuture, FutureExt}; -use std::{ - io, - net::UdpSocket, - task::{Context, Poll}, - time::Duration, -}; - -use crate::GenTransport; - -/// Transport with [`async-std`] runtime. -pub type Transport = GenTransport; - -/// Provider for quinn runtime and spawning tasks using [`async-std`]. -pub struct Provider; - -impl super::Provider for Provider { - type IfWatcher = if_watch::smol::IfWatcher; - - fn runtime() -> super::Runtime { - super::Runtime::AsyncStd - } - - fn new_if_watcher() -> io::Result { - if_watch::smol::IfWatcher::new() - } - - fn poll_if_event( - watcher: &mut Self::IfWatcher, - cx: &mut Context<'_>, - ) -> Poll> { - watcher.poll_if_event(cx) - } - - fn sleep(duration: Duration) -> BoxFuture<'static, ()> { - async_std::task::sleep(duration).boxed() - } - - fn send_to<'a>( - udp_socket: &'a UdpSocket, - buf: &'a [u8], - target: std::net::SocketAddr, - ) -> BoxFuture<'a, io::Result> { - Box::pin(async move { - async_std::net::UdpSocket::from(udp_socket.try_clone()?) - .send_to(buf, target) - .await - }) - } -} diff --git a/transports/webtransport/src/provider/tokio.rs b/transports/webtransport/src/provider/tokio.rs deleted file mode 100644 index 9cb148d6ef2..00000000000 --- a/transports/webtransport/src/provider/tokio.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2022 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use futures::{future::BoxFuture, FutureExt}; -use std::{ - io, - net::{SocketAddr, UdpSocket}, - task::{Context, Poll}, - time::Duration, -}; - -use crate::GenTransport; - -/// Transport with [`tokio`] runtime. -pub type Transport = GenTransport; - -/// Provider for quinn runtime and spawning tasks using [`tokio`]. -pub struct Provider; - -impl super::Provider for Provider { - type IfWatcher = if_watch::tokio::IfWatcher; - - fn runtime() -> super::Runtime { - super::Runtime::Tokio - } - - fn new_if_watcher() -> io::Result { - if_watch::tokio::IfWatcher::new() - } - - fn poll_if_event( - watcher: &mut Self::IfWatcher, - cx: &mut Context<'_>, - ) -> Poll> { - watcher.poll_if_event(cx) - } - - fn sleep(duration: Duration) -> BoxFuture<'static, ()> { - tokio::time::sleep(duration).boxed() - } - - fn send_to<'a>( - udp_socket: &'a UdpSocket, - buf: &'a [u8], - target: SocketAddr, - ) -> BoxFuture<'a, io::Result> { - Box::pin(async move { - tokio::net::UdpSocket::from_std(udp_socket.try_clone()?)? - .send_to(buf, target) - .await - }) - } -} diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 06e63f425dc..a064715a671 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -9,6 +9,7 @@ use std::time::Duration; use futures::{prelude::*, stream::SelectAll}; use futures::future::BoxFuture; use if_watch::IfEvent; +use if_watch::tokio::IfWatcher; use wtransport::config::TlsServerConfig; use wtransport::endpoint::{endpoint_side, IncomingSession}; use wtransport::error::ConnectionError; @@ -21,13 +22,13 @@ use libp2p_core::muxing::StreamMuxerBox; use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; use libp2p_identity::{Keypair, PeerId}; -use crate::{Connecting, Provider}; +use crate::Connecting; use crate::certificate::CertHash; use crate::config::Config; use crate::connection::Connection; use crate::Error; -pub struct GenTransport { +pub struct GenTransport { server_tls_config: TlsServerConfig, keypair: Keypair, cert_hashes: Vec, @@ -35,12 +36,12 @@ pub struct GenTransport { /// Timeout for the [`Connecting`] future. handshake_timeout: Duration, - listeners: SelectAll>, + listeners: SelectAll, /// Waker to poll the transport again when a new listener is added. waker: Option, } -impl GenTransport

{ +impl GenTransport { pub fn new(config: Config) -> Self { let handshake_timeout = config.handshake_timeout; let keypair = config.keypair.clone(); @@ -76,7 +77,7 @@ impl GenTransport

{ } } -impl Transport for GenTransport

{ +impl Transport for GenTransport { type Output = (PeerId, Connection); type Error = Error; type ListenerUpgrade = Connecting; @@ -121,7 +122,7 @@ impl Transport for GenTransport

{ } /// Listener for incoming connections. -struct Listener { +struct Listener { /// Id of the listener. listener_id: ListenerId, /// Endpoint @@ -133,7 +134,7 @@ struct Listener { /// Watcher for network interface changes. /// /// None if we are only listening on a single interface. - if_watcher: Option, + if_watcher: Option, /// Whether the listener was closed and the stream should terminate. is_closed: bool, /// Pending event to reported. @@ -147,7 +148,7 @@ struct Listener { cert_hashes: Vec, } -impl Listener

{ +impl Listener { fn new( listener_id: ListenerId, socket_addr: SocketAddr, @@ -159,7 +160,7 @@ impl Listener

{ let pending_event; let mut listening_addresses = HashSet::new(); if socket_addr.ip().is_unspecified() { - if_watcher = Some(P::new_if_watcher()?); + if_watcher = Some(if_watch::tokio::IfWatcher::new()?); pending_event = None; } else { if_watcher = None; @@ -258,8 +259,8 @@ impl Listener

{ }*/ } -impl Stream for Listener

{ - type Item = TransportEvent< as Transport>::ListenerUpgrade, Error>; +impl Stream for Listener { + type Item = TransportEvent<::ListenerUpgrade, Error>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { From 60b5c36d3b4a181610587501c2dfbd4a31537d7e Mon Sep 17 00:00:00 2001 From: dgarus Date: Tue, 17 Dec 2024 14:44:33 +0300 Subject: [PATCH 03/16] removed the Provider trait --- Cargo.lock | 234 ++++++++++++++---- transports/webtransport/Cargo.toml | 7 +- .../webtransport/src/connection/stream.rs | 17 +- transports/webtransport/src/transport.rs | 1 - 4 files changed, 189 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31df58e8ec4..5eaf5b8a109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -693,9 +693,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake2" @@ -863,6 +863,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -1032,6 +1038,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1722,7 +1738,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.11", + "rustls 0.23.20", "rustls-pki-types", ] @@ -2073,6 +2089,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "httlib-huffman" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877" + [[package]] name = "http" version = "0.2.9" @@ -2395,7 +2417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.3", "fnv", "futures", "if-addrs", @@ -3214,7 +3236,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.20", "socket2", "thiserror 2.0.3", "tokio", @@ -3433,11 +3455,12 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "libp2p-yamux", - "rcgen", + "rcgen 0.11.3", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.20", "rustls-webpki 0.101.7", "thiserror 2.0.3", + "time", "tokio", "x509-parser 0.16.0", "yasna", @@ -3485,7 +3508,7 @@ dependencies = [ "multihash", "quickcheck", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "serde", "stun 0.6.0", "thiserror 2.0.3", @@ -3553,7 +3576,7 @@ dependencies = [ "libp2p-tcp", "parking_lot", "pin-project-lite", - "rcgen", + "rcgen 0.11.3", "rw-stream-sink", "soketto", "thiserror 2.0.3", @@ -3581,6 +3604,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "libp2p-webtransport" +version = "0.1.0" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "libp2p-tls", + "quinn", + "rustls 0.23.20", + "sha2 0.10.8", + "thiserror 1.0.63", + "time", + "tokio", + "tracing", + "wtransport", +] + [[package]] name = "libp2p-webtransport-websys" version = "0.4.1" @@ -3933,7 +3977,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.9.2", "security-framework-sys", "tempfile", ] @@ -4107,6 +4151,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "octets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109983a091271ee8916076731ba5fdc9ee22fea871bc7c6ceab9bfd423eb1d99" + [[package]] name = "oid-registry" version = "0.6.1" @@ -4149,7 +4199,7 @@ version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -4401,11 +4451,11 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pem" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "serde", ] @@ -4706,9 +4756,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "async-io", "async-std", @@ -4717,36 +4767,41 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 1.1.0", - "rustls 0.23.11", - "thiserror 1.0.63", + "rustc-hash", + "rustls 0.23.20", + "socket2", + "thiserror 2.0.3", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom 0.2.15", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.0.0", - "rustls 0.23.11", + "rustc-hash", + "rustls 0.23.20", + "rustls-pki-types", "slab", - "thiserror 1.0.63", + "thiserror 2.0.3", "tinyvec", "tracing", + "web-time 1.1.0", ] [[package]] name = "quinn-udp" -version = "0.5.0" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7ad7bc932e4968523fa7d9c320ee135ff779de720e9350fee8728838551764" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", @@ -4840,7 +4895,7 @@ version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", ] [[package]] @@ -4876,6 +4931,19 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" +dependencies = [ + "pem", + "ring 0.17.8", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redis" version = "0.24.0" @@ -5204,12 +5272,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.0.0" @@ -5240,7 +5302,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -5268,40 +5330,54 @@ dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.0.1", +] + [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time 1.1.0", +] [[package]] name = "rustls-webpki" @@ -5315,9 +5391,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -5428,7 +5504,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.3", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -5436,9 +5525,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -5920,7 +6009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.3", "system-configuration-sys 0.5.0", ] @@ -5930,8 +6019,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.4.1", - "core-foundation", + "bitflags 2.6.0", + "core-foundation 0.9.3", "system-configuration-sys 0.6.0", ] @@ -6322,7 +6411,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "bytes", "futures-util", "http 1.1.0", @@ -6867,7 +6956,7 @@ dependencies = [ "log", "pem", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "regex", "ring 0.16.20", "rtcp", @@ -6931,7 +7020,7 @@ dependencies = [ "pem", "rand 0.8.5", "rand_core 0.6.4", - "rcgen", + "rcgen 0.11.3", "ring 0.16.20", "rustls 0.21.11", "sec1", @@ -7384,6 +7473,43 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "wtransport" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db854cf8d3a1089a8a4e283dace6afc3746d4e570e82392779a53c943cf7aa4" +dependencies = [ + "bytes", + "pem", + "quinn", + "rcgen 0.13.1", + "rustls 0.23.20", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "sha2 0.10.8", + "socket2", + "thiserror 1.0.63", + "time", + "tokio", + "tracing", + "url", + "wtransport-proto", + "x509-parser 0.16.0", +] + +[[package]] +name = "wtransport-proto" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28b252f224a6467fb0dfc38be040bc1dde17ba5bae43120c536225ff6f4f60b" +dependencies = [ + "httlib-huffman", + "octets", + "thiserror 1.0.63", + "url", +] + [[package]] name = "x25519-dalek" version = "2.0.1" diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml index 93d661437b9..6d273629d98 100644 --- a/transports/webtransport/Cargo.toml +++ b/transports/webtransport/Cargo.toml @@ -12,8 +12,7 @@ libp2p-core = { workspace = true } libp2p-tls = { workspace = true } libp2p-identity = { workspace = true, features = ["ed25519", "rand"] } libp2p-noise = { workspace = true } -async-std = { version = "1.12.0", optional = true } -tokio = { workspace = true, default-features = false, features = ["net", "rt", "time"], optional = true } +tokio = { workspace = true, default-features = false, features = ["net", "rt", "time"] } futures = { workspace = true } tracing = { workspace = true } if-watch = { version = "3.2.0", features = ["tokio"] } @@ -25,9 +24,5 @@ sha2 = "0.10.8" quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } wtransport = "0.4.0" -#[features] -#tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] -#async-std = ["dep:async-std", "if-watch/smol", "quinn/runtime-async-std"] - [lints] workspace = true diff --git a/transports/webtransport/src/connection/stream.rs b/transports/webtransport/src/connection/stream.rs index 07400bfa285..49ea4e3a661 100644 --- a/transports/webtransport/src/connection/stream.rs +++ b/transports/webtransport/src/connection/stream.rs @@ -1,9 +1,8 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -use futures::{AsyncRead, AsyncWrite}; +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use wtransport::{SendStream, RecvStream}; -use tokio; /// A single stream on a connection pub struct Stream { @@ -25,7 +24,7 @@ impl Stream { } } -impl AsyncRead for Stream { +impl futures::AsyncRead for Stream { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -36,8 +35,8 @@ impl AsyncRead for Stream { return Poll::Ready(Ok(0)); } } - let mut read_buf = tokio::io::ReadBuf::new(buf); - let res = tokio::io::AsyncRead::poll_read(Pin::new(&mut self.recv), cx, &mut read_buf); + let mut read_buf = ReadBuf::new(buf); + let res = AsyncRead::poll_read(Pin::new(&mut self.recv), cx, &mut read_buf); match res { Poll::Ready(Ok(_)) => { Poll::Ready(Ok(read_buf.filled().len())) @@ -52,13 +51,13 @@ impl AsyncRead for Stream { } } -impl AsyncWrite for Stream { +impl futures::AsyncWrite for Stream { fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { - tokio::io::AsyncWrite::poll_write(Pin::new(&mut self.send), cx, buf) + AsyncWrite::poll_write(Pin::new(&mut self.send), cx, buf) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - tokio::io::AsyncWrite::poll_flush(Pin::new(&mut self.send), cx) + AsyncWrite::poll_flush(Pin::new(&mut self.send), cx) } fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -66,7 +65,7 @@ impl AsyncWrite for Stream { // For some reason poll_close needs to be 'fuse'able return Poll::Ready(close_result.map_err(Into::into)); } - let close_result = futures::ready!(tokio::io::AsyncWrite::poll_shutdown(Pin::new(&mut self.send), cx)); + let close_result = futures::ready!(AsyncWrite::poll_shutdown(Pin::new(&mut self.send), cx)); self.close_result = Some(close_result.as_ref().map_err(|e| e.kind()).copied()); Poll::Ready(close_result) } diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index a064715a671..e7a0f73e1ee 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -32,7 +32,6 @@ pub struct GenTransport { server_tls_config: TlsServerConfig, keypair: Keypair, cert_hashes: Vec, - /// Timeout for the [`Connecting`] future. handshake_timeout: Duration, From f41e8fa149ea9490f7d1093b9242d62dcf65702a Mon Sep 17 00:00:00 2001 From: dgarus Date: Fri, 20 Dec 2024 11:28:05 +0300 Subject: [PATCH 04/16] mod transport --- transports/webtransport/src/transport.rs | 259 +++++++++++------------ 1 file changed, 119 insertions(+), 140 deletions(-) diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index e7a0f73e1ee..3acf01b8a63 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -1,6 +1,7 @@ use std::collections::HashSet; +use std::fmt; use std::future::Pending; -use std::net::{IpAddr, SocketAddr}; +use std::net::SocketAddr; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll, Waker}; @@ -8,23 +9,16 @@ use std::time::Duration; use futures::{prelude::*, stream::SelectAll}; use futures::future::BoxFuture; -use if_watch::IfEvent; -use if_watch::tokio::IfWatcher; -use wtransport::config::TlsServerConfig; -use wtransport::endpoint::{endpoint_side, IncomingSession}; -use wtransport::error::ConnectionError; -use wtransport::ServerConfig; - -use libp2p_core::{Multiaddr, Transport}; -use libp2p_core::multiaddr::Protocol; -use libp2p_core::multihash::Multihash; -use libp2p_core::muxing::StreamMuxerBox; +use wtransport::{config::TlsServerConfig, ServerConfig}; +use wtransport::endpoint::{Endpoint, endpoint_side::Server, IncomingSession}; + +use libp2p_core::{Multiaddr, multiaddr::Protocol, multihash::Multihash, Transport}; use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; use libp2p_identity::{Keypair, PeerId}; -use crate::Connecting; use crate::certificate::CertHash; use crate::config::Config; +use crate::Connecting; use crate::connection::Connection; use crate::Error; @@ -66,6 +60,7 @@ impl GenTransport { (SocketAddr, Option), TransportError<::Error>, > { + //todo rewrite: addr.clone() should be avoided. let (socket_addr, peer_id) = multiaddr_to_socketaddr(&addr) .ok_or_else(|| TransportError::MultiaddrNotSupported(addr.clone()))?; if check_unspecified_addr && (socket_addr.port() == 0 || socket_addr.ip().is_unspecified()) @@ -85,7 +80,7 @@ impl Transport for GenTransport { fn listen_on(&mut self, id: ListenerId, addr: Multiaddr) -> Result<(), TransportError> { let (socket_addr, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; let config = ServerConfig::builder() - .with_bind_address(socket_addr.clone()) + .with_bind_address(socket_addr) .with_custom_tls(self.server_tls_config.clone()) .build(); @@ -96,7 +91,7 @@ impl Transport for GenTransport { let handshake_timeout = self.handshake_timeout.clone(); let listener = Listener::new( - id, socket_addr, Arc::new(endpoint), keypair, cert_hashes, handshake_timeout, + id, endpoint, keypair, cert_hashes, handshake_timeout, )?; self.listeners.push(listener); @@ -108,15 +103,37 @@ impl Transport for GenTransport { } fn remove_listener(&mut self, id: ListenerId) -> bool { - todo!() + if let Some(listener) = self.listeners.iter_mut().find(|l| l.listener_id == id) { + // Close the listener, which will eventually finish its stream. + // `SelectAll` removes streams once they are finished. + listener.close(Ok(())); + true + } else { + false + } } fn dial(&mut self, _addr: Multiaddr, _opts: DialOpts) -> Result> { panic!("Dial operation is not supported!") } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - todo!() + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll> + { + if let Poll::Ready(Some(ev)) = self.listeners.poll_next_unpin(cx) { + return Poll::Ready(ev); + } + + match &self.waker { + None => self.waker = Some(cx.waker().clone()), + Some(waker) => { + if !waker.will_wake(cx.waker()) { + self.waker = Some(cx.waker().clone()); + } + } + }; + + Poll::Pending } } @@ -125,15 +142,11 @@ struct Listener { /// Id of the listener. listener_id: ListenerId, /// Endpoint - endpoint: Arc>, + endpoint: Arc>, /// A future to poll new incoming connections. accept: BoxFuture<'static, IncomingSession>, /// Timeout for connection establishment on inbound connections. handshake_timeout: Duration, - /// Watcher for network interface changes. - /// - /// None if we are only listening on a single interface. - if_watcher: Option, /// Whether the listener was closed and the stream should terminate. is_closed: bool, /// Pending event to reported. @@ -141,55 +154,52 @@ struct Listener { /// The stream must be to awaken after it has been closed to deliver the last event. close_listener_waker: Option, - listening_addresses: HashSet, - keypair: Keypair, + cert_hashes: Vec, } impl Listener { fn new( listener_id: ListenerId, - socket_addr: SocketAddr, - endpoint: Arc>, + endpoint: Endpoint, keypair: &Keypair, cert_hashes: &Vec, handshake_timeout: Duration, ) -> Result { - let if_watcher; - let pending_event; - let mut listening_addresses = HashSet::new(); - if socket_addr.ip().is_unspecified() { - if_watcher = Some(if_watch::tokio::IfWatcher::new()?); - pending_event = None; - } else { - if_watcher = None; - listening_addresses.insert(socket_addr.ip()); - let ma = socketaddr_to_multiaddr(&socket_addr, cert_hashes); - pending_event = Some(TransportEvent::NewAddress { - listener_id, - listen_addr: ma, - }) - } - - - let endpoint_c = Arc::clone(&endpoint); - let accept = async move { endpoint_c.accept().await }.boxed(); + let endpoint = Arc::new(endpoint); + let c_endpoint = Arc::clone(&endpoint); + let accept = async move { c_endpoint.accept().await }.boxed(); - Ok( - Listener { + Ok(Listener { listener_id, endpoint, accept, handshake_timeout, - if_watcher, is_closed: false, - pending_event, + pending_event: None, close_listener_waker: None, - listening_addresses, keypair: keypair.clone(), cert_hashes: cert_hashes.clone(), - } - ) + }) + } + + /// Report the listener as closed in a [`TransportEvent::ListenerClosed`] and + /// terminate the stream. + fn close(&mut self, reason: Result<(), Error>) { + if self.is_closed { + return; + } + self.endpoint.close(From::from(0u32), &[]); + self.pending_event = Some(TransportEvent::ListenerClosed { + listener_id: self.listener_id, + reason, + }); + self.is_closed = true; + + // Wake the stream to deliver the last event. + if let Some(waker) = self.close_listener_waker.take() { + waker.wake(); + } } fn socket_addr(&self) -> SocketAddr { @@ -199,63 +209,12 @@ impl Listener { } fn noise_config(&self) -> libp2p_noise::Config { - let mut res = libp2p_noise::Config::new(&self.keypair).expect("Getting a noise config"); - // let mut set = HashSet::with_capacity(self.cert_hashes.len()); + let res = libp2p_noise::Config::new(&self.keypair).expect("Getting a noise config"); let set = self.cert_hashes.iter().cloned().collect::>(); let res = res.with_webtransport_certhashes(set); res } - - - /* todo poll_if_addr - /// Poll for a next If Event. - fn poll_if_addr(&mut self, cx: &mut Context<'_>) -> Poll<::Item> { - let endpoint_addr = self.socket_addr(); - let Some(if_watcher) = self.if_watcher.as_mut() else { - return Poll::Pending; - }; - loop { - match ready!(P::poll_if_event(if_watcher, cx)) { - Ok(IfEvent::Up(inet)) => { - if let Some(listen_addr) = - ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) - { - tracing::debug!( - address=%listen_addr, - "New listen address" - ); - self.listening_addresses.insert(inet.addr()); - return Poll::Ready(TransportEvent::NewAddress { - listener_id: self.listener_id, - listen_addr, - }); - } - } - Ok(IfEvent::Down(inet)) => { - if let Some(listen_addr) = - ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) - { - tracing::debug!( - address=%listen_addr, - "Expired listen address" - ); - self.listening_addresses.remove(&inet.addr()); - return Poll::Ready(TransportEvent::AddressExpired { - listener_id: self.listener_id, - listen_addr, - }); - } - } - Err(err) => { - return Poll::Ready(TransportEvent::ListenerError { - listener_id: self.listener_id, - error: err.into(), - }) - } - } - } - }*/ } impl Stream for Listener { @@ -269,30 +228,15 @@ impl Stream for Listener { if self.is_closed { return Poll::Ready(None); } - /* todo poll_if_addr - if let Poll::Ready(event) = self.poll_if_addr(cx) { - return Poll::Ready(Some(event)); - }*/ match self.accept.poll_unpin(cx) { Poll::Ready(incoming_session) => { - let endpoint = self.endpoint.clone(); + let endpoint = Arc::clone(&self.endpoint); self.accept = async move { endpoint.accept().await }.boxed(); - - /*let connecting = match session_request.accept() { - Ok(connecting) => connecting, - Err(error) => { - return Poll::Ready(Some(TransportEvent::ListenerError { - listener_id: self.listener_id, - error: Error::Connection(crate::ConnectionError(error)), - })) - } - };*/ - - let local_addr = socketaddr_to_multiaddr(&self.socket_addr(), &self.cert_hashes); + let mut local_addr = socketaddr_to_multiaddr(&self.socket_addr()); + local_addr = add_hashes(local_addr, &self.cert_hashes); let remote_addr = incoming_session.remote_address(); - //todo нафига к удаленному адресу добавлять хэши сертификатов? - let send_back_addr = socketaddr_to_multiaddr(&remote_addr, &self.cert_hashes); + let send_back_addr = socketaddr_to_multiaddr(&remote_addr); let noise = self.noise_config(); let event = TransportEvent::Incoming { @@ -306,38 +250,61 @@ impl Stream for Listener { Poll::Pending => {} }; - self.close_listener_waker = Some(cx.waker().clone()); + match &self.close_listener_waker { + None => self.close_listener_waker = Some(cx.waker().clone()), + Some(waker) => { + if !waker.will_wake(cx.waker()) { + self.close_listener_waker = Some(cx.waker().clone()) + } + }, + } return Poll::Pending; } } } +impl fmt::Debug for Listener { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Listener") + .field("listener_id", &self.listener_id) + .field("handshake_timeout", &self.handshake_timeout) + .field("is_closed", &self.is_closed) + .field("pending_event", &self.pending_event) + .finish() + } +} + /// Turns an IP address and port into the corresponding WebTransport multiaddr. -fn socketaddr_to_multiaddr(socket_addr: &SocketAddr, hashes: &Vec>) -> Multiaddr { - let mut vec = hashes.clone(); - let mut res = Multiaddr::empty() +fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { + Multiaddr::empty() .with(socket_addr.ip().into()) .with(Protocol::Udp(socket_addr.port())) .with(Protocol::QuicV1) .with(Protocol::WebTransport) - .with(Protocol::Certhash( - vec.pop().expect("Gets the last element"), - )); - if !vec.is_empty() { - res = res.with(Protocol::Certhash( +} + +fn add_hashes(m_addr: Multiaddr, hashes: &Vec>) -> Multiaddr { + if !hashes.is_empty() { + let mut vec = hashes.clone(); + let mut res = m_addr.with(Protocol::Certhash( vec.pop().expect("Gets the last element"), )); - }; + if !vec.is_empty() { + res = res.with(Protocol::Certhash( + vec.pop().expect("Gets the last element"), + )); + }; - res + res + } else { + m_addr + } } /// Tries to turn a Webtransport multiaddress into a UDP [`SocketAddr`]. Returns None if the format /// of the multiaddr is wrong. -fn multiaddr_to_socketaddr( - addr: &Multiaddr, -) -> Option<(SocketAddr, Option)> { +fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option<(SocketAddr, Option)> { let mut iter = addr.iter(); let proto1 = iter.next()?; let proto2 = iter.next()?; @@ -385,10 +352,22 @@ fn multiaddr_to_socketaddr( } #[cfg(test)] -// #[cfg(any(feature = "async-std", feature = "tokio"))] mod test { + use time::ext::NumericalDuration; + use time::OffsetDateTime; + + use crate::certificate::Certificate; + + use super::*; + #[test] fn test() { - println!("hi!") + let keypair = Keypair::generate_ed25519(); + let not_before = OffsetDateTime::now_utc().checked_sub(1.days()).unwrap(); + let cert = Certificate::generate(&keypair, not_before).expect("Generate certificate"); + + let config = Config::new(&keypair, cert); + let mut transport = GenTransport::new(config); + // todo write few tests: closing a listener, addresses parsing and so on } } \ No newline at end of file From b18c11e76874e6134b5926c2267b399c62acd154 Mon Sep 17 00:00:00 2001 From: dgarus Date: Sat, 21 Dec 2024 11:51:15 +0300 Subject: [PATCH 05/16] connecting & noise usage --- Cargo.lock | 8 +-- transports/webtransport/Cargo.toml | 2 +- transports/webtransport/src/connection.rs | 22 +----- .../webtransport/src/connection/connecting.rs | 71 +++++++++++-------- transports/webtransport/src/lib.rs | 8 ++- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5eaf5b8a109..4eb7e76f720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7475,9 +7475,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "wtransport" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db854cf8d3a1089a8a4e283dace6afc3746d4e570e82392779a53c943cf7aa4" +checksum = "93a724f65db90b6a1ffa92ea4966cf03cb7e2bcd3ef7135b84dfe4339640d1b9" dependencies = [ "bytes", "pem", @@ -7500,9 +7500,9 @@ dependencies = [ [[package]] name = "wtransport-proto" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28b252f224a6467fb0dfc38be040bc1dde17ba5bae43120c536225ff6f4f60b" +checksum = "14e4882c24a62f15024609b3688e6e29a4c2129634d27debc849ccd3f9b9690b" dependencies = [ "httlib-huffman", "octets", diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml index 6d273629d98..1f3e90099e5 100644 --- a/transports/webtransport/Cargo.toml +++ b/transports/webtransport/Cargo.toml @@ -22,7 +22,7 @@ thiserror = "1.0.61" time = "0.3.36" sha2 = "0.10.8" quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } -wtransport = "0.4.0" +wtransport = "0.5.0" [lints] workspace = true diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs index 4ced2b1fe00..e3d78a8dc46 100644 --- a/transports/webtransport/src/connection.rs +++ b/transports/webtransport/src/connection.rs @@ -1,14 +1,13 @@ use std::pin::Pin; use std::task::{Context, Poll}; +use futures::{FutureExt, ready}; use futures::future::BoxFuture; -use futures::FutureExt; use wtransport::{error::ConnectionError, RecvStream, SendStream}; pub use connecting::Connecting; use libp2p_core::muxing::StreamMuxerEvent; use libp2p_core::StreamMuxer; -use libp2p_identity::PeerId; pub(crate) use crate::connection::stream::Stream; use crate::Error; @@ -33,22 +32,6 @@ impl Connection { closing: None, } } - - - /// Returns the address of the node we're connected to. - /// Panics if the connection is still handshaking. - fn remote_peer_id(&self) -> PeerId { - let cert_chain = self.connection - .peer_identity() - .expect("connection got identity because it passed TLS handshake; qed"); - let cert = cert_chain.as_slice() - .first().expect("there should be exactly one certificate; qed"); - - let p2p_cert = libp2p_tls::certificate::parse_binary(cert.der()) - .expect("the certificate was validated during TLS handshake; qed"); - - p2p_cert.peer_id() - } } impl StreamMuxer for Connection { @@ -63,8 +46,7 @@ impl StreamMuxer for Connection { async move { connection.accept_bi().await }.boxed() }); - let (send, recv) = futures::ready!(incoming.poll_unpin(cx))?; - // .map_err(ConnectionError)?; + let (send, recv) = ready!(incoming.poll_unpin(cx))?; this.incoming.take(); let stream = Stream::new(send, recv); Poll::Ready(Ok(stream)) diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs index 87dae1c78e1..1d2c8f2340d 100644 --- a/transports/webtransport/src/connection/connecting.rs +++ b/transports/webtransport/src/connection/connecting.rs @@ -3,12 +3,11 @@ use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; +use futures::{FutureExt, ready}; use futures::future::{BoxFuture, Either, Select, select}; -use futures::FutureExt; use futures_timer::Delay; use wtransport::endpoint::IncomingSession; -use libp2p_core::StreamMuxer; use libp2p_core::upgrade::InboundConnectionUpgrade; use libp2p_identity::PeerId; @@ -18,8 +17,6 @@ pub(crate) const WEBTRANSPORT_PATH: &str = "/.well-known/libp2p-webtransport?typ /// A Webtransport connection currently being negotiated. pub struct Connecting { - noise_config: libp2p_noise::Config, - // certhashes: Vec, connecting: Select>, Delay>, } @@ -27,19 +24,19 @@ impl Connecting { pub fn new(incoming_session: IncomingSession, noise_config: libp2p_noise::Config, timeout: Duration, - // certhashes: Vec, ) -> Self { Connecting { - noise_config, - // certhashes, connecting: select( - Self::handshake(incoming_session).boxed(), + Self::handshake(incoming_session, noise_config).boxed(), Delay::new(timeout), ), } } - async fn handshake(incoming_session: IncomingSession) -> Result<(PeerId, Connection), Error> { + async fn handshake( + incoming_session: IncomingSession, + noise_config: libp2p_noise::Config, + ) -> Result<(PeerId, Connection), Error> { match incoming_session.await { Ok(session_request) => { let path = session_request.path(); @@ -51,8 +48,12 @@ impl Connecting { match session_request.accept().await { Ok(wtransport_connection) => { + // The client SHOULD start the handshake right after sending the CONNECT request, + // without waiting for the server's response. + let peer_id = Self::noise_auth(wtransport_connection.clone(), noise_config).await?; let connection = Connection::new(wtransport_connection); - Ok((connection.remote_peer_id(), connection)) + + Ok((peer_id, connection)) } Err(connection_error) => { Err(Error::Connection(connection_error)) @@ -64,35 +65,47 @@ impl Connecting { } } } + + async fn noise_auth( + connection: wtransport::Connection, + noise_config: libp2p_noise::Config, + ) -> Result { + fn remote_peer_id(con: &wtransport::Connection,) -> PeerId { + let cert_chain = con + .peer_identity() + .expect("connection got identity because it passed TLS handshake; qed"); + let cert = cert_chain.as_slice() + .first().expect("there should be exactly one certificate; qed"); + + let p2p_cert = libp2p_tls::certificate::parse_binary(cert.der()) + .expect("the certificate was validated during TLS handshake; qed"); + + p2p_cert.peer_id() + } + + let (send, recv) = connection.accept_bi().await?; + let stream = crate::Stream::new(send, recv); + let (actual_peer_id, _) = noise_config.upgrade_inbound(stream, "").await?; + + let expected_peer_id = remote_peer_id(&connection); + // TODO: This should be part libp2p-noise + if actual_peer_id != expected_peer_id { + return Err(Error::UnknownRemotePeerId); + } + + Ok(actual_peer_id) + } } impl Future for Connecting { type Output = Result<(PeerId, Connection), Error>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let (peer_id, connection) = match futures::ready!(self.connecting.poll_unpin(cx)) { + let (peer_id, connection) = match ready!(self.connecting.poll_unpin(cx)) { Either::Right(_) => return Poll::Ready(Err(Error::HandshakeTimedOut)), Either::Left((res, _)) => res?, }; - /*let session = WebTransportSession::accept(request, stream, h3_conn).await?; - let arc_session = Arc::new(session); - let webtr_stream = - webtransport::accept_webtransport_stream(&arc_session).await?; - - let certs = certhashes.iter().cloned().collect::>(); - let t_noise = noise_config.with_webtransport_certhashes(certs); - t_noise.upgrade_inbound(webtr_stream, "").await?; - - let muxer = webtransport::Connection::new(arc_session, connection); - - return Ok((peer_id, StreamMuxerBox::new(muxer)));*/ - - // futures::ready!(incoming.poll_unpin(cx)) - // t_noise.upgrade_inbound().await?; - - // todo здесь же нужно будет делать нойз хэндшейк - Poll::Ready(Ok((peer_id, connection))) } } \ No newline at end of file diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs index ee13f03b202..96ad3c8996c 100644 --- a/transports/webtransport/src/lib.rs +++ b/transports/webtransport/src/lib.rs @@ -9,7 +9,7 @@ pub use transport::GenTransport; pub use connection::{Connecting, Connection}; pub use certificate::CertHash; use libp2p_core::transport::TransportError; -// pub(crate) use connection::Stream; +pub(crate) use connection::Stream; /// Errors that may happen on the [`GenTransport`] or a single [`Connection`]. #[derive(Debug, thiserror::Error)] @@ -26,6 +26,12 @@ pub enum Error { #[error("Unexpected HTTP endpoint of a libp2p WebTransport server {0}")] UnexpectedPath(String), + #[error(transparent)] + AuthenticationError(#[from] libp2p_noise::Error), + + #[error("Unknown remote peer ID")] + UnknownRemotePeerId, + /// The [`Connecting`] future timed out. #[error("Handshake with the remote timed out.")] HandshakeTimedOut, From 969cbc9346c1bcbcd8256bcabf21660d9f6f8c31 Mon Sep 17 00:00:00 2001 From: dgarus Date: Mon, 23 Dec 2024 10:48:37 +0300 Subject: [PATCH 06/16] connection --- transports/webtransport/src/connection.rs | 44 ++++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs index e3d78a8dc46..6698594ce54 100644 --- a/transports/webtransport/src/connection.rs +++ b/transports/webtransport/src/connection.rs @@ -1,8 +1,8 @@ use std::pin::Pin; use std::task::{Context, Poll}; -use futures::{FutureExt, ready}; use futures::future::BoxFuture; +use futures::{ready, FutureExt}; use wtransport::{error::ConnectionError, RecvStream, SendStream}; pub use connecting::Connecting; @@ -38,7 +38,10 @@ impl StreamMuxer for Connection { type Substream = Stream; type Error = Error; - fn poll_inbound(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_inbound( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.get_mut(); let incoming = this.incoming.get_or_insert_with(|| { @@ -52,15 +55,38 @@ impl StreamMuxer for Connection { Poll::Ready(Ok(stream)) } - fn poll_outbound(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - todo!() + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.get_mut(); + + let closing = this.closing.get_or_insert_with(|| { + this.connection.close(From::from(0u32), &[]); + let connection = this.connection.clone(); + async move { connection.closed().await }.boxed() + }); + + match ready!(closing.poll_unpin(cx)) { + // Expected error given that `connection.close` was called above. + ConnectionError::LocallyClosed => {} + error => return Poll::Ready(Err(Error::Connection(error))), + }; + + Poll::Ready(Ok(())) } - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - todo!() + fn poll_outbound( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + // Doesn't support outbound connections! + Poll::Pending } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - todo!() + fn poll( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + // TODO: If connection migration is enabled (currently disabled) address + // change on the connection needs to be handled. + Poll::Pending } -} \ No newline at end of file +} From 57c7dcfb836fbac0f35a7fc9da1166bfc77eb257 Mon Sep 17 00:00:00 2001 From: dgarus Date: Mon, 23 Dec 2024 10:52:09 +0300 Subject: [PATCH 07/16] applied fmt --- transports/webtransport/src/certificate.rs | 4 +- transports/webtransport/src/config.rs | 10 ++- .../webtransport/src/connection/connecting.rs | 36 ++++---- .../webtransport/src/connection/stream.rs | 22 +++-- transports/webtransport/src/lib.rs | 14 ++-- transports/webtransport/src/transport.rs | 83 ++++++++++--------- 6 files changed, 86 insertions(+), 83 deletions(-) diff --git a/transports/webtransport/src/certificate.rs b/transports/webtransport/src/certificate.rs index 4a2baa0e80f..a2f67ee8934 100644 --- a/transports/webtransport/src/certificate.rs +++ b/transports/webtransport/src/certificate.rs @@ -85,7 +85,7 @@ impl Certificate { MULTIHASH_SHA256_CODE, sha2::Sha256::digest(&self.cert.as_ref().as_ref()).as_ref(), ) - .expect("fingerprint's len to be 32 bytes") + .expect("fingerprint's len to be 32 bytes") } pub fn to_bytes(&self) -> Vec { @@ -166,4 +166,4 @@ mod tests { assert_eq!(actual, cert); } -} \ No newline at end of file +} diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs index 03a3e28b37b..615b66b482a 100644 --- a/transports/webtransport/src/config.rs +++ b/transports/webtransport/src/config.rs @@ -42,8 +42,11 @@ pub struct Config { impl Config { pub fn new(keypair: &libp2p_identity::Keypair, cert: Certificate) -> Self { let server_config: rustls::ServerConfig = libp2p_tls::make_webtransport_server_config( - &cert.cert, &cert.private_key, alpn_protocols(), - ).expect("A server config"); + &cert.cert, + &cert.private_key, + alpn_protocols(), + ) + .expect("A server config"); Self { server_tls_config: server_config, @@ -64,7 +67,6 @@ impl Config { } } - fn alpn_protocols() -> Vec> { vec![ b"libp2p".to_vec(), @@ -74,4 +76,4 @@ fn alpn_protocols() -> Vec> { b"h3-30".to_vec(), b"h3-29".to_vec(), ] -} \ No newline at end of file +} diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs index 1d2c8f2340d..ce8295f35b6 100644 --- a/transports/webtransport/src/connection/connecting.rs +++ b/transports/webtransport/src/connection/connecting.rs @@ -3,8 +3,8 @@ use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; -use futures::{FutureExt, ready}; -use futures::future::{BoxFuture, Either, Select, select}; +use futures::future::{select, BoxFuture, Either, Select}; +use futures::{ready, FutureExt}; use futures_timer::Delay; use wtransport::endpoint::IncomingSession; @@ -21,9 +21,10 @@ pub struct Connecting { } impl Connecting { - pub fn new(incoming_session: IncomingSession, - noise_config: libp2p_noise::Config, - timeout: Duration, + pub fn new( + incoming_session: IncomingSession, + noise_config: libp2p_noise::Config, + timeout: Duration, ) -> Self { Connecting { connecting: select( @@ -41,28 +42,23 @@ impl Connecting { Ok(session_request) => { let path = session_request.path(); if path != WEBTRANSPORT_PATH { - return Err( - Error::UnexpectedPath(String::from(path)) - ); + return Err(Error::UnexpectedPath(String::from(path))); } match session_request.accept().await { Ok(wtransport_connection) => { // The client SHOULD start the handshake right after sending the CONNECT request, // without waiting for the server's response. - let peer_id = Self::noise_auth(wtransport_connection.clone(), noise_config).await?; + let peer_id = + Self::noise_auth(wtransport_connection.clone(), noise_config).await?; let connection = Connection::new(wtransport_connection); Ok((peer_id, connection)) } - Err(connection_error) => { - Err(Error::Connection(connection_error)) - } + Err(connection_error) => Err(Error::Connection(connection_error)), } } - Err(connection_error) => { - Err(Error::Connection(connection_error)) - } + Err(connection_error) => Err(Error::Connection(connection_error)), } } @@ -70,12 +66,14 @@ impl Connecting { connection: wtransport::Connection, noise_config: libp2p_noise::Config, ) -> Result { - fn remote_peer_id(con: &wtransport::Connection,) -> PeerId { + fn remote_peer_id(con: &wtransport::Connection) -> PeerId { let cert_chain = con .peer_identity() .expect("connection got identity because it passed TLS handshake; qed"); - let cert = cert_chain.as_slice() - .first().expect("there should be exactly one certificate; qed"); + let cert = cert_chain + .as_slice() + .first() + .expect("there should be exactly one certificate; qed"); let p2p_cert = libp2p_tls::certificate::parse_binary(cert.der()) .expect("the certificate was validated during TLS handshake; qed"); @@ -108,4 +106,4 @@ impl Future for Connecting { Poll::Ready(Ok((peer_id, connection))) } -} \ No newline at end of file +} diff --git a/transports/webtransport/src/connection/stream.rs b/transports/webtransport/src/connection/stream.rs index 49ea4e3a661..a88a5f439d4 100644 --- a/transports/webtransport/src/connection/stream.rs +++ b/transports/webtransport/src/connection/stream.rs @@ -2,7 +2,7 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; -use wtransport::{SendStream, RecvStream}; +use wtransport::{RecvStream, SendStream}; /// A single stream on a connection pub struct Stream { @@ -38,21 +38,19 @@ impl futures::AsyncRead for Stream { let mut read_buf = ReadBuf::new(buf); let res = AsyncRead::poll_read(Pin::new(&mut self.recv), cx, &mut read_buf); match res { - Poll::Ready(Ok(_)) => { - Poll::Ready(Ok(read_buf.filled().len())) - } - Poll::Ready(Err(e)) => { - Poll::Ready(Err(e)) - } - Poll::Pending => { - Poll::Pending - } + Poll::Ready(Ok(_)) => Poll::Ready(Ok(read_buf.filled().len())), + Poll::Ready(Err(e)) => Poll::Ready(Err(e)), + Poll::Pending => Poll::Pending, } } } impl futures::AsyncWrite for Stream { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { AsyncWrite::poll_write(Pin::new(&mut self.send), cx, buf) } @@ -69,4 +67,4 @@ impl futures::AsyncWrite for Stream { self.close_result = Some(close_result.as_ref().map_err(|e| e.kind()).copied()); Poll::Ready(close_result) } -} \ No newline at end of file +} diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs index 96ad3c8996c..cf0359d5188 100644 --- a/transports/webtransport/src/lib.rs +++ b/transports/webtransport/src/lib.rs @@ -1,15 +1,15 @@ -mod transport; -mod connection; -mod config; mod certificate; +mod config; +mod connection; +mod transport; use wtransport::error::ConnectionError; -pub use transport::GenTransport; -pub use connection::{Connecting, Connection}; pub use certificate::CertHash; -use libp2p_core::transport::TransportError; pub(crate) use connection::Stream; +pub use connection::{Connecting, Connection}; +use libp2p_core::transport::TransportError; +pub use transport::GenTransport; /// Errors that may happen on the [`GenTransport`] or a single [`Connection`]. #[derive(Debug, thiserror::Error)] @@ -41,4 +41,4 @@ impl From for TransportError { fn from(value: Error) -> Self { TransportError::Other(value) } -} \ No newline at end of file +} diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 3acf01b8a63..64ceff4ba30 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -7,19 +7,19 @@ use std::sync::Arc; use std::task::{Context, Poll, Waker}; use std::time::Duration; -use futures::{prelude::*, stream::SelectAll}; use futures::future::BoxFuture; +use futures::{prelude::*, stream::SelectAll}; +use wtransport::endpoint::{endpoint_side::Server, Endpoint, IncomingSession}; use wtransport::{config::TlsServerConfig, ServerConfig}; -use wtransport::endpoint::{Endpoint, endpoint_side::Server, IncomingSession}; -use libp2p_core::{Multiaddr, multiaddr::Protocol, multihash::Multihash, Transport}; use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; +use libp2p_core::{multiaddr::Protocol, multihash::Multihash, Multiaddr, Transport}; use libp2p_identity::{Keypair, PeerId}; use crate::certificate::CertHash; use crate::config::Config; -use crate::Connecting; use crate::connection::Connection; +use crate::Connecting; use crate::Error; pub struct GenTransport { @@ -56,10 +56,7 @@ impl GenTransport { &self, addr: Multiaddr, check_unspecified_addr: bool, - ) -> Result< - (SocketAddr, Option), - TransportError<::Error>, - > { + ) -> Result<(SocketAddr, Option), TransportError<::Error>> { //todo rewrite: addr.clone() should be avoided. let (socket_addr, peer_id) = multiaddr_to_socketaddr(&addr) .ok_or_else(|| TransportError::MultiaddrNotSupported(addr.clone()))?; @@ -77,22 +74,24 @@ impl Transport for GenTransport { type ListenerUpgrade = Connecting; type Dial = Pending>; - fn listen_on(&mut self, id: ListenerId, addr: Multiaddr) -> Result<(), TransportError> { + fn listen_on( + &mut self, + id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError> { let (socket_addr, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; let config = ServerConfig::builder() .with_bind_address(socket_addr) .with_custom_tls(self.server_tls_config.clone()) .build(); - let endpoint = wtransport::Endpoint::server(config) - .map_err(|e| { TransportError::Other(e.into()) })?; + let endpoint = + wtransport::Endpoint::server(config).map_err(|e| TransportError::Other(e.into()))?; let keypair = &self.keypair; let cert_hashes = &self.cert_hashes; let handshake_timeout = self.handshake_timeout.clone(); - let listener = Listener::new( - id, endpoint, keypair, cert_hashes, handshake_timeout, - )?; + let listener = Listener::new(id, endpoint, keypair, cert_hashes, handshake_timeout)?; self.listeners.push(listener); if let Some(waker) = self.waker.take() { @@ -113,13 +112,18 @@ impl Transport for GenTransport { } } - fn dial(&mut self, _addr: Multiaddr, _opts: DialOpts) -> Result> { + fn dial( + &mut self, + _addr: Multiaddr, + _opts: DialOpts, + ) -> Result> { panic!("Dial operation is not supported!") } - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) - -> Poll> - { + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { if let Poll::Ready(Some(ev)) = self.listeners.poll_next_unpin(cx) { return Poll::Ready(ev); } @@ -165,21 +169,22 @@ impl Listener { endpoint: Endpoint, keypair: &Keypair, cert_hashes: &Vec, - handshake_timeout: Duration, ) -> Result { + handshake_timeout: Duration, + ) -> Result { let endpoint = Arc::new(endpoint); let c_endpoint = Arc::clone(&endpoint); let accept = async move { c_endpoint.accept().await }.boxed(); Ok(Listener { - listener_id, - endpoint, - accept, - handshake_timeout, - is_closed: false, - pending_event: None, - close_listener_waker: None, - keypair: keypair.clone(), - cert_hashes: cert_hashes.clone(), + listener_id, + endpoint, + accept, + handshake_timeout, + is_closed: false, + pending_event: None, + close_listener_waker: None, + keypair: keypair.clone(), + cert_hashes: cert_hashes.clone(), }) } @@ -256,7 +261,7 @@ impl Stream for Listener { if !waker.will_wake(cx.waker()) { self.close_listener_waker = Some(cx.waker().clone()) } - }, + } } return Poll::Pending; @@ -326,7 +331,9 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option<(SocketAddr, Option { - tracing::error!("Cannot listen on a specific certhash for WebTransport address {addr}"); + tracing::error!( + "Cannot listen on a specific certhash for WebTransport address {addr}" + ); return None; } _ => return None, @@ -339,14 +346,12 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option<(SocketAddr, Option Some(( - SocketAddr::new(ip.into(), port), - peer_id, - )), - (Protocol::Ip6(ip), Protocol::Udp(port)) => Some(( - SocketAddr::new(ip.into(), port), - peer_id, - )), + (Protocol::Ip4(ip), Protocol::Udp(port)) => { + Some((SocketAddr::new(ip.into(), port), peer_id)) + } + (Protocol::Ip6(ip), Protocol::Udp(port)) => { + Some((SocketAddr::new(ip.into(), port), peer_id)) + } _ => None, } } @@ -370,4 +375,4 @@ mod test { let mut transport = GenTransport::new(config); // todo write few tests: closing a listener, addresses parsing and so on } -} \ No newline at end of file +} From e0535d98324c478e546084aeda2c841b42b0b5d0 Mon Sep 17 00:00:00 2001 From: dgarus Date: Tue, 24 Dec 2024 10:52:39 +0300 Subject: [PATCH 08/16] multiaddr tests --- transports/webtransport/src/connection.rs | 1 + transports/webtransport/src/transport.rs | 149 +++++++++++++++++++++- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs index 6698594ce54..d7329552885 100644 --- a/transports/webtransport/src/connection.rs +++ b/transports/webtransport/src/connection.rs @@ -15,6 +15,7 @@ use crate::Error; mod connecting; mod stream; +/// State for a single opened Webtransport connection. pub struct Connection { /// Underlying connection. connection: wtransport::Connection, diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 64ceff4ba30..568f26510c4 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -315,7 +315,7 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option<(SocketAddr, Option Option<(SocketAddr, Option { + assert_eq!(listener_id, id); + assert!( + matches!(listen_addr.iter().next(), Some(Protocol::Ip4(a)) if !a.is_unspecified()) + ); + assert!( + matches!(listen_addr.iter().nth(1), Some(Protocol::Udp(port)) if port != 0) + ); + assert!(matches!(listen_addr.iter().nth(2), Some(Protocol::QuicV1))); + } + e => panic!("Unexpected event: {e:?}"), + } + assert!(transport.remove_listener(id), "Expect listener to exist."); + match poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)).await { + TransportEvent::ListenerClosed { + listener_id, + reason: Ok(()), + } => { + assert_eq!(listener_id, id); + } + e => panic!("Unexpected event: {e:?}"), + } + // Poll once again so that the listener has the chance to return `Poll::Ready(None)` and + // be removed from the list of listeners. + assert!(poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)) + .now_or_never() + .is_none()); + assert!(transport.listeners.is_empty()); + } + }*/ #[test] - fn test() { + fn socket_to_multiaddr() { + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345); let keypair = Keypair::generate_ed25519(); let not_before = OffsetDateTime::now_utc().checked_sub(1.days()).unwrap(); let cert = Certificate::generate(&keypair, not_before).expect("Generate certificate"); + let certs = vec![cert.cert_hash()]; - let config = Config::new(&keypair, cert); - let mut transport = GenTransport::new(config); - // todo write few tests: closing a listener, addresses parsing and so on + let mut res = socketaddr_to_multiaddr(&addr); + + res = add_hashes(res, &certs); + + assert!(multiaddr_to_socketaddr(&res.to_string().parse::().unwrap()).is_none()); + } + + #[test] + fn multiaddr_to_udp_conversion() { + assert!( + multiaddr_to_socketaddr(&"/ip4/127.0.0.1/udp/1234".parse::().unwrap()) + .is_none() + ); + + assert!(multiaddr_to_socketaddr( + &"/ip4/127.0.0.1/udp/1234/quic-v1" + .parse::() + .unwrap() + ) + .is_none()); + + assert_eq!( + multiaddr_to_socketaddr( + &"/ip4/127.0.0.1/udp/12345/quic-v1/webtransport" + .parse::() + .unwrap() + ), + Some(( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345), + None + )) + ); + assert_eq!( + multiaddr_to_socketaddr( + &"/ip4/255.255.255.255/udp/8080/quic-v1/webtransport" + .parse::() + .unwrap() + ), + Some(( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)), 8080), + None + )) + ); + assert_eq!( + multiaddr_to_socketaddr( + &"/ip4/127.0.0.1/udp/55148/quic-v1/webtransport/p2p/12D3KooW9xk7Zp1gejwfwNpfm6L9zH5NL4Bx5rm94LRYJJHJuARZ" + .parse::() + .unwrap() + ), + Some((SocketAddr::new( + IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 55148), + Some("12D3KooW9xk7Zp1gejwfwNpfm6L9zH5NL4Bx5rm94LRYJJHJuARZ".parse().unwrap()))) + ); + assert_eq!( + multiaddr_to_socketaddr( + &"/ip6/::1/udp/12345/quic-v1/webtransport" + .parse::() + .unwrap() + ), + Some(( + SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 12345), + None + )) + ); + assert_eq!( + multiaddr_to_socketaddr( + &"/ip6/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/udp/8080/quic-v1/webtransport" + .parse::() + .unwrap() + ), + Some(( + SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + )), + 8080, + ), + None + )) + ); } } From 427ae0c7e580791cb8e1bca651e8aa7e066ddb0a Mon Sep 17 00:00:00 2001 From: dgarus Date: Wed, 25 Dec 2024 16:19:58 +0300 Subject: [PATCH 09/16] close listener test --- Cargo.lock | 3 + transports/webtransport/Cargo.toml | 8 + transports/webtransport/src/certificate.rs | 2 +- transports/webtransport/src/connection.rs | 2 +- transports/webtransport/src/lib.rs | 6 +- transports/webtransport/src/transport.rs | 172 +++++++++++++++++++-- transports/webtransport/tests/smoke.rs | 45 ++++++ 7 files changed, 218 insertions(+), 20 deletions(-) create mode 100644 transports/webtransport/tests/smoke.rs diff --git a/Cargo.lock b/Cargo.lock index 4eb7e76f720..2705e4152b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3615,13 +3615,16 @@ dependencies = [ "libp2p-identity", "libp2p-noise", "libp2p-tls", + "quickcheck", "quinn", "rustls 0.23.20", "sha2 0.10.8", + "socket2", "thiserror 1.0.63", "time", "tokio", "tracing", + "tracing-subscriber", "wtransport", ] diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml index 1f3e90099e5..3d5bd72add5 100644 --- a/transports/webtransport/Cargo.toml +++ b/transports/webtransport/Cargo.toml @@ -21,8 +21,16 @@ rustls = { version = "0.23.9", default-features = false } thiserror = "1.0.61" time = "0.3.36" sha2 = "0.10.8" +socket2 = "0.5.7" quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } wtransport = "0.5.0" +[dev-dependencies] +libp2p-identity = { workspace = true, features = ["rand"] } +quickcheck = "1" +time = "0.3.36" +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } + [lints] workspace = true diff --git a/transports/webtransport/src/certificate.rs b/transports/webtransport/src/certificate.rs index a2f67ee8934..e219d329560 100644 --- a/transports/webtransport/src/certificate.rs +++ b/transports/webtransport/src/certificate.rs @@ -80,7 +80,7 @@ impl Certificate { }) } - pub(crate) fn cert_hash(&self) -> Multihash<64> { + pub(crate) fn cert_hash(&self) -> CertHash { Multihash::wrap( MULTIHASH_SHA256_CODE, sha2::Sha256::digest(&self.cert.as_ref().as_ref()).as_ref(), diff --git a/transports/webtransport/src/connection.rs b/transports/webtransport/src/connection.rs index d7329552885..9137902f63a 100644 --- a/transports/webtransport/src/connection.rs +++ b/transports/webtransport/src/connection.rs @@ -5,7 +5,7 @@ use futures::future::BoxFuture; use futures::{ready, FutureExt}; use wtransport::{error::ConnectionError, RecvStream, SendStream}; -pub use connecting::Connecting; +pub(crate) use connecting::Connecting; use libp2p_core::muxing::StreamMuxerEvent; use libp2p_core::StreamMuxer; diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs index cf0359d5188..97ec2a72e90 100644 --- a/transports/webtransport/src/lib.rs +++ b/transports/webtransport/src/lib.rs @@ -5,9 +5,9 @@ mod transport; use wtransport::error::ConnectionError; -pub use certificate::CertHash; -pub(crate) use connection::Stream; -pub use connection::{Connecting, Connection}; +pub use certificate::{CertHash, Certificate}; +pub use config::Config; +pub(crate) use connection::{Connecting, Connection, Stream}; use libp2p_core::transport::TransportError; pub use transport::GenTransport; diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 568f26510c4..a4a3430e888 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -1,20 +1,23 @@ use std::collections::HashSet; -use std::fmt; use std::future::Pending; -use std::net::SocketAddr; +use std::net::{IpAddr, SocketAddr, UdpSocket}; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll, Waker}; use std::time::Duration; +use std::{fmt, io}; use futures::future::BoxFuture; -use futures::{prelude::*, stream::SelectAll}; +use futures::{prelude::*, ready, stream::SelectAll}; +use if_watch::tokio::IfWatcher; +use if_watch::IfEvent; use wtransport::endpoint::{endpoint_side::Server, Endpoint, IncomingSession}; use wtransport::{config::TlsServerConfig, ServerConfig}; use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; -use libp2p_core::{multiaddr::Protocol, multihash::Multihash, Multiaddr, Transport}; +use libp2p_core::{multiaddr::Protocol, Multiaddr, Transport}; use libp2p_identity::{Keypair, PeerId}; +use socket2::{Domain, Socket, Type}; use crate::certificate::CertHash; use crate::config::Config; @@ -90,8 +93,16 @@ impl Transport for GenTransport { let keypair = &self.keypair; let cert_hashes = &self.cert_hashes; let handshake_timeout = self.handshake_timeout.clone(); + let socket = create_socket(socket_addr).map_err(Self::Error::from)?; - let listener = Listener::new(id, endpoint, keypair, cert_hashes, handshake_timeout)?; + let listener = Listener::new( + id, + socket, + endpoint, + keypair, + cert_hashes, + handshake_timeout, + )?; self.listeners.push(listener); if let Some(waker) = self.waker.take() { @@ -147,6 +158,9 @@ struct Listener { listener_id: ListenerId, /// Endpoint endpoint: Arc>, + /// Watcher for network interface changes. + /// None if we are only listening on a single interface. + if_watcher: Option, /// A future to poll new incoming connections. accept: BoxFuture<'static, IncomingSession>, /// Timeout for connection establishment on inbound connections. @@ -166,6 +180,7 @@ struct Listener { impl Listener { fn new( listener_id: ListenerId, + socket: UdpSocket, endpoint: Endpoint, keypair: &Keypair, cert_hashes: &Vec, @@ -175,13 +190,29 @@ impl Listener { let c_endpoint = Arc::clone(&endpoint); let accept = async move { c_endpoint.accept().await }.boxed(); + let if_watcher; + let pending_event; + let local_addr = socket.local_addr()?; + if local_addr.ip().is_unspecified() { + if_watcher = Some(IfWatcher::new()?); + pending_event = None; + } else { + if_watcher = None; + let ma = socketaddr_to_multiaddr(&local_addr); + pending_event = Some(TransportEvent::NewAddress { + listener_id, + listen_addr: ma, + }) + } + Ok(Listener { listener_id, endpoint, + if_watcher, accept, handshake_timeout, is_closed: false, - pending_event: None, + pending_event, close_listener_waker: None, keypair: keypair.clone(), cert_hashes: cert_hashes.clone(), @@ -220,6 +251,47 @@ impl Listener { res } + + fn poll_if_addr(&mut self, cx: &mut Context<'_>) -> Poll<::Item> { + let endpoint_addr = self.socket_addr(); + let Some(if_watcher) = self.if_watcher.as_mut() else { + return Poll::Pending; + }; + loop { + match ready!(if_watcher.poll_if_event(cx)) { + Ok(IfEvent::Up(inet)) => { + if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr()) { + tracing::debug!( + address=%listen_addr, + "New listen address" + ); + return Poll::Ready(TransportEvent::NewAddress { + listener_id: self.listener_id, + listen_addr, + }); + } + } + Ok(IfEvent::Down(inet)) => { + if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr()) { + tracing::debug!( + address=%listen_addr, + "Expired listen address" + ); + return Poll::Ready(TransportEvent::AddressExpired { + listener_id: self.listener_id, + listen_addr, + }); + } + } + Err(err) => { + return Poll::Ready(TransportEvent::ListenerError { + listener_id: self.listener_id, + error: err.into(), + }) + } + } + } + } } impl Stream for Listener { @@ -233,6 +305,9 @@ impl Stream for Listener { if self.is_closed { return Poll::Ready(None); } + if let Poll::Ready(event) = self.poll_if_addr(cx) { + return Poll::Ready(Some(event)); + } match self.accept.poll_unpin(cx) { Poll::Ready(incoming_session) => { @@ -252,6 +327,11 @@ impl Stream for Listener { }; return Poll::Ready(Some(event)); } + // todo + // Poll::Ready(None) => { + // self.close(Ok(())); + // continue; + // } Poll::Pending => {} }; @@ -280,6 +360,62 @@ impl fmt::Debug for Listener { } } +fn create_socket(socket_addr: SocketAddr) -> io::Result { + let socket = Socket::new( + Domain::for_address(socket_addr), + Type::DGRAM, + Some(socket2::Protocol::UDP), + )?; + if socket_addr.is_ipv6() { + socket.set_only_v6(true)?; + } + + socket.bind(&socket_addr.into())?; + + Ok(socket.into()) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) enum SocketFamily { + Ipv4, + Ipv6, +} + +impl SocketFamily { + fn is_same(a: &IpAddr, b: &IpAddr) -> bool { + matches!( + (a, b), + (IpAddr::V4(_), IpAddr::V4(_)) | (IpAddr::V6(_), IpAddr::V6(_)) + ) + } +} + +impl From for SocketFamily { + fn from(ip: IpAddr) -> Self { + match ip { + IpAddr::V4(_) => SocketFamily::Ipv4, + IpAddr::V6(_) => SocketFamily::Ipv6, + } + } +} + +/// Turn an [`IpAddr`] reported by the interface watcher into a +/// listen-address for the endpoint. +/// +/// For this, the `ip` is combined with the port that the endpoint +/// is actually bound. +/// +/// Returns `None` if the `ip` is not the same socket family as the +/// address that the endpoint is bound to. +fn ip_to_listen_addr(endpoint_addr: &SocketAddr, ip: IpAddr) -> Option { + // True if either both addresses are Ipv4 or both Ipv6. + if !SocketFamily::is_same(&endpoint_addr.ip(), &ip) { + return None; + } + let socket_addr = SocketAddr::new(ip, endpoint_addr.port()); + Some(socketaddr_to_multiaddr(&socket_addr)) +} + /// Turns an IP address and port into the corresponding WebTransport multiaddr. fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { Multiaddr::empty() @@ -289,7 +425,7 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { .with(Protocol::WebTransport) } -fn add_hashes(m_addr: Multiaddr, hashes: &Vec>) -> Multiaddr { +fn add_hashes(m_addr: Multiaddr, hashes: &Vec) -> Multiaddr { if !hashes.is_empty() { let mut vec = hashes.clone(); let mut res = m_addr.with(Protocol::Certhash( @@ -365,12 +501,17 @@ mod test { use time::ext::NumericalDuration; use time::OffsetDateTime; - /*#[tokio::test] - async fn test_close_listener() { + fn generate_keypair_and_cert() -> (Keypair, Certificate) { let keypair = Keypair::generate_ed25519(); let not_before = OffsetDateTime::now_utc().checked_sub(1.days()).unwrap(); let cert = Certificate::generate(&keypair, not_before).expect("Generate certificate"); + (keypair, cert) + } + + #[tokio::test] + async fn test_close_listener() { + let (keypair, cert) = generate_keypair_and_cert(); let config = Config::new(&keypair, cert); let mut transport = GenTransport::new(config); @@ -383,7 +524,10 @@ mod test { for _ in 0..2 { let id = ListenerId::next(); transport - .listen_on(id, "/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap()) + .listen_on( + id, + "/ip4/0.0.0.0/udp/0/quic-v1/webtransport".parse().unwrap(), + ) .unwrap(); match poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)).await { @@ -419,15 +563,13 @@ mod test { .is_none()); assert!(transport.listeners.is_empty()); } - }*/ + } #[test] fn socket_to_multiaddr() { - let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345); - let keypair = Keypair::generate_ed25519(); - let not_before = OffsetDateTime::now_utc().checked_sub(1.days()).unwrap(); - let cert = Certificate::generate(&keypair, not_before).expect("Generate certificate"); + let (_keypair, cert) = generate_keypair_and_cert(); let certs = vec![cert.cert_hash()]; + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345); let mut res = socketaddr_to_multiaddr(&addr); diff --git a/transports/webtransport/tests/smoke.rs b/transports/webtransport/tests/smoke.rs new file mode 100644 index 00000000000..d793af27ed2 --- /dev/null +++ b/transports/webtransport/tests/smoke.rs @@ -0,0 +1,45 @@ +use libp2p_identity::{Keypair, PeerId}; +use tracing_subscriber::EnvFilter; + +use futures::{ + channel::{mpsc, oneshot}, + future, + future::{poll_fn, BoxFuture, Either}, + stream::StreamExt, + AsyncReadExt, AsyncWriteExt, FutureExt, SinkExt, +}; + +use libp2p_core::muxing::StreamMuxerBox; +use libp2p_core::transport::Boxed; +use libp2p_webtransport as webtransport; +use time::ext::NumericalDuration; +use time::OffsetDateTime; + +#[tokio::test] +async fn smoke() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); +} + +fn create_transport() -> (PeerId, Boxed<(PeerId, StreamMuxerBox)>) { + let (keypair, cert) = generate_keypair_and_certificate(); + // let keypair = generate_tls_keypair(); + let peer_id = keypair.public().to_peer_id(); + let config = webtransport::Config::new(&keypair, cert); + // with_config(&mut config); + let transport = webtransport::GenTransport::new(config) + .map(|(p, c), _| (p, StreamMuxerBox::new(c))) + .boxed(); + + (peer_id, transport) +} + +fn generate_keypair_and_certificate() -> (Keypair, webtransport::Certificate) { + let keypair = Keypair::generate_ed25519(); + let not_before = OffsetDateTime::now_utc().checked_sub(1.days()).unwrap(); + let cert = + webtransport::Certificate::generate(&keypair, not_before).expect("Generate certificate"); + + (keypair, cert) +} From c8cb4bdfda262dc973a9e7b2181adea1cfbf94b2 Mon Sep 17 00:00:00 2001 From: dgarus Date: Wed, 25 Dec 2024 16:48:17 +0300 Subject: [PATCH 10/16] close listener test --- transports/webtransport/src/transport.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index a4a3430e888..aa17eabefba 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -327,7 +327,10 @@ impl Stream for Listener { }; return Poll::Ready(Some(event)); } - // todo + // todo See Endpoint::accept() implementation + // It just expects that "Endpoint cannot be closed", + // but it's an expected behavior that quic_incoming.accept() can return None. + // So it's not obvious how to handle this case. // Poll::Ready(None) => { // self.close(Ok(())); // continue; From 9f9a54dfe7ab5ea7a005adcb069c46de78e933e3 Mon Sep 17 00:00:00 2001 From: dgarus Date: Wed, 25 Dec 2024 17:19:49 +0300 Subject: [PATCH 11/16] fixed clippy --- Cargo.lock | 197 +++++++++++++++++++++----- transports/tls/src/lib.rs | 4 +- transports/webtransport/src/config.rs | 3 +- 3 files changed, 162 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 308c3c45e5c..1ca9a51e5a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -685,9 +685,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake2" @@ -1028,6 +1028,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1724,7 +1734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.11", + "rustls 0.23.20", "rustls-pki-types", ] @@ -2075,6 +2085,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "httlib-huffman" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877" + [[package]] name = "http" version = "0.2.9" @@ -2396,7 +2412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.3", "fnv", "futures", "if-addrs", @@ -3174,7 +3190,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.20", "socket2", "thiserror 2.0.3", "tokio", @@ -3377,11 +3393,12 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "libp2p-yamux", - "rcgen", + "rcgen 0.11.3", "ring 0.17.8", - "rustls 0.23.11", + "rustls 0.23.20", "rustls-webpki 0.101.7", "thiserror 2.0.3", + "time", "tokio", "x509-parser 0.16.0", "yasna", @@ -3428,7 +3445,7 @@ dependencies = [ "multihash", "quickcheck", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "stun 0.6.0", "thiserror 2.0.3", "tokio", @@ -3493,7 +3510,7 @@ dependencies = [ "libp2p-tcp", "parking_lot", "pin-project-lite", - "rcgen", + "rcgen 0.11.3", "rw-stream-sink", "soketto", "thiserror 2.0.3", @@ -3520,6 +3537,30 @@ dependencies = [ "web-sys", ] +[[package]] +name = "libp2p-webtransport" +version = "0.1.0" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "libp2p-tls", + "quickcheck", + "quinn", + "rustls 0.23.20", + "sha2 0.10.8", + "socket2", + "thiserror 1.0.63", + "time", + "tokio", + "tracing", + "tracing-subscriber", + "wtransport", +] + [[package]] name = "libp2p-webtransport-websys" version = "0.4.1" @@ -3871,7 +3912,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.9.2", "security-framework-sys", "tempfile", ] @@ -4045,6 +4086,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "octets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109983a091271ee8916076731ba5fdc9ee22fea871bc7c6ceab9bfd423eb1d99" + [[package]] name = "oid-registry" version = "0.6.1" @@ -4087,7 +4134,7 @@ version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -4339,11 +4386,11 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pem" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "serde", ] @@ -4655,7 +4702,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.20", "socket2", "thiserror 2.0.3", "tokio", @@ -4673,7 +4720,7 @@ dependencies = [ "rand 0.8.5", "ring 0.17.8", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.20", "rustls-pki-types", "slab", "thiserror 2.0.3", @@ -4782,7 +4829,7 @@ version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", ] [[package]] @@ -4818,6 +4865,19 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring 0.17.8", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redis" version = "0.24.0" @@ -5175,7 +5235,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -5203,40 +5263,51 @@ dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.1.0", +] + [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" dependencies = [ "web-time 1.1.0", ] @@ -5253,9 +5324,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -5366,7 +5437,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.3", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -5374,9 +5458,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -5858,7 +5942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.3", "system-configuration-sys 0.5.0", ] @@ -5868,8 +5952,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.4.1", - "core-foundation", + "bitflags 2.6.0", + "core-foundation 0.9.3", "system-configuration-sys 0.6.0", ] @@ -6260,7 +6344,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "bytes", "futures-util", "http 1.1.0", @@ -6805,7 +6889,7 @@ dependencies = [ "log", "pem", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "regex", "ring 0.16.20", "rtcp", @@ -6869,7 +6953,7 @@ dependencies = [ "pem", "rand 0.8.5", "rand_core 0.6.4", - "rcgen", + "rcgen 0.11.3", "ring 0.16.20", "rustls 0.21.11", "sec1", @@ -7322,6 +7406,43 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "wtransport" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a724f65db90b6a1ffa92ea4966cf03cb7e2bcd3ef7135b84dfe4339640d1b9" +dependencies = [ + "bytes", + "pem", + "quinn", + "rcgen 0.13.2", + "rustls 0.23.20", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "sha2 0.10.8", + "socket2", + "thiserror 1.0.63", + "time", + "tokio", + "tracing", + "url", + "wtransport-proto", + "x509-parser 0.16.0", +] + +[[package]] +name = "wtransport-proto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e4882c24a62f15024609b3688e6e29a4c2129634d27debc849ccd3f9b9690b" +dependencies = [ + "httlib-huffman", + "octets", + "thiserror 1.0.63", + "url", +] + [[package]] name = "x25519-dalek" version = "2.0.1" diff --git a/transports/tls/src/lib.rs b/transports/tls/src/lib.rs index 18d60379984..4ac50229e06 100644 --- a/transports/tls/src/lib.rs +++ b/transports/tls/src/lib.rs @@ -97,7 +97,7 @@ pub fn make_webtransport_server_config( certificate: &CertificateDer<'static>, private_key: &PrivateKeyDer, protocols: Vec>, -) -> Result { +) -> rustls::ServerConfig { let mut provider = rustls::crypto::ring::default_provider(); provider.cipher_suites = verifier::CIPHERSUITES.to_vec(); @@ -113,5 +113,5 @@ pub fn make_webtransport_server_config( .with_cert_resolver(cert_resolver); crypto.alpn_protocols = protocols.to_vec(); - Ok(crypto) + crypto } \ No newline at end of file diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs index 615b66b482a..e31b7f8feb1 100644 --- a/transports/webtransport/src/config.rs +++ b/transports/webtransport/src/config.rs @@ -45,8 +45,7 @@ impl Config { &cert.cert, &cert.private_key, alpn_protocols(), - ) - .expect("A server config"); + ); Self { server_tls_config: server_config, From 7b6719907f72913d583d03dccdd1158f9e077f4b Mon Sep 17 00:00:00 2001 From: dgarus Date: Thu, 26 Dec 2024 16:16:31 +0300 Subject: [PATCH 12/16] added hashes to a multiaddr --- transports/webtransport/src/transport.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index aa17eabefba..c2cc4da9971 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -198,7 +198,7 @@ impl Listener { pending_event = None; } else { if_watcher = None; - let ma = socketaddr_to_multiaddr(&local_addr); + let ma = socketaddr_to_multiaddr_with_hashes(&local_addr, &cert_hashes); pending_event = Some(TransportEvent::NewAddress { listener_id, listen_addr: ma, @@ -260,7 +260,7 @@ impl Listener { loop { match ready!(if_watcher.poll_if_event(cx)) { Ok(IfEvent::Up(inet)) => { - if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr()) { + if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) { tracing::debug!( address=%listen_addr, "New listen address" @@ -272,7 +272,7 @@ impl Listener { } } Ok(IfEvent::Down(inet)) => { - if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr()) { + if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) { tracing::debug!( address=%listen_addr, "Expired listen address" @@ -313,8 +313,7 @@ impl Stream for Listener { Poll::Ready(incoming_session) => { let endpoint = Arc::clone(&self.endpoint); self.accept = async move { endpoint.accept().await }.boxed(); - let mut local_addr = socketaddr_to_multiaddr(&self.socket_addr()); - local_addr = add_hashes(local_addr, &self.cert_hashes); + let local_addr = socketaddr_to_multiaddr_with_hashes(&self.socket_addr(), &self.cert_hashes); let remote_addr = incoming_session.remote_address(); let send_back_addr = socketaddr_to_multiaddr(&remote_addr); let noise = self.noise_config(); @@ -410,13 +409,13 @@ impl From for SocketFamily { /// /// Returns `None` if the `ip` is not the same socket family as the /// address that the endpoint is bound to. -fn ip_to_listen_addr(endpoint_addr: &SocketAddr, ip: IpAddr) -> Option { +fn ip_to_listen_addr(endpoint_addr: &SocketAddr, ip: IpAddr, hashes: &Vec) -> Option { // True if either both addresses are Ipv4 or both Ipv6. if !SocketFamily::is_same(&endpoint_addr.ip(), &ip) { return None; } let socket_addr = SocketAddr::new(ip, endpoint_addr.port()); - Some(socketaddr_to_multiaddr(&socket_addr)) + Some(socketaddr_to_multiaddr_with_hashes(&socket_addr, hashes)) } /// Turns an IP address and port into the corresponding WebTransport multiaddr. @@ -428,7 +427,9 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { .with(Protocol::WebTransport) } -fn add_hashes(m_addr: Multiaddr, hashes: &Vec) -> Multiaddr { +fn socketaddr_to_multiaddr_with_hashes(socket_addr: &SocketAddr, hashes: &Vec) -> Multiaddr { + let mut m_addr = socketaddr_to_multiaddr(socket_addr); + if !hashes.is_empty() { let mut vec = hashes.clone(); let mut res = m_addr.with(Protocol::Certhash( @@ -573,10 +574,7 @@ mod test { let (_keypair, cert) = generate_keypair_and_cert(); let certs = vec![cert.cert_hash()]; let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345); - - let mut res = socketaddr_to_multiaddr(&addr); - - res = add_hashes(res, &certs); + let res = socketaddr_to_multiaddr_with_hashes(&addr, &certs); assert!(multiaddr_to_socketaddr(&res.to_string().parse::().unwrap()).is_none()); } From 47b1159d403bef258842aa716b1464f3796a9575 Mon Sep 17 00:00:00 2001 From: dgarus Date: Sat, 28 Dec 2024 14:13:55 +0300 Subject: [PATCH 13/16] the first smoke test --- transports/webtransport/src/certificate.rs | 22 ++-- transports/webtransport/src/config.rs | 26 ++-- .../webtransport/src/connection/connecting.rs | 15 ++- transports/webtransport/src/transport.rs | 49 ++++---- transports/webtransport/tests/smoke.rs | 112 ++++++++++++++---- 5 files changed, 142 insertions(+), 82 deletions(-) diff --git a/transports/webtransport/src/certificate.rs b/transports/webtransport/src/certificate.rs index e219d329560..594ad4d294f 100644 --- a/transports/webtransport/src/certificate.rs +++ b/transports/webtransport/src/certificate.rs @@ -22,8 +22,8 @@ My suggestion would be: */ #[derive(Debug, PartialEq, Eq)] pub struct Certificate { - pub cert: CertificateDer<'static>, - pub private_key: PrivateKeyDer<'static>, + pub der: CertificateDer<'static>, + pub private_key_der: PrivateKeyDer<'static>, pub not_before: OffsetDateTime, pub not_after: OffsetDateTime, } @@ -49,8 +49,8 @@ impl From for Error { impl Clone for Certificate { fn clone(&self) -> Self { Self { - cert: self.cert.clone(), - private_key: self.private_key.clone_key(), + der: self.der.clone(), + private_key_der: self.private_key_der.clone_key(), not_before: self.not_before.clone(), not_after: self.not_after.clone(), } @@ -73,8 +73,8 @@ impl Certificate { )?; Ok(Self { - cert, - private_key, + der: cert, + private_key_der: private_key, not_before, not_after, }) @@ -83,7 +83,7 @@ impl Certificate { pub(crate) fn cert_hash(&self) -> CertHash { Multihash::wrap( MULTIHASH_SHA256_CODE, - sha2::Sha256::digest(&self.cert.as_ref().as_ref()).as_ref(), + sha2::Sha256::digest(&self.der.as_ref().as_ref()).as_ref(), ) .expect("fingerprint's len to be 32 bytes") } @@ -91,8 +91,8 @@ impl Certificate { pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); - Self::write_data(&mut bytes, self.cert.as_ref()).expect("Write cert data"); - Self::write_data(&mut bytes, self.private_key.secret_der()) + Self::write_data(&mut bytes, self.der.as_ref()).expect("Write cert data"); + Self::write_data(&mut bytes, self.private_key_der.secret_der()) .expect("Write private_key data"); let nb_buff = self.not_before.unix_timestamp().to_be_bytes(); @@ -117,8 +117,8 @@ impl Certificate { let not_after = OffsetDateTime::from_unix_timestamp(na).unwrap(); Ok(Self { - cert, - private_key, + der: cert, + private_key_der: private_key, not_before, not_after, }) diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs index e31b7f8feb1..b83334aae7c 100644 --- a/transports/webtransport/src/config.rs +++ b/transports/webtransport/src/config.rs @@ -32,23 +32,15 @@ pub struct Config { /// info. pub keep_alive_interval: Duration, - pub server_tls_config: TlsServerConfig, /// Libp2p identity of the node. pub keypair: libp2p_identity::Keypair, - cert_hash: CertHash, + cert: Certificate, } impl Config { pub fn new(keypair: &libp2p_identity::Keypair, cert: Certificate) -> Self { - let server_config: rustls::ServerConfig = libp2p_tls::make_webtransport_server_config( - &cert.cert, - &cert.private_key, - alpn_protocols(), - ); - Self { - server_tls_config: server_config, handshake_timeout: Duration::from_secs(5), max_idle_timeout: 10 * 1000, max_concurrent_stream_limit: 256, @@ -57,12 +49,20 @@ impl Config { // Ensure that one stream is not consuming the whole connection. max_stream_data: 10_000_000, keypair: keypair.clone(), - cert_hash: cert.cert_hash(), + cert, } } + pub fn server_tls_config(&self) -> TlsServerConfig { + libp2p_tls::make_webtransport_server_config( + &self.cert.der, + &self.cert.private_key_der, + alpn_protocols(), + ) + } + pub fn cert_hashes(&self) -> Vec { - vec![self.cert_hash.clone()] + vec![self.cert.cert_hash()] } } @@ -70,9 +70,5 @@ fn alpn_protocols() -> Vec> { vec![ b"libp2p".to_vec(), b"h3".to_vec(), - b"h3-32".to_vec(), - b"h3-31".to_vec(), - b"h3-30".to_vec(), - b"h3-29".to_vec(), ] } diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs index ce8295f35b6..8f86c4c54bf 100644 --- a/transports/webtransport/src/connection/connecting.rs +++ b/transports/webtransport/src/connection/connecting.rs @@ -36,23 +36,28 @@ impl Connecting { async fn handshake( incoming_session: IncomingSession, - noise_config: libp2p_noise::Config, + _noise_config: libp2p_noise::Config, ) -> Result<(PeerId, Connection), Error> { match incoming_session.await { Ok(session_request) => { + tracing::debug!("Got session request={:?}", session_request.path()); + let path = session_request.path(); if path != WEBTRANSPORT_PATH { return Err(Error::UnexpectedPath(String::from(path))); } - match session_request.accept().await { Ok(wtransport_connection) => { // The client SHOULD start the handshake right after sending the CONNECT request, // without waiting for the server's response. - let peer_id = - Self::noise_auth(wtransport_connection.clone(), noise_config).await?; - let connection = Connection::new(wtransport_connection); + let peer_id = PeerId::random(); + // todo a real noise auth + // let peer_id = + // Self::noise_auth(wtransport_connection.clone(), noise_config).await?; + + tracing::debug!("Accepted connection with sessionId={}", wtransport_connection.session_id()); + let connection = Connection::new(wtransport_connection); Ok((peer_id, connection)) } Err(connection_error) => Err(Error::Connection(connection_error)), diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index c2cc4da9971..11513d7cdc3 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -12,7 +12,7 @@ use futures::{prelude::*, ready, stream::SelectAll}; use if_watch::tokio::IfWatcher; use if_watch::IfEvent; use wtransport::endpoint::{endpoint_side::Server, Endpoint, IncomingSession}; -use wtransport::{config::TlsServerConfig, ServerConfig}; +use wtransport::ServerConfig; use libp2p_core::transport::{DialOpts, ListenerId, TransportError, TransportEvent}; use libp2p_core::{multiaddr::Protocol, Multiaddr, Transport}; @@ -26,11 +26,7 @@ use crate::Connecting; use crate::Error; pub struct GenTransport { - server_tls_config: TlsServerConfig, - keypair: Keypair, - cert_hashes: Vec, - /// Timeout for the [`Connecting`] future. - handshake_timeout: Duration, + config: Config, listeners: SelectAll, /// Waker to poll the transport again when a new listener is added. @@ -39,16 +35,8 @@ pub struct GenTransport { impl GenTransport { pub fn new(config: Config) -> Self { - let handshake_timeout = config.handshake_timeout; - let keypair = config.keypair.clone(); - let cert_hashes = config.cert_hashes(); - let server_tls_config = config.server_tls_config; - GenTransport { - server_tls_config, - keypair, - cert_hashes, - handshake_timeout, + config, listeners: SelectAll::new(), waker: None, } @@ -83,17 +71,22 @@ impl Transport for GenTransport { addr: Multiaddr, ) -> Result<(), TransportError> { let (socket_addr, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; + let socket = create_socket(socket_addr).map_err(Self::Error::from)?; + + let server_tls_config = self.config.server_tls_config(); + let config = ServerConfig::builder() - .with_bind_address(socket_addr) - .with_custom_tls(self.server_tls_config.clone()) + .with_bind_socket(socket.try_clone().unwrap()) + .with_custom_tls(server_tls_config) + //todo should be get from config + .keep_alive_interval(Some(Duration::from_secs(3))) .build(); let endpoint = wtransport::Endpoint::server(config).map_err(|e| TransportError::Other(e.into()))?; - let keypair = &self.keypair; - let cert_hashes = &self.cert_hashes; - let handshake_timeout = self.handshake_timeout.clone(); - let socket = create_socket(socket_addr).map_err(Self::Error::from)?; + let keypair = &self.config.keypair; + let cert_hashes = self.config.cert_hashes(); + let handshake_timeout = self.config.handshake_timeout.clone(); let listener = Listener::new( id, @@ -183,7 +176,7 @@ impl Listener { socket: UdpSocket, endpoint: Endpoint, keypair: &Keypair, - cert_hashes: &Vec, + cert_hashes: Vec, handshake_timeout: Duration, ) -> Result { let endpoint = Arc::new(endpoint); @@ -215,7 +208,7 @@ impl Listener { pending_event, close_listener_waker: None, keypair: keypair.clone(), - cert_hashes: cert_hashes.clone(), + cert_hashes, }) } @@ -428,11 +421,11 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { } fn socketaddr_to_multiaddr_with_hashes(socket_addr: &SocketAddr, hashes: &Vec) -> Multiaddr { - let mut m_addr = socketaddr_to_multiaddr(socket_addr); + let mut res = socketaddr_to_multiaddr(socket_addr); if !hashes.is_empty() { let mut vec = hashes.clone(); - let mut res = m_addr.with(Protocol::Certhash( + res = res.with(Protocol::Certhash( vec.pop().expect("Gets the last element"), )); if !vec.is_empty() { @@ -440,11 +433,9 @@ fn socketaddr_to_multiaddr_with_hashes(socket_addr: &SocketAddr, hashes: &Vec (PeerId, Boxed<(PeerId, StreamMuxerBox)>) { let (keypair, cert) = generate_keypair_and_certificate(); - // let keypair = generate_tls_keypair(); - let peer_id = keypair.public().to_peer_id(); let config = webtransport::Config::new(&keypair, cert); - // with_config(&mut config); - let transport = webtransport::GenTransport::new(config) + let mut transport = webtransport::GenTransport::new(config) .map(|(p, c), _| (p, StreamMuxerBox::new(c))) .boxed(); + let addr = start_listening(&mut transport, "/ip4/127.0.0.1/udp/0/quic-v1/webtransport").await; + let socket_addr = multiaddr_to_socketaddr(&addr).unwrap(); + + let a = + async move { + loop { + match &mut transport.next().await { + Some(TransportEvent::Incoming { listener_id, upgrade, .. }) => { + tracing::debug!("Got incoming event. listener_id={}", listener_id); + match upgrade.await { + Ok((peer_id, _mutex)) => { + tracing::debug!("Connection is opened. peer_id={}", peer_id); + return Some(peer_id) + }, + Err(e) => { + tracing::error!("Upgrade got an error {:?}", e); + return None; + } + } + } , + Some(e) => tracing::debug!("Got event {:?}", e), + e => { + tracing::error!("MY_TEST Got an error {:?}", e); + return None; + } + } + } + }; + + let url = format!("https://{}/.well-known/libp2p-webtransport?type=noise", socket_addr); + let b = async move { + let client_key_pair = Keypair::generate_ed25519(); + let client_tls= libp2p_tls::make_client_config(&client_key_pair, None).unwrap(); + let config = ClientConfig::builder() + .with_bind_default() + .with_custom_tls(client_tls) + .build(); + + match Endpoint::client(config) + .unwrap() + .connect(url.as_str()) + .await { + Ok(_) => {} + Err(_) => {} + } + }; + + matches!(join!(a, b), (Some(_id), ())); +} + +fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option { + let mut iter = addr.iter(); + let proto1 = iter.next()?; + let proto2 = iter.next()?; + + match (proto1, proto2) { + (Protocol::Ip4(ip), Protocol::Udp(port)) => { + Some(SocketAddr::new(ip.into(), port)) + } + (Protocol::Ip6(ip), Protocol::Udp(port)) => { + Some(SocketAddr::new(ip.into(), port)) + } + _ => None, + } +} - (peer_id, transport) +async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: &str) -> Multiaddr { + transport + .listen_on(ListenerId::next(), addr.parse().unwrap()) + .unwrap(); + match transport.next().await { + Some(TransportEvent::NewAddress { listen_addr, .. }) => listen_addr, + e => panic!("{e:?}"), + } } fn generate_keypair_and_certificate() -> (Keypair, webtransport::Certificate) { From 9a77699cd4fad62862bb5c87d501cfc4510f84b4 Mon Sep 17 00:00:00 2001 From: dgarus Date: Sat, 28 Dec 2024 14:14:46 +0300 Subject: [PATCH 14/16] the first smoke test --- transports/webtransport/src/config.rs | 5 +- .../webtransport/src/connection/connecting.rs | 5 +- transports/webtransport/src/transport.rs | 22 +++++-- transports/webtransport/tests/smoke.rs | 65 ++++++++++--------- 4 files changed, 56 insertions(+), 41 deletions(-) diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs index b83334aae7c..b55b84e86d6 100644 --- a/transports/webtransport/src/config.rs +++ b/transports/webtransport/src/config.rs @@ -67,8 +67,5 @@ impl Config { } fn alpn_protocols() -> Vec> { - vec![ - b"libp2p".to_vec(), - b"h3".to_vec(), - ] + vec![b"libp2p".to_vec(), b"h3".to_vec()] } diff --git a/transports/webtransport/src/connection/connecting.rs b/transports/webtransport/src/connection/connecting.rs index 8f86c4c54bf..8be3fb27f60 100644 --- a/transports/webtransport/src/connection/connecting.rs +++ b/transports/webtransport/src/connection/connecting.rs @@ -55,7 +55,10 @@ impl Connecting { // let peer_id = // Self::noise_auth(wtransport_connection.clone(), noise_config).await?; - tracing::debug!("Accepted connection with sessionId={}", wtransport_connection.session_id()); + tracing::debug!( + "Accepted connection with sessionId={}", + wtransport_connection.session_id() + ); let connection = Connection::new(wtransport_connection); Ok((peer_id, connection)) diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 11513d7cdc3..6617e36fb97 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -253,7 +253,9 @@ impl Listener { loop { match ready!(if_watcher.poll_if_event(cx)) { Ok(IfEvent::Up(inet)) => { - if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) { + if let Some(listen_addr) = + ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) + { tracing::debug!( address=%listen_addr, "New listen address" @@ -265,7 +267,9 @@ impl Listener { } } Ok(IfEvent::Down(inet)) => { - if let Some(listen_addr) = ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) { + if let Some(listen_addr) = + ip_to_listen_addr(&endpoint_addr, inet.addr(), &self.cert_hashes) + { tracing::debug!( address=%listen_addr, "Expired listen address" @@ -306,7 +310,8 @@ impl Stream for Listener { Poll::Ready(incoming_session) => { let endpoint = Arc::clone(&self.endpoint); self.accept = async move { endpoint.accept().await }.boxed(); - let local_addr = socketaddr_to_multiaddr_with_hashes(&self.socket_addr(), &self.cert_hashes); + let local_addr = + socketaddr_to_multiaddr_with_hashes(&self.socket_addr(), &self.cert_hashes); let remote_addr = incoming_session.remote_address(); let send_back_addr = socketaddr_to_multiaddr(&remote_addr); let noise = self.noise_config(); @@ -402,7 +407,11 @@ impl From for SocketFamily { /// /// Returns `None` if the `ip` is not the same socket family as the /// address that the endpoint is bound to. -fn ip_to_listen_addr(endpoint_addr: &SocketAddr, ip: IpAddr, hashes: &Vec) -> Option { +fn ip_to_listen_addr( + endpoint_addr: &SocketAddr, + ip: IpAddr, + hashes: &Vec, +) -> Option { // True if either both addresses are Ipv4 or both Ipv6. if !SocketFamily::is_same(&endpoint_addr.ip(), &ip) { return None; @@ -420,7 +429,10 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr) -> Multiaddr { .with(Protocol::WebTransport) } -fn socketaddr_to_multiaddr_with_hashes(socket_addr: &SocketAddr, hashes: &Vec) -> Multiaddr { +fn socketaddr_to_multiaddr_with_hashes( + socket_addr: &SocketAddr, + hashes: &Vec, +) -> Multiaddr { let mut res = socketaddr_to_multiaddr(socket_addr); if !hashes.is_empty() { diff --git a/transports/webtransport/tests/smoke.rs b/transports/webtransport/tests/smoke.rs index c27454f9bfb..69f96245f10 100644 --- a/transports/webtransport/tests/smoke.rs +++ b/transports/webtransport/tests/smoke.rs @@ -7,10 +7,10 @@ use time::OffsetDateTime; use wtransport::ClientConfig; use wtransport::Endpoint; -use libp2p_core::{Multiaddr, Transport}; use libp2p_core::multiaddr::Protocol; use libp2p_core::muxing::StreamMuxerBox; use libp2p_core::transport::{Boxed, ListenerId, TransportEvent}; +use libp2p_core::{Multiaddr, Transport}; use libp2p_identity::{Keypair, PeerId}; use libp2p_webtransport as webtransport; @@ -30,36 +30,42 @@ async fn smoke() { let addr = start_listening(&mut transport, "/ip4/127.0.0.1/udp/0/quic-v1/webtransport").await; let socket_addr = multiaddr_to_socketaddr(&addr).unwrap(); - let a = - async move { - loop { - match &mut transport.next().await { - Some(TransportEvent::Incoming { listener_id, upgrade, .. }) => { - tracing::debug!("Got incoming event. listener_id={}", listener_id); - match upgrade.await { - Ok((peer_id, _mutex)) => { - tracing::debug!("Connection is opened. peer_id={}", peer_id); - return Some(peer_id) - }, - Err(e) => { - tracing::error!("Upgrade got an error {:?}", e); - return None; - } + let a = async move { + loop { + match &mut transport.next().await { + Some(TransportEvent::Incoming { + listener_id, + upgrade, + .. + }) => { + tracing::debug!("Got incoming event. listener_id={}", listener_id); + match upgrade.await { + Ok((peer_id, _mutex)) => { + tracing::debug!("Connection is opened. peer_id={}", peer_id); + return Some(peer_id); + } + Err(e) => { + tracing::error!("Upgrade got an error {:?}", e); + return None; } - } , - Some(e) => tracing::debug!("Got event {:?}", e), - e => { - tracing::error!("MY_TEST Got an error {:?}", e); - return None; } } + Some(e) => tracing::debug!("Got event {:?}", e), + e => { + tracing::error!("MY_TEST Got an error {:?}", e); + return None; + } } - }; + } + }; - let url = format!("https://{}/.well-known/libp2p-webtransport?type=noise", socket_addr); + let url = format!( + "https://{}/.well-known/libp2p-webtransport?type=noise", + socket_addr + ); let b = async move { let client_key_pair = Keypair::generate_ed25519(); - let client_tls= libp2p_tls::make_client_config(&client_key_pair, None).unwrap(); + let client_tls = libp2p_tls::make_client_config(&client_key_pair, None).unwrap(); let config = ClientConfig::builder() .with_bind_default() .with_custom_tls(client_tls) @@ -68,7 +74,8 @@ async fn smoke() { match Endpoint::client(config) .unwrap() .connect(url.as_str()) - .await { + .await + { Ok(_) => {} Err(_) => {} } @@ -83,12 +90,8 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option { let proto2 = iter.next()?; match (proto1, proto2) { - (Protocol::Ip4(ip), Protocol::Udp(port)) => { - Some(SocketAddr::new(ip.into(), port)) - } - (Protocol::Ip6(ip), Protocol::Udp(port)) => { - Some(SocketAddr::new(ip.into(), port)) - } + (Protocol::Ip4(ip), Protocol::Udp(port)) => Some(SocketAddr::new(ip.into(), port)), + (Protocol::Ip6(ip), Protocol::Udp(port)) => Some(SocketAddr::new(ip.into(), port)), _ => None, } } From 9dc666472554e67d3a7afa40cda95e254e325b13 Mon Sep 17 00:00:00 2001 From: dgarus Date: Sat, 28 Dec 2024 15:29:13 +0300 Subject: [PATCH 15/16] using quic transport configuration --- Cargo.lock | 140 +++++++++++++++++++++-- transports/webtransport/Cargo.toml | 2 +- transports/webtransport/src/config.rs | 57 +++++---- transports/webtransport/src/transport.rs | 5 +- 4 files changed, 160 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6f00ab4c9f..774532cbcf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1020,6 +1020,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -2070,6 +2080,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "httlib-huffman" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877" + [[package]] name = "http" version = "0.2.12" @@ -2392,7 +2408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.4", "fnv", "futures", "if-addrs", @@ -3392,11 +3408,12 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "libp2p-yamux", - "rcgen", + "rcgen 0.11.3", "ring 0.17.8", "rustls 0.23.20", "rustls-webpki 0.101.7", "thiserror 2.0.9", + "time", "tokio", "x509-parser 0.16.0", "yasna", @@ -3444,7 +3461,7 @@ dependencies = [ "multihash", "quickcheck", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "stun 0.7.0", "thiserror 2.0.9", "tokio", @@ -3509,7 +3526,7 @@ dependencies = [ "libp2p-tcp", "parking_lot", "pin-project-lite", - "rcgen", + "rcgen 0.11.3", "rw-stream-sink", "soketto", "thiserror 2.0.9", @@ -3536,6 +3553,30 @@ dependencies = [ "web-sys", ] +[[package]] +name = "libp2p-webtransport" +version = "0.1.0" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "libp2p-tls", + "quickcheck", + "quinn", + "rustls 0.23.20", + "sha2 0.10.8", + "socket2", + "thiserror 1.0.69", + "time", + "tokio", + "tracing", + "tracing-subscriber", + "wtransport", +] + [[package]] name = "libp2p-webtransport-websys" version = "0.4.1" @@ -3888,7 +3929,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4060,6 +4101,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "octets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109983a091271ee8916076731ba5fdc9ee22fea871bc7c6ceab9bfd423eb1d99" + [[package]] name = "oid-registry" version = "0.6.1" @@ -4843,6 +4890,19 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring 0.17.8", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redis" version = "0.24.0" @@ -5239,6 +5299,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.1.0", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -5382,7 +5454,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -5878,7 +5963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6818,7 +6903,7 @@ dependencies = [ "log", "pem", "rand 0.8.5", - "rcgen", + "rcgen 0.11.3", "regex", "ring 0.16.20", "rtcp", @@ -6882,7 +6967,7 @@ dependencies = [ "pem", "rand 0.8.5", "rand_core 0.6.4", - "rcgen", + "rcgen 0.11.3", "ring 0.16.20", "rustls 0.21.12", "sec1", @@ -7365,6 +7450,43 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "wtransport" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a724f65db90b6a1ffa92ea4966cf03cb7e2bcd3ef7135b84dfe4339640d1b9" +dependencies = [ + "bytes", + "pem", + "quinn", + "rcgen 0.13.2", + "rustls 0.23.20", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "sha2 0.10.8", + "socket2", + "thiserror 1.0.69", + "time", + "tokio", + "tracing", + "url", + "wtransport-proto", + "x509-parser 0.16.0", +] + +[[package]] +name = "wtransport-proto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e4882c24a62f15024609b3688e6e29a4c2129634d27debc849ccd3f9b9690b" +dependencies = [ + "httlib-huffman", + "octets", + "thiserror 1.0.69", + "url", +] + [[package]] name = "x25519-dalek" version = "2.0.1" diff --git a/transports/webtransport/Cargo.toml b/transports/webtransport/Cargo.toml index 3d5bd72add5..75e78cdbb66 100644 --- a/transports/webtransport/Cargo.toml +++ b/transports/webtransport/Cargo.toml @@ -23,7 +23,7 @@ time = "0.3.36" sha2 = "0.10.8" socket2 = "0.5.7" quinn = { version = "0.11.2", default-features = false, features = ["rustls", "futures-io"] } -wtransport = "0.5.0" +wtransport = { version = "0.5.0", features = ["quinn"] } [dev-dependencies] libp2p-identity = { workspace = true, features = ["rand"] } diff --git a/transports/webtransport/src/config.rs b/transports/webtransport/src/config.rs index b55b84e86d6..ee54890d2fa 100644 --- a/transports/webtransport/src/config.rs +++ b/transports/webtransport/src/config.rs @@ -1,37 +1,15 @@ +use quinn::{TransportConfig, VarInt}; +use std::sync::Arc; use std::time::Duration; - use wtransport::config::TlsServerConfig; use crate::certificate::{CertHash, Certificate}; -#[derive(Clone)] pub struct Config { + pub quic_transport_config: Arc, /// Timeout for the initial handshake when establishing a connection. /// The actual timeout is the minimum of this and the [`Config::max_idle_timeout`]. pub handshake_timeout: Duration, - - /// Maximum duration of inactivity in ms to accept before timing out the connection. - pub max_idle_timeout: u32, - - /// Maximum number of incoming bidirectional streams that may be open - /// concurrently by the remote peer. - pub max_concurrent_stream_limit: u32, - - /// Max unacknowledged data in bytes that may be sent on a single stream. - pub max_stream_data: u32, - - /// Max unacknowledged data in bytes that may be sent in total on all streams - /// of a connection. - pub max_connection_data: u32, - - /// Period of inactivity before sending a keep-alive packet. - /// Must be set lower than the idle_timeout of both - /// peers to be effective. - /// - /// See [`quinn::TransportConfig::keep_alive_interval`] for more - /// info. - pub keep_alive_interval: Duration, - /// Libp2p identity of the node. pub keypair: libp2p_identity::Keypair, @@ -40,14 +18,31 @@ pub struct Config { impl Config { pub fn new(keypair: &libp2p_identity::Keypair, cert: Certificate) -> Self { + let max_idle_timeout = 10 * 1000; + let max_concurrent_stream_limit = 256; + let keep_alive_interval = Duration::from_secs(5); + let max_connection_data = 15_000_000; + // Ensure that one stream is not consuming the whole connection. + let max_stream_data = 10_000_000; + let mtu_discovery_config = Some(Default::default()); + + let mut transport = quinn::TransportConfig::default(); + // Disable uni-directional streams. + transport.max_concurrent_uni_streams(0u32.into()); + transport.max_concurrent_bidi_streams(max_concurrent_stream_limit.into()); + // Disable datagrams. + transport.datagram_receive_buffer_size(None); + transport.keep_alive_interval(Some(keep_alive_interval)); + transport.max_idle_timeout(Some(VarInt::from_u32(max_idle_timeout).into())); + transport.allow_spin(false); + transport.stream_receive_window(max_stream_data.into()); + transport.receive_window(max_connection_data.into()); + transport.mtu_discovery_config(mtu_discovery_config); + let transport = Arc::new(transport); + Self { + quic_transport_config: transport, handshake_timeout: Duration::from_secs(5), - max_idle_timeout: 10 * 1000, - max_concurrent_stream_limit: 256, - keep_alive_interval: Duration::from_secs(5), - max_connection_data: 15_000_000, - // Ensure that one stream is not consuming the whole connection. - max_stream_data: 10_000_000, keypair: keypair.clone(), cert, } diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 6617e36fb97..4767ed952a5 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -74,12 +74,11 @@ impl Transport for GenTransport { let socket = create_socket(socket_addr).map_err(Self::Error::from)?; let server_tls_config = self.config.server_tls_config(); + let quic_transport_config = Arc::clone(&self.config.quic_transport_config); let config = ServerConfig::builder() .with_bind_socket(socket.try_clone().unwrap()) - .with_custom_tls(server_tls_config) - //todo should be get from config - .keep_alive_interval(Some(Duration::from_secs(3))) + .with_custom_tls_and_transport(server_tls_config, quic_transport_config) .build(); let endpoint = From 21d242d787281473ae27cc9f4c182071fd9bc431 Mon Sep 17 00:00:00 2001 From: dgarus Date: Fri, 10 Jan 2025 11:00:29 +0300 Subject: [PATCH 16/16] dial operation is not allowed --- transports/webtransport/src/lib.rs | 5 ++++- transports/webtransport/src/transport.rs | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/transports/webtransport/src/lib.rs b/transports/webtransport/src/lib.rs index 97ec2a72e90..c322b6fb150 100644 --- a/transports/webtransport/src/lib.rs +++ b/transports/webtransport/src/lib.rs @@ -33,8 +33,11 @@ pub enum Error { UnknownRemotePeerId, /// The [`Connecting`] future timed out. - #[error("Handshake with the remote timed out.")] + #[error("Handshake with the remote timed out")] HandshakeTimedOut, + + #[error("Dial operation is not allowed on a libp2p WebTransport server")] + DialOperationIsNotAllowed, } impl From for TransportError { diff --git a/transports/webtransport/src/transport.rs b/transports/webtransport/src/transport.rs index 4767ed952a5..7b56bdbc626 100644 --- a/transports/webtransport/src/transport.rs +++ b/transports/webtransport/src/transport.rs @@ -120,7 +120,7 @@ impl Transport for GenTransport { _addr: Multiaddr, _opts: DialOpts, ) -> Result> { - panic!("Dial operation is not supported!") + Err(TransportError::Other(Error::DialOperationIsNotAllowed)) } fn poll( @@ -323,10 +323,9 @@ impl Stream for Listener { }; return Poll::Ready(Some(event)); } - // todo See Endpoint::accept() implementation - // It just expects that "Endpoint cannot be closed", - // but it's an expected behavior that quic_incoming.accept() can return None. - // So it's not obvious how to handle this case. + // todo Думаю, что нужно получать не IncomingSession, а + // todo Result с запросом на соединение. Тогда можно будет грамотно обработать ошибки + // todo и закрыть здесь листенер // Poll::Ready(None) => { // self.close(Ok(())); // continue;